From bc4ba3536a588e1799c6426a2ecd62149415242c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Feb 2025 18:35:53 +0800 Subject: [PATCH 001/156] =?UTF-8?q?fix:=20Modal=20=E6=94=AF=E6=8C=81iframe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/modal/src/composition/type.ts | 3 ++ .../components/modal/src/modal.component.tsx | 4 +-- .../components/modal/src/modal.props.ts | 4 ++- packages/ui-vue/demos/modal/modal-iframe.vue | 30 +++++++++++++++++++ .../ui-vue/docs/components/modal/index.md | 11 +++++++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 packages/ui-vue/demos/modal/modal-iframe.vue diff --git a/packages/ui-vue/components/modal/src/composition/type.ts b/packages/ui-vue/components/modal/src/composition/type.ts index e39156ec691..677b66761c0 100644 --- a/packages/ui-vue/components/modal/src/composition/type.ts +++ b/packages/ui-vue/components/modal/src/composition/type.ts @@ -28,6 +28,7 @@ export interface ModalOptions { fitContent?: boolean; buttons?: ModalButton[]; draggable?: boolean; + resizeable?: boolean; showMaxButton?: boolean; showCloseButton?: boolean; acceptCallback?: () => void; @@ -35,6 +36,8 @@ export interface ModalOptions { closedCallback?: ($event?: Event, from?: 'esc' | 'icon' | 'button') => void; resizeHandle?: (event: IResizeEvent) => void; enableEsc?: boolean; + dialogType?: string; + src?: string; } export interface ModalFunctions { diff --git a/packages/ui-vue/components/modal/src/modal.component.tsx b/packages/ui-vue/components/modal/src/modal.component.tsx index d8724b12f52..9ed03716fea 100644 --- a/packages/ui-vue/components/modal/src/modal.component.tsx +++ b/packages/ui-vue/components/modal/src/modal.component.tsx @@ -38,8 +38,8 @@ export default defineComponent({ const enableClose = ref(props.showCloseButton); const enableMaximize = ref(props.showMaxButton); const enableMinimize = ref(false); - const dialogType = ref(''); - const iframeSrc = ref(''); + const dialogType = ref(props.dialogType); + const iframeSrc = ref(props.src); const buttonAlignment = ref(''); const showButtons = ref(props.showButtons); const title = ref(props.title); diff --git a/packages/ui-vue/components/modal/src/modal.props.ts b/packages/ui-vue/components/modal/src/modal.props.ts index 19fa251526c..92220d4d093 100644 --- a/packages/ui-vue/components/modal/src/modal.props.ts +++ b/packages/ui-vue/components/modal/src/modal.props.ts @@ -77,7 +77,9 @@ export const modalProps = { acceptCallback: { type: Function, default: null}, rejectCallback: { type: Function, default: null}, enableEsc: { type: Boolean, default: true }, - enableEnter: { type: Boolean, default: false } + enableEnter: { type: Boolean, default: false }, + dialogType: { type: String, default: '' }, + src: { type: String, default: '' } }; export type ModalProps = Partial>; diff --git a/packages/ui-vue/demos/modal/modal-iframe.vue b/packages/ui-vue/demos/modal/modal-iframe.vue new file mode 100644 index 00000000000..ad4a65b0147 --- /dev/null +++ b/packages/ui-vue/demos/modal/modal-iframe.vue @@ -0,0 +1,30 @@ + + diff --git a/packages/ui-vue/docs/components/modal/index.md b/packages/ui-vue/docs/components/modal/index.md index bdd7d2fd4bd..980a994e8ca 100644 --- a/packages/ui-vue/docs/components/modal/index.md +++ b/packages/ui-vue/docs/components/modal/index.md @@ -52,6 +52,17 @@ Modal 组件用来已弹出模态窗口的形式展示页面内容。 ::: +## iframe + +:::vdemo + +```vue +{demos/modal/modal-iframe.vue} +``` + +::: + + ## 类型 ```typescript -- Gitee From 685e93c40a5cad0a16320c8473bd6c02c52a0e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 21 Feb 2025 10:47:32 +0800 Subject: [PATCH 002/156] =?UTF-8?q?feature:=20lookup=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=94=B6=E8=97=8F=E5=A4=B9=E3=80=81=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=B7=B2=E9=80=89=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../favorite/lookup-favorite.component.tsx | 95 +++++---- .../favorite/lookup-favorite.props.ts | 8 +- .../include-child-checkbox.component.tsx | 28 +++ .../components/lookup-container.component.tsx | 16 +- .../components/modal-container.component.tsx | 97 ++++++++-- .../src/components/modal-container.props.ts | 6 +- .../search-bar/search-bar.component.tsx | 9 +- .../lookup-selected-list.component.tsx | 181 ++++++++++++++++++ .../lookup-selected-list.props.ts | 8 + .../lookup/src/composition/types.ts | 2 +- .../lookup/src/composition/use-check-props.ts | 67 ++++--- .../lookup/src/composition/use-datagrid.tsx | 102 ++++++---- .../lookup/src/composition/use-dialog.ts | 116 +++++------ .../lookup/src/composition/use-favorite.tsx | 34 ++-- .../lookup/src/composition/use-http.ts | 95 +++++++-- .../src/composition/use-input-change.ts | 9 +- .../lookup/src/composition/use-load-data.ts | 26 +++ .../src/composition/use-lookup-callback.ts | 4 +- .../lookup/src/composition/use-navigation.tsx | 21 +- .../lookup/src/composition/use-pageinfo.ts | 4 +- .../lookup/src/composition/use-search-bar.tsx | 15 +- .../src/composition/use-search-fields.ts | 6 +- .../lookup/src/composition/use-selections.ts | 141 ++++++++++++++ .../lookup/src/composition/use-state.ts | 62 +++++- .../lookup/src/composition/use-sync-select.ts | 39 ++++ .../lookup/src/composition/use-treegrid.tsx | 67 ++++--- .../lookup/src/composition/use-user-data.ts | 29 +-- .../lookup/src/lookup.component.tsx | 67 +++++-- .../components/lookup/src/lookup.props.ts | 10 +- .../src/property-config/lookup-events.ts | 12 ++ .../property-config/lookup.property-config.ts | 115 ++++++++--- .../lookup/src/schema/lookup.schema.json | 40 ++++ .../modal/src/composition/modal.service.tsx | 11 +- .../components/modal/src/composition/type.ts | 1 + .../popover/src/composition/use-popup.ts | 6 +- .../popover/src/composition/use-position.ts | 29 ++- .../popover/src/popover.component.tsx | 10 +- .../popover/src/popover.directive.tsx | 24 ++- .../components/popover/src/popover.props.ts | 3 +- .../tree-grid/src/tree-grid.component.tsx | 8 +- packages/ui-vue/demos/lookup/basic.vue | 4 +- packages/ui-vue/demos/lookup/tree-list.vue | 4 +- packages/ui-vue/demos/modal/modal-service.vue | 5 +- 43 files changed, 1285 insertions(+), 351 deletions(-) create mode 100644 packages/ui-vue/components/lookup/src/components/include-child-checkbox/include-child-checkbox.component.tsx create mode 100644 packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx create mode 100644 packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.props.ts create mode 100644 packages/ui-vue/components/lookup/src/composition/use-load-data.ts create mode 100644 packages/ui-vue/components/lookup/src/composition/use-selections.ts create mode 100644 packages/ui-vue/components/lookup/src/composition/use-sync-select.ts create mode 100644 packages/ui-vue/components/lookup/src/property-config/lookup-events.ts diff --git a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx index 7f89e0d0daf..112f488bdc6 100644 --- a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx @@ -1,11 +1,15 @@ -import { defineComponent, inject, onMounted, ref, Ref, watch } from "vue"; +import { computed, defineComponent, inject, ref, Ref, watch } from "vue"; import { LOOKUP_USER_DATA_SERVICE, UserDataService } from "../../composition/use-user-data"; -import { FDataGrid } from "../../../../data-grid"; -import { FTreeGrid } from '../../../../tree-grid'; +import { VisualData } from "@farris/ui-vue/components/data-view"; +import { FDataGrid } from "@farris/ui-vue/components/data-grid"; +import { FTreeGrid } from '@farris/ui-vue/components/tree-grid'; import { lookupFavoriteComponentProps } from "./lookup-favorite.props"; import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "../../composition/types"; import { useFavorite } from "../../composition/use-favorite"; import { useCheckProps } from "../../composition/use-check-props"; +import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "../../composition/use-selections"; +import { useSyncSelect } from "../../composition/use-sync-select"; +import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../../composition/use-http"; export default defineComponent({ name: 'FLookupFavorite', @@ -13,32 +17,52 @@ export default defineComponent({ setup(props, context) { const {userDataState, getFavoriteData}: any = inject(LOOKUP_USER_DATA_SERVICE); const currentTab = inject>(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); - const { columns, favorite, removeFavoriteItem } = useFavorite(props); - const { isTreeList } = useCheckProps(props); + const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; + const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const { lookupStates} = useHttpComposition; + + const idField = computed(() => { + return lookupStates.lookupOptions.idField || 'id'; + }); + + const selectIds = ref(props.selectedIds); + + watch(() => props.selectedIds, (newValue) => { + selectIds.value = newValue; + }); + + const { setColumns, removeFavoriteItem } = useFavorite(props, idField.value); + const { isTreeList } = useCheckProps(props, lookupStates); + const { updateSelections, unSelectTreeNode, selectTreeNodes} = lookupSelectionsManager; const favoriteDataGridRef = ref(); const favoriteTreeGridRef = ref(); - watch(() => columns.value, (newColumns) => { - const gridRef = isTreeList() ? favoriteTreeGridRef : favoriteDataGridRef; - gridRef.value.updateColumns(newColumns); - // gridRef.value.updateDataSource(userDataState.favoriteItems || []); + const gridRef = computed(() => { + return isTreeList() ? favoriteTreeGridRef.value : favoriteDataGridRef.value; }); + + useSyncSelect(props, gridRef, lookupStates); + function hasFavorites() { return userDataState.data && userDataState.data.favorites && userDataState.data.favorites.length; } + function selectItem(itemIds: any) { + gridRef.value.clearSelection(); + if (itemIds && itemIds.length) { + gridRef.value.selectItemByIds(itemIds); + } + } + function loadFavoriteData(items: any, columns: any) { - const gridRef = isTreeList() ? favoriteTreeGridRef : favoriteDataGridRef; if (columns && columns.length) { - columns =columns.map(n => { - n.resizable = true; - return n; - }); - gridRef.value.updateColumns([...columns, favorite]); + setColumns(gridRef.value, columns); } items && gridRef.value.updateDataSource(items || []); + + selectItem(selectIds.value || []); } function queryFavoriteData() { @@ -51,7 +75,6 @@ export default defineComponent({ }); } - watch(() => currentTab.value, (newValue, oldValue) => { if (newValue === LookupTabs.favorite) { if (hasFavorites()) { @@ -59,14 +82,6 @@ export default defineComponent({ } else { loadFavoriteData([], null); } - // if ((!userDataState.favoriteItems || !userDataState.favoriteItems.length) || isTreeList()) { - // getFavoriteData().then((res: LookupHttpResult) => { - // loadFavoriteData(res.items || []); - // }); - // } - // else { - // loadFavoriteData(userDataState.favoriteItems || []); - // } } }); @@ -91,26 +106,37 @@ export default defineComponent({ enableSelectRow: true, multiSelect: props.multiSelect, showCheckbox: props.multiSelect, - multiSelectMode: 'DependOnCheck' + multiSelectMode: 'OnCheckAndClick' }; - function onSelectionChange() {} - - onMounted(() => { + function onSelectionChange(items: any[]) { + if (isTreeList()) { + selectTreeNodes(items); + } else { + updateSelections(items); + } + } - }); + function onUnSelectItem(item: VisualData) { + if (isTreeList()) { + unSelectTreeNode(item); + } else { + updateSelections(item?.raw, false); + } + } function renderTreeGrid() { return ; + onSelectionChange={onSelectionChange} + onUnSelectItem={onUnSelectItem}>; }; function renderDataGrid() { @@ -119,18 +145,19 @@ export default defineComponent({ pagination={{ enable: false}} summary={{ enable: false }} columnOption={columnOptions} - idField={props.idField} + idField={idField.value} rowNumber={{ enable: false }} showBorder={true} virtualized={true} fit={true} selection={selectionOption} - onSelectionChange={onSelectionChange}> + onSelectionChange={onSelectionChange} + onUnSelectItem={onUnSelectItem}> ; } return () => { - return isTreeList() ? renderTreeGrid() : renderDataGrid(); + return isTreeList()? renderTreeGrid() : renderDataGrid(); }; } }); diff --git a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.props.ts b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.props.ts index 4531cc24489..fbfe53a0c7f 100644 --- a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.props.ts +++ b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.props.ts @@ -2,7 +2,11 @@ import { ExtractPropTypes } from 'vue'; export const lookupFavoriteComponentProps = { multiSelect: { type: Boolean, default: false }, - idField: { type: String }, - displayType: {type: String, default: 'list'} + idField: { type: String, default: 'id' }, + displayType: {type: String, default: 'list'}, + selectedIds: { type: Array, default: []}, + showSelections: {type: Boolean, default: false}, + treeToList: {type: Boolean, default: false}, + enableFavorite: {type: Boolean, default: true} }; export type LookupFavoriteComponentProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/components/include-child-checkbox/include-child-checkbox.component.tsx b/packages/ui-vue/components/lookup/src/components/include-child-checkbox/include-child-checkbox.component.tsx new file mode 100644 index 00000000000..79efc440b9a --- /dev/null +++ b/packages/ui-vue/components/lookup/src/components/include-child-checkbox/include-child-checkbox.component.tsx @@ -0,0 +1,28 @@ +import { defineComponent, ref } from "vue"; + +export default defineComponent({ + props: { + modelValue: { + type: Boolean, + default: false + } + }, + emits: ['update:modelValue'], + setup(props, context) { + + const modelValue = ref(props.modelValue); + + function onClick($event: MouseEvent) { + $event.stopPropagation(); + modelValue.value = !modelValue.value; + context.emit('update:modelValue', modelValue.value); + } + + return () => { + return
+ + +
; + }; + } +}); diff --git a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx index a3523db960f..b57ddb68901 100644 --- a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx @@ -1,4 +1,4 @@ -import { defineComponent, ref, inject, watch, provide, onMounted, reactive, onUnmounted, Ref } from "vue"; +import { defineComponent, ref, inject, watch, onMounted, onUnmounted, Ref } from "vue"; import { FLayout, FLayoutPane } from "../../../../components/layout"; import { LookupProps, lookupProps } from "../lookup.props"; @@ -11,7 +11,6 @@ import { useCheckProps } from "../composition/use-check-props"; import { useNavigation } from "../composition/use-navigation"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../composition/use-http"; import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "../composition/types"; -import { lookupState, navigationState, queryState } from "../composition/use-state"; export default defineComponent({ name: "LookupContainer", @@ -22,11 +21,12 @@ export default defineComponent({ setup(props: LookupProps, context) { const currentTab = inject>(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const { lookupStates } = useHttpComposition; + const { lookupState, navigationState, queryState } = lookupStates; - const { renderSearchBar } = useSearchbar(props, false); - const { isDoubleList, getNavigationSize, isTreeList } = useCheckProps(props); + const { renderSearchBar } = useSearchbar(props, false, lookupStates); + const { isDoubleList, getNavigationSize, isTreeList } = useCheckProps(props, lookupStates); const { renderNavigation, selectedItems:navSelectedItems, getNavigationIdField, getRelationFilter } = useNavigation(props, context); - function getRenderDataComponent() { if (isTreeList()) { const { renderTreeGrid } = useTreegrid(props, context as any); @@ -106,10 +106,10 @@ export default defineComponent({ return () => { return ( - + {isDoubleList() && props.showNavigation && + {renderNavigation()} - + }
{renderSearchBar()} diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx index 1e7be13201c..f4d7041c6a1 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx @@ -1,9 +1,13 @@ -import { computed, defineComponent, inject, KeepAlive, onMounted, provide, ref, Transition } from "vue"; +import { computed, defineComponent, onMounted, provide, reactive, ref, watch } from "vue"; import { lookupModalContainerProps, LookupModalContainerProps } from "./modal-container.props"; -import { LOOKUP_ACTIVE_TAB, LookupTabs } from "../composition/types"; -import { LOOKUP_USER_DATA_SERVICE, useUserData } from "../composition/use-user-data"; +import { LOOKUP_ACTIVE_TAB, LookupDisplayType, LookupTabs } from "../composition/types"; +import { LOOKUP_USER_DATA_SERVICE } from "../composition/use-user-data"; import { LOOKUP_HTTP_COMPOSITION } from "../composition/use-http"; +import SelectedList from "./selected-list/lookup-selected-list.component"; +import { LOOKUP_SELECTIONS_MANAGER } from "../composition/use-selections"; +import LookupIncludeChildCheckbox from './include-child-checkbox/include-child-checkbox.component'; + export default defineComponent({ name: 'FLookupModalContainer', @@ -15,8 +19,34 @@ export default defineComponent({ provide(LOOKUP_ACTIVE_TAB, activeTab); provide(LOOKUP_HTTP_COMPOSITION, props.useHttpComposition); provide(LOOKUP_USER_DATA_SERVICE, props.userDataService); + provide(LOOKUP_SELECTIONS_MANAGER, props.selectionsManager); + + const includeChildNodesInfo = reactive(props.showIncludeChildNodes); + + const includeChildNodes = ref(includeChildNodesInfo.value); + + const { lookupOptions } = props.useHttpComposition.lookupStates; + + const showIncludeChildNodes = computed(() => { + return includeChildNodesInfo.show && activeTab.value === LookupTabs.dataList && lookupOptions.displayType && + lookupOptions.displayType.toUpperCase() === LookupDisplayType.TreeList; + }); + + const popoverOffsetX = computed(() => { + return showIncludeChildNodes.value? -99 : -15; + }); + + watch(() => includeChildNodes.value, (newValue, oldValue) => { + props.useHttpComposition.updateIncludeChilds(newValue); + }); + + const { userDataState } = props.userDataService; + + const { cancelDialog, submitDialog } = props.useDialog; - const { userDataState, getUserData } = props.userDataService; + const modalContainerRef = ref(); + + const selectedListRef = ref(); function onMaximizeModal($event) { context.emit('maximize', $event); @@ -26,6 +56,20 @@ export default defineComponent({ context.emit('closeModal', $event); } + async function onSubmitDialog($event) { + const result = await submitDialog(); + if (result) { + onCloseModal($event); + } + } + + async function onCancelDialog($event) { + const result = await cancelDialog(); + if (result) { + onCloseModal($event); + } + } + function onTabClick(tabName: string) { activeTab.value = tabName as LookupTabs; userDataState.data.tabIndex = tabName; @@ -39,23 +83,31 @@ export default defineComponent({ const showTabContentStyle = computed(() => { return (tabName) => { - return {display: activeTab.value === tabName ? 'block' : 'none!important'}; + return { + visibility: activeTab.value === tabName ? 'visible' : 'hidden', + position:'absolute', top: 0, + transition: 'all 0.3s ease-in', + opacity: activeTab.value === tabName ? 1 : 0 + }; }; }); + function onTabMousedown($event) { + $event.stopPropagation(); + document.body.click(); + } + onMounted(() => { - getUserData().then((res: any) => { - if (userDataState.data.favorites && userDataState.data.favorites.length) { - activeTab.value = userDataState.data?.tabIndex || LookupTabs.dataList; - } - }); + if (userDataState.data.favorites && userDataState.data.favorites.length) { + activeTab.value = userDataState.data?.tabIndex || LookupTabs.dataList; + } }); - return () =>
+ return () =>
{props.title}
{props.enableFavorite &&
-
event.stopPropagation()}> +
onTabClick(LookupTabs.dataList)}>数据列表
@@ -70,20 +122,23 @@ export default defineComponent({
-
- {/* -
- {activeTab.value === LookupTabs.dataList && context.slots.default && context.slots.default()} - {activeTab.value === LookupTabs.favorite && context.slots.fav && context.slots.fav()} -
-
*/} -
+
+
{context.slots.default && context.slots.default()}
-
+
{context.slots.fav && context.slots.fav()}
+
; } }); diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.props.ts b/packages/ui-vue/components/lookup/src/components/modal-container.props.ts index a0035c44368..9c993f679bb 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.props.ts +++ b/packages/ui-vue/components/lookup/src/components/modal-container.props.ts @@ -8,6 +8,10 @@ export const lookupModalContainerProps = { draggable: { type: Boolean, default: true }, enableFavorite: { type: Boolean, default: false }, useHttpComposition: { type: Object as PropType, default: {} }, - userDataService: { type: Object as PropType, default: {} } + userDataService: { type: Object as PropType, default: {} }, + useDialog: { type: Object, default: {} }, + selectionsManager: { type: Object, default: {} }, + showSelectedList: { type: Boolean, default: false}, + showIncludeChildNodes: { type: Object, default: { show: true, value: false}} }; export type LookupModalContainerProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx b/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx index ae4f0392d37..bae94525e58 100644 --- a/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx @@ -3,7 +3,7 @@ import { FButtonEdit } from "@farris/ui-vue/components/button-edit"; import { FComboList } from "../../../../combo-list"; import { searchBarProps, SearchBarProps } from "./search-bar.props"; import { SearchField } from "../../composition/types"; -import { queryState } from "../../composition/use-state"; +import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../../composition/use-http"; export default defineComponent({ @@ -11,6 +11,10 @@ export default defineComponent({ props: searchBarProps, emits: ["search"], setup(props: SearchBarProps, context) { + + const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const { queryState } = useHttpComposition.lookupStates; + const searchFields = ref(props.fields || []); const searchField = ref(''); const searchValue = ref(queryState.value); @@ -20,7 +24,8 @@ export default defineComponent({ const eventParams = computed(() => { return { field: searchField.value, - value: searchValue.value + value: searchValue.value, + isNavigation: isNavigation.value }; }); diff --git a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx new file mode 100644 index 00000000000..0280a9806e1 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx @@ -0,0 +1,181 @@ +import { computed, defineComponent, inject, onMounted, onUnmounted, ref, watch } from "vue"; +import { cloneDeep } from "lodash-es"; + +import FPopover from '@farris/ui-vue/components/popover'; +import { FDataGrid } from "@farris/ui-vue/components/data-grid"; +import { FMessageBoxService } from "@farris/ui-vue/components/message-box"; + +import { LookupSelectedListProps, lookupSelectedListProps } from "./lookup-selected-list.props"; +import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "../../composition/use-selections"; +import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../../composition/use-http"; + +export default defineComponent({ + props: lookupSelectedListProps, + setup(props: LookupSelectedListProps, context) { + + const messagerService: FMessageBoxService = inject('FMessageBoxService') as FMessageBoxService; + const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; + const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const { lookupState, selectionState } = useHttpComposition.lookupStates; + + const { clearSelections, unSelectionsByIds } = lookupSelectionsManager; + + const popoverRef = ref(); + const popoverInstance = computed(() => popoverRef); + const selectedGridRef = ref(); + const popoverOffsetX = ref(props.popoverOffsetX || -15); + + watch(() => props.popoverOffsetX, (offsetX) => { + popoverOffsetX.value = offsetX; + }); + + const popoverArrowOffsetX =computed(() => { + return popoverOffsetX.value === -15? 10: 100; + }); + + const modalElementRef = ref(props.parentRef); + + const removeSelectedFieldName = '_remove_selected_'; + + function onRemoveSelected($event: MouseEvent, row, cell) { + $event.stopPropagation(); + const rowId = row.raw[props.idField]; + unSelectionsByIds(rowId); + } + + const removeSelectedColumn = { + field: removeSelectedFieldName, title: '', width: 50, fixed: 'right', align: 'center', + formatter: (cell, row) => { + return ; + } + }; + + const gridColumns = computed(() => { + const newColumns = cloneDeep(lookupState?.columns || []); + if (newColumns.length) { + newColumns.push(removeSelectedColumn); + return newColumns; + } + }); + + watch(() => props.parentRef, (lookupModalRef) => { + modalElementRef.value = lookupModalRef; + }); + + watch(() => selectedGridRef.value, (gridInstance) => { + if (gridInstance) { + gridInstance.updateColumns(gridColumns.value); + gridInstance.updateDataSource(selectionState.value || []); + } + }); + + watch(() => selectionState.value, (selections) => { + selectedGridRef.value?.updateDataSource(selections || []); + }); + + const columnOptions= { + fitColumns: true, + fitMode: 'percentage', + resizeColumn: true + }; + + const selectionOption = { + enableSelectRow: true, + multiSelect: false, + showCheckbox: false, + showSelectAll: false, + multiSelectMode: 'OnCheckAndClick' + }; + + const selectedContainerStyle = ref({ + width: '0px', + height: '0px' + }); + + let resizeObserver; + function updateSelectedPanelSize() { + selectedContainerStyle.value = { + width: (modalElementRef.value?.offsetWidth - 20) + 'px', + height: (modalElementRef.value?.offsetHeight - 100) + 'px' + }; + } + + watch(() => modalElementRef.value, (modalElement) => { + resizeObserver = new ResizeObserver(() => { + if (modalElementRef.value) { + updateSelectedPanelSize(); + } + }); + resizeObserver.observe(modalElementRef.value); + }); + + const showClearButton = computed(() => { + return (selectionState.value || []).length > 0; + }); + + const selectedInfoStyle = computed(() => { + return { + display:"flex", + "align-items": "center", + opacity: showClearButton.value ? 1 : 0.4, + cursor: showClearButton.value ? 'pointer' : 'not-allowed', + pointerEvents: showClearButton.value ? 'auto' : 'none' + }; + }); + + function onClearSelections() { + messagerService?.question('您确认要取消所有选中记录吗?', '', () => { + clearSelections(); + }); + } + + onMounted(() => { + updateSelectedPanelSize(); + }); + + onUnmounted(() => { + if (resizeObserver && modalElementRef.value) { + resizeObserver.unobserve(modalElementRef.value); + } + }); + + function hidePopup() { + popoverInstance.value?.value.hide(); + } + + context.expose({ hidePopup }); + + return () => { + return (<> +
+
已选{selectionState.value.length}
+ {showClearButton.value && } +
+ + +
+ {popoverRef.value?.isShow && + + } +
+
+ + ); + }; + } +}); diff --git a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.props.ts b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.props.ts new file mode 100644 index 00000000000..9bb65765092 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.props.ts @@ -0,0 +1,8 @@ +import { ExtractPropTypes } from "vue"; + +export const lookupSelectedListProps = { + idField: { type: String, default: 'id' }, + parentRef: {type: HTMLElement, default: null}, + popoverOffsetX: { type: Number, default: 0} +}; +export type LookupSelectedListProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index da5fed7b4d6..8f06b80efdc 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -181,7 +181,7 @@ export interface TreeInfo { /** 数据加载方式: all, async */ loadDataType?: 'all' | 'async'; /** 分层方式: pathcode, parentId */ - layerType?: string; + layerType?: 'pathcode' | 'parentId'; /** 数据中带有分级信息的字段 */ dataField?: string; /** 父ID字段 */ diff --git a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts index 0bf3c4cb4b1..2ca03a15698 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts @@ -1,30 +1,31 @@ import { LookupProps } from "../lookup.props"; -import { LookupDisplayType, LookupPagination } from "./types"; +import { LookupDisplayType, LookupPagination, TreeInfo } from "./types"; +import { LookupStates } from "./use-state"; -export function useCheckProps(props: LookupProps) { - function checkPaination(paginationOptions?: Partial) { - const defaultPaginationOptions = { - enable: true, - sizeLimits: [10, 20, 30, 50, 100], - size: 20, - index: 1, - total: 0, - mode: 'server' - }; +export function useCheckProps(props: LookupProps, lookupStates: LookupStates) { + const { lookupOptions } = lookupStates; + + // 定义默认分页选项常量,避免重复创建对象 + const DEFAULT_PAGINATION_OPTIONS: LookupPagination = { + enable: true, + sizeLimits: [10, 20, 30, 50, 100], + size: 20, + index: 1, + total: 0, + mode: 'server' + }; - const mergedOptions = Object.assign({}, defaultPaginationOptions, paginationOptions); - return mergedOptions; + function checkPaination(paginationOptions?: Partial) { + return { ...DEFAULT_PAGINATION_OPTIONS, ...paginationOptions }; } function checkMultiSelect() { - const selectionOption = { + return { enableSelectRow: true, - multiSelect: props.multiSelect, - showCheckbox: props.multiSelect, + multiSelect: lookupOptions.multiSelect, + showCheckbox: lookupOptions.multiSelect, multiSelectMode: 'OnCheckAndClick' }; - - return selectionOption; } function checkColumnOptions() { @@ -36,27 +37,31 @@ export function useCheckProps(props: LookupProps) { } function isDoubleList() { - const isValid = typeof props.displayType === 'string' && props.displayType in LookupDisplayType; + const { displayType } = lookupStates.lookupOptions; + const isValid = typeof displayType === 'string' && displayType in LookupDisplayType; if (!isValid) { - return props.displayType.toLowerCase().indexOf('nav') === 0; + return displayType.toLowerCase().startsWith('nav'); } return false; } function isTreeList() { - return props.displayType.toLowerCase() === LookupDisplayType.Tree.toLowerCase() || - props.displayType.toLowerCase() === LookupDisplayType.ListTree.toLowerCase(); + const { displayType, treeToList } = lookupStates.lookupOptions; + return (displayType.toLowerCase() === LookupDisplayType.Tree.toLowerCase() || + displayType.toLowerCase() === LookupDisplayType.ListTree.toLowerCase()) && !treeToList; } function navIsTreeList() { - return props.displayType.toLowerCase() === LookupDisplayType.TreeList.toLowerCase(); + const { displayType, navTreeToList } = lookupStates.lookupOptions; + return displayType.toLowerCase() === LookupDisplayType.TreeList.toLowerCase() && !navTreeToList; } function navIsList() { - const currentDisplayType = props.displayType.toLowerCase(); + const { displayType, navTreeToList } = lookupStates.lookupOptions; + const currentDisplayType = displayType.toLowerCase(); return currentDisplayType === LookupDisplayType.ListList.toLowerCase() || - currentDisplayType === LookupDisplayType.ListTree.toLowerCase(); + currentDisplayType === LookupDisplayType.ListTree.toLowerCase() || navTreeToList; } function getNavigationSize() { @@ -74,5 +79,15 @@ export function useCheckProps(props: LookupProps) { }; } - return { checkPaination, checkMultiSelect, checkColumnOptions, isDoubleList, getNavigationSize, isTreeList, navIsTreeList, navIsList }; + function isLoadAll(treeInfo?: TreeInfo) { + return props.loadTreeDataType === 'all' || (props.loadTreeDataType === 'default' && treeInfo?.loadDataType === 'all'); + } + + function isPathCodeTree(treeInfo?: TreeInfo) { + return treeInfo?.layerType === "pathcode"; + } + + return { checkPaination, checkMultiSelect, checkColumnOptions, isDoubleList, getNavigationSize, isTreeList, navIsTreeList, navIsList, + isLoadAll, isPathCodeTree + }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx index 0ecf929f054..41ad6f44861 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx @@ -1,18 +1,33 @@ -import { ref, watch, SetupContext, Ref, computed, inject } from "vue"; -import { FDataGrid } from "../../../data-grid"; +import { ref, watch, SetupContext, computed, inject } from "vue"; + +import { FDataGrid } from "@farris/ui-vue/components/data-grid"; + import { useCheckProps } from "./use-check-props"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "./use-http"; import { usePageInfo } from "./use-pageinfo"; -import { LookupHttpResult } from "./types"; -import { lookupState, pageInfoState, searchState, selectionState } from "./use-state"; +import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "./types"; import { useFavorite } from "./use-favorite"; +import { useSyncSelect } from "./use-sync-select"; +import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "./use-selections"; +import { useLoadData } from "./use-load-data"; +import { LookupProps } from "../lookup.props"; +import { throttle } from "lodash-es"; + +export function useDatagrid(props: LookupProps, context: SetupContext, navigationInfo) { + const currentTab = inject(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); + const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; -export function useDatagrid(props: any, context: SetupContext, navigationInfo) { + const {lookupStates, loadData, includeChilds, getPathCode, getChildNodes } = useHttpComposition; + const { lookupState, navigationState, pageInfoState, searchState, lookupOptions} = lookupStates; - const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; - const { checkPaination, checkMultiSelect, checkColumnOptions } = useCheckProps(props); - const { updatePageInfo } = usePageInfo(props); + const { checkPaination, checkMultiSelect, checkColumnOptions, navIsTreeList, isLoadAll, isPathCodeTree } = useCheckProps(props, lookupStates); + const { updatePageInfo } = usePageInfo(props, pageInfoState); + + const { updateSelections } = lookupSelectionsManager; + + const { loadAdnSelect } = useLoadData(props, lookupStates); const paginationOptions = checkPaination(props.pagination); const selectionOptions = checkMultiSelect(); @@ -20,7 +35,6 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { const datagridRef = ref(); const selectionValues = ref([]); - const selectedItems = ref([]); const { navSelectedItems, getNavigationIdField, getRelationFilter } = navigationInfo; @@ -28,20 +42,14 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { const currentPaginationOptions = ref(pageInfoState.default); - const { loadData, idValues } = useHttpComposition; - const { favorite } = useFavorite(props); + const { setColumns } = useFavorite(props, lookupOptions.idField); watch(() => pageInfoState.default, (newPageInfo) => { currentPaginationOptions.value = newPageInfo; datagridRef.value?.updatePagination(newPageInfo); }); - function selectItems() { - const itemIds = selectedItems.value.map(item => item[props.idField]); - if (itemIds && itemIds.length) { - datagridRef.value?.selectItemByIds(itemIds); - } - } + useSyncSelect(props, datagridRef, useHttpComposition.lookupStates, currentTab); function dataGridLoadData(items: any, total: number, pageInfo: Record | undefined) { const value: any = {total}; @@ -50,30 +58,33 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { Object.assign(value, {index, size, enable, sizeLimits}); } updatePageInfo(value); - datagridRef.value?.updateDataSource(items || []); - selectItems(); - } - - function setDatagridColumns(columns: any[]) { - if (props.enableFavorite) { - columns.push(favorite); - } - datagridRef.value?.updateColumns(columns); + loadAdnSelect(datagridRef.value, items || []); } const relation = computed(() => { if(navSelectedItems.value && navSelectedItems.value.length) { - return {relationFilter: getRelationFilter(navSelectedItems.value)}; + let nodes = navSelectedItems.value; + if (navIsTreeList() && includeChilds.value) { + const treeInfo = navigationState.treeInfo as any; + if (isPathCodeTree(treeInfo)) { + return { navNodePathCode: getPathCode(nodes[0].data, treeInfo) }; + } else if (isLoadAll(treeInfo)) { + nodes = getChildNodes(nodes[0]); + return {relationFilter: getRelationFilter(nodes)}; + } + } + return {relationFilter: getRelationFilter(nodes)}; } return null; }); + watch([() => lookupState?.columns,() => lookupState?.items, () => lookupState?.pageInfo, () => lookupState?.total, () => lookupState?.selectedData ], ([newColumns, newItems, newPageInfo, newTotal, selectedData]) => { - newColumns && setDatagridColumns(newColumns); + newColumns && setColumns(datagridRef.value, newColumns); if (selectedData && selectedData.length) { - selectedItems.value = selectedData; + updateSelections(selectedData); } dataGridLoadData(newItems, newTotal || 0, newPageInfo); }); @@ -82,12 +93,12 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { selectionValues.value = newValue.split(props.separator); }); - watch(() => selectedItems.value, (newItems) => { - selectionState.value = newItems; - }); - function onSelectionChange(items: any[]) { - selectedItems.value = items; + updateSelections(items); + } + + function onUnSelectItem(items: any) { + updateSelections(items?.raw, false); } function httpRequest() { @@ -100,10 +111,15 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { }); } + // 优化 throttle 函数的使用,同时移除未使用的变量 + const throttledRequest = throttle(() => { + updatePageInfo({index: 1}); + httpRequest(); + }, 200); + watch(() => navSelectedItems.value, (navSelectedRows) => { if (props.uri) { - updatePageInfo({index: 1}); - httpRequest(); + throttledRequest(); return; } const navSelectIds = navSelectedRows.map(item => item[getNavigationIdField()]); @@ -112,13 +128,19 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { watch(() => searchState.default, (newSearchInfo) => { if (props.uri) { - updatePageInfo({index: 1}); - httpRequest(); + throttledRequest(); return; } context.emit('search', newSearchInfo); }); + watch(() => includeChilds.value, () => { + if (props.uri && navSelectedItems.value && navSelectedItems.value.length) { + throttledRequest(); + return; + } + }); + function onPageInfoChanged({pageSize, pageIndex}) { let index = pageIndex; if (currentPaginationOptions.value?.size !== pageSize) { @@ -139,7 +161,7 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { pagination={currentPaginationOptions.value} summary={{ enable: false }} columnOption={columnOptions} - idField={props.idField} + idField={lookupOptions.idField} rowNumber={{ enable: false }} showBorder={true} virtualized={true} @@ -147,6 +169,7 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { selection={selectionOptions} selectionValues={selectionValues.value} onSelectionChange={onSelectionChange} + onUnSelectItem={onUnSelectItem} onChanged={onPageInfoChanged} > ; @@ -154,7 +177,6 @@ export function useDatagrid(props: any, context: SetupContext, navigationInfo) { return { datagridRef, - selectedItems, selectionValues, renderDataGrid }; diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index e93a0fec117..fe676abdd44 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -1,8 +1,11 @@ import { inject, Ref, ref, SetupContext, watch } from "vue"; + +import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "@farris/ui-vue/components/notify"; + import { LookupProps } from "../lookup.props"; -import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../../../components/notify"; -import { queryState, lookupState, navigationState, pageInfoState, searchState, selectionState } from "./use-state"; import { useCheckProps } from "./use-check-props"; +import { UserDataService } from "./use-user-data"; +import { UseHttpComposition } from "./use-http"; /** 窗口关闭类型 */ enum CloseType { @@ -11,37 +14,42 @@ enum CloseType { esc = 'esc' }; +export interface UseDialogOptions { + dictPicked: (items: any) => Promise; + modelValue: Ref; + buttonEditInstance: Ref; + userDataService: UserDataService; + useHttp: UseHttpComposition +} export function useDialog( props: LookupProps, context: SetupContext, selectedItems: Ref, { - dictPicked, modelValue, buttonEditInstance, userDataService, idValue }: any) { + dictPicked, modelValue, buttonEditInstance, userDataService, useHttp }: UseDialogOptions) { const notifyService: FNotifyService | null = inject(F_NOTIFY_SERVICE_TOKEN, null); const loadingService: any | null = inject('FLoadingService'); const dialogOptions = ref(props.dialog); - const dialogSize = ref(); - const dialogCloseType = ref(CloseType.accept); - const customData = ref(); - const { isDoubleList } = useCheckProps(props); - + const { lookupStates } = useHttp; + const { queryState, lookupState, navigationState, pageInfoState, searchState, selectionState, lookupOptions } = lookupStates; + const { isDoubleList } = useCheckProps(props, lookupStates); async function updateModelValue() { const displayText = selectedItems.value.map((item: any) => { - return item[props.textField]; + return item[lookupOptions.textField]; }).join(props.separator); const idValues = selectedItems.value.map((item: any) => { - return item[props.idField]; + return item[lookupOptions.idField]; }).join(props.separator); modelValue.value = displayText; - idValue.value = idValues; + useHttp.idValues.value = idValues; context.emit('update:modelValue', displayText); context.emit('update:idValue', idValues); - const mappingInfo = { items: selectedItems.value, mappingFields: props.mappingFields }; + const mappingInfo = { items: selectedItems.value, mappingFields: lookupOptions.mappingFields }; context.emit('update:dataMapping', mappingInfo); if (props.context) { @@ -113,30 +121,6 @@ export function useDialog( } return false; } - async function beforeOpenDialog($event?: any) { - - let shouldContinue = true; - if (props.dictPicking && typeof props.dictPicking === 'function') { - const result = await props.dictPicking({ context: { customData } }); - if (typeof result === 'boolean' && !result) { - shouldContinue = false; - } - - if (typeof result === 'object') { - if (!result.showDialog) { - shouldContinue = false; - - if (result.message) { - notifyService?.error({ message: result.message, position: 'top-center' }); - } - } else if (result.data) { - customData.value = result.data; - } - } - } - - return shouldContinue; - } function getDefaultDialogSize() { const height = dialogOptions.value?.height || 620; @@ -198,24 +182,7 @@ export function useDialog( destroyed(); context.emit('dialogClosed', emitParams); }, - buttons: [ - { - name: 'cancel', - text: '取消', - class: 'btn btn-secondary', - handle: ($event: MouseEvent) => { - return cancelDialog(); - } - }, - { - name: 'accept', - text: '确定', - class: 'btn btn-primary', - handle: ($event: MouseEvent) => { - return submitDialog(); - } - } - ], + showButtons: false, resizeHandle: ($event: any) => { dialogSize.value = $event; const { width, height } = $event.newSize.size; @@ -241,11 +208,50 @@ export function useDialog( } }; + async function beforeOpenDialog($event?: any) { + + let shouldContinue = true; + await userDataService.getUserData(); + + if (userDataService?.userDataState?.data) { + const { size } = userDataService.userDataState.data; + if (size) { + Object.assign(modalOptions, size); + } + } + + const beforeEvent = props.dictPicking; + + if (beforeEvent && typeof beforeEvent === 'function') { + const result = await beforeEvent({ customData, options: lookupOptions }); + if (typeof result === 'boolean' && !result) { + shouldContinue = false; + } + + if (typeof result === 'object') { + if (!result.showDialog) { + shouldContinue = false; + + if (result.message) { + notifyService?.error({ message: result.message, position: 'top-center' }); + } + } else if (result.data) { + customData.value = result.data; + } + } + } + + return shouldContinue; + } + + return { modalOptions, beforeOpenDialog, dialogSize, customData, - updateModelValue + updateModelValue, + cancelDialog, + submitDialog }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx index 1377c1b637d..9b632400a87 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx @@ -1,16 +1,16 @@ import { computed, inject, ref, watch } from "vue"; -import { LOOKUP_USER_DATA_SERVICE, UserDataService } from "./use-user-data"; -import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../../notify"; -import { lookupState } from "./use-state"; import { cloneDeep } from "lodash-es"; -export function useFavorite(props: any) { +import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "@farris/ui-vue/components/notify"; + +import { LOOKUP_USER_DATA_SERVICE, UserDataService } from "./use-user-data"; +import { LookupProps } from "../lookup.props"; + +export function useFavorite(props: LookupProps, idField: string) { const notifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; const userDataService = inject(LOOKUP_USER_DATA_SERVICE) as UserDataService; const { userDataState } = userDataService; - const columns = ref(); - userDataState.data = userDataState.data || {}; const favoriteFieldName = '_favorite_'; @@ -32,7 +32,7 @@ export function useFavorite(props: any) { } else { removeFavoriteItem.value = true; userDataState.data.favorites = userDataState.data.favorites.filter(id => id !== itemId); - userDataState.favoriteItems = userDataState.favoriteItems.filter(item => item[props.idField] !== itemId); + userDataState.favoriteItems = userDataState.favoriteItems.filter(item => item[idField] !== itemId); } userDataService?.saveUserData().then((res) => { @@ -43,7 +43,7 @@ export function useFavorite(props: any) { } function getRowId(row) { - return row ? row.raw[props.idField] : ''; + return row ? row.raw[idField] : ''; } const isFavorite = computed(() => { @@ -60,21 +60,25 @@ export function useFavorite(props: any) { } const favoriteColumn = { - field: favoriteFieldName, title: '', width: '50px', fixed: 'right', align: 'center', + field: favoriteFieldName, title: '', width: 50, fixed: 'right', align: 'center', formatter: (cell, row) => { return ; } }; - watch(() => lookupState?.columns, (newColumns) => { - columns.value = cloneDeep([...newColumns ||[]]); - }); + function setColumns(gridInstance: any, columns: any) { + const newColumns = cloneDeep(columns); + if (props.enableFavorite) { + newColumns.push(favoriteColumn); + } + gridInstance?.updateColumns(newColumns); + } return { favorite: favoriteColumn, - columns, - removeFavoriteItem + removeFavoriteItem, + setColumns }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 8e29f451635..3fe5189b6c1 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -1,31 +1,49 @@ import { inject, Ref, ref, toRaw } from "vue"; +import { flatten } from "lodash-es"; + +import { FLoadingService } from "@farris/ui-vue/components/loading"; +import { resolveField as getFieldValue } from '@farris/ui-vue/components/common'; + + import { Compare, FilterRelation, LOAD_DATA_TYPE, F_LOOKUP_HTTP_SERVICE_TOKEN, - LookupHttpResult, LookupHttpService, LookupRequestParams, SearchParam + LookupHttpResult, LookupHttpService, LookupRequestParams, SearchParam, + TreeInfo } from "./types"; -import { FLoadingService } from "@farris/ui-vue/components/loading"; -import { flatten } from "lodash-es"; import { useSearchFields } from "./use-search-fields"; -import { pageInfoState } from "./use-state"; +import { LookupStates, useLookupState } from "./use-state"; import { customData } from "./use-customdata"; +import { LookupProps } from "../lookup.props"; export const LOOKUP_HTTP_COMPOSITION = 'F_LOOKUP_HTTP_COMPOSITION_TOKEN'; export interface UseHttpComposition { + includeChilds: Ref; + updateIncludeChilds: (checked: boolean) => void; idValues: Ref; loadData: (event: any, callback: (data: LookupHttpResult) => void) => void; getData: (params: any) => Promise; updateSearchFieldTitle: (searchFields: any[], columns: any[]) => any[]; + getPathCode: (data: any, treeInfo: TreeInfo) => string; + getChildNodes: (node: any) => Array; + lookupStates: LookupStates; + httpService?: LookupHttpService; + lookupRequest: () => (uri, params) => Promise; } -export function useHttp(props: any, context: any): UseHttpComposition { +export function useHttp(props: LookupProps, context: any): UseHttpComposition { const loadingService: any | null = inject('FLoadingService'); const httpService = inject(F_LOOKUP_HTTP_SERVICE_TOKEN); + const lookupStates = useLookupState(props); + const { pageInfoState, lookupState, navigationState, lookupOptions } = lookupStates; - const { searchFieldItems } = useSearchFields(props); + const { searchFieldItems, navSearchFieldItems } = useSearchFields(props, lookupState, navigationState); const uri = ref(props.uri); const idValues = ref(props.idValue); - function buildConditionsWhenSearchAnyFields(searchFields: any[], searchValues: string, isNavSearch = false): any[] { + + const includeChilds = ref(false); + + function buildConditionsWhenSearchAnyFields(searchFields: any[], searchValues: string): any[] { // 处理空值或只包含空格的情况 if (searchValues == null || !searchValues.trim()) { return []; @@ -95,7 +113,8 @@ export function useHttp(props: any, context: any): UseHttpComposition { } if (!props.enableMultiFieldSearch && searchParam.searchField === '*') { - const conditions = buildConditionsWhenSearchAnyFields(searchFieldItems.value, value, isNavigation); + const searchFields = isNavigation? navSearchFieldItems.value: searchFieldItems.value; + const conditions = buildConditionsWhenSearchAnyFields(searchFields, value); if (conditions && conditions.length) { if (isNavigation) { navSearchConditions = conditions; @@ -163,6 +182,10 @@ export function useHttp(props: any, context: any): UseHttpComposition { queryParams.relationFilter = [...event.relationFilter]; } + if (event?.navNodePathCode) { + queryParams.navPathCode = event.navNodePathCode; + } + if (event.selectedInfo) { queryParams.selectedInfo = event.selectedInfo; } @@ -205,10 +228,15 @@ export function useHttp(props: any, context: any): UseHttpComposition { } } + function lookupRequest() { + const loader = lookupOptions.loader || (httpService && httpService.getData.bind(httpService)); + return loader; + } + function getData(params: LookupRequestParams): Promise { - // console.log('LOOKUP request Params:', params); - if (uri.value && httpService) { - return httpService.getData(uri.value, params).then(res => { + const loader = lookupRequest(); + if (uri.value && loader) { + return loader(uri.value, params).then(res => { initColumnsInfo(res); return res; }); @@ -226,17 +254,56 @@ export function useHttp(props: any, context: any): UseHttpComposition { function loadData(event: any, callback: (e: LookupHttpResult) => void) { const params = buildQueryParams(event) as Partial; - loadingService?.show(); + const loadingInstance = loadingService?.show(); getData(params).then((req: Partial) => { - loadingService?.clearAll(); + // loadingService?.clearAll(); + loadingInstance.value?.close(); callback(req); }); } + function updateIncludeChilds(checked: boolean) { + includeChilds.value = checked; + } + + function getPathCode(data: any, treeInfo: TreeInfo) { + const { dataField, pathField } = treeInfo ; + if (pathField) { + if (dataField) { + return data[dataField][pathField]; + } else { + return getFieldValue(data, pathField); + } + } + + return ''; + } + + function getChildNodes(node: any) { + const nodes: any = []; + if (node.selectable || node.selectable === undefined) { + nodes.push(node); + } + if (node.children && node.children.length) { + node.children.forEach(item => { + nodes.push(...getChildNodes(item)); + }); + } + + return nodes; + } + return { + includeChilds, + updateIncludeChilds, idValues, getData, loadData, - updateSearchFieldTitle + updateSearchFieldTitle, + getPathCode, + getChildNodes, + lookupStates, + httpService, + lookupRequest }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts index 74dac1fee55..fdf2f6f1206 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts @@ -1,8 +1,9 @@ +import { computed, Ref } from "vue"; import { isEmpty } from "lodash-es"; -import { computed, Ref, ref, watch } from "vue"; + import { UseHttpComposition } from "./use-http"; import { BeforeOpenDialogFunction, LookupHttpResult } from "./types"; -import { lookupState, queryState } from './use-state'; +import { LookupProps } from "../lookup.props"; export type LookupInputChangeOptions = { updateModelValue: () => void; @@ -13,13 +14,13 @@ export type LookupInputChangeOptions = { useHttpComposition: UseHttpComposition; }; -export function useInputChange(props: any, context: any, options: LookupInputChangeOptions) { +export function useInputChange(props: LookupProps, context: any, options: LookupInputChangeOptions) { const changeOnBlur = computed(() => props.textChangeType === 'blur' || props.textChangeType === 'any'); const changeOnEnter = computed(() => props.textChangeType === 'enter' || props.textChangeType === 'any'); const {beforeOpenDialog, updateModelValue, selectedItems, openDialog, modelValue, useHttpComposition} = options; const {updateSearchFieldTitle} = useHttpComposition; - + const { lookupState, queryState } = useHttpComposition.lookupStates; function isTextChange(text: string) { if (isEmpty(text)) { return false; diff --git a/packages/ui-vue/components/lookup/src/composition/use-load-data.ts b/packages/ui-vue/components/lookup/src/composition/use-load-data.ts new file mode 100644 index 00000000000..95329769573 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/composition/use-load-data.ts @@ -0,0 +1,26 @@ +import { LookupProps } from "../lookup.props"; +import { useSelections } from "./use-selections"; +import { LookupStates } from "./use-state"; + +export function useLoadData(props: LookupProps, lookupStates: LookupStates) { + + const { getSelectionIds } = useSelections(props, lookupStates); + + function loadData(gridRef: any, data: any) { + gridRef?.updateDataSource(data || []); + } + + function selectItemByIds(gridRef: any) { + const itemIds = getSelectionIds(); + if (itemIds && itemIds.length) { + gridRef?.selectItemByIds(itemIds); + } + } + + function loadAdnSelect(gridRef: any, items: any) { + loadData(gridRef, items); + selectItemByIds(gridRef); + } + + return { loadData, selectItemByIds, loadAdnSelect }; +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-lookup-callback.ts b/packages/ui-vue/components/lookup/src/composition/use-lookup-callback.ts index 8eb0bbae628..303827075d1 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-lookup-callback.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-lookup-callback.ts @@ -1,4 +1,6 @@ -export function useLookupCallBack(props: any) { +import { LookupProps } from "../lookup.props"; + +export function useLookupCallBack(props: LookupProps) { const {mapFields, separator} = props; const eventParams = { mapFields, separator }; diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index b31ec89e325..7bcecac8df7 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -1,22 +1,24 @@ import { inject, ref, watch } from "vue"; -import {FTreeGrid} from '@farris/ui-vue/components/tree-grid'; -import {FDataGrid} from "@farris/ui-vue/components/data-grid"; -import {LookupProps } from "../lookup.props"; + +import { FTreeGrid } from '@farris/ui-vue/components/tree-grid'; +import { FDataGrid } from "@farris/ui-vue/components/data-grid"; + +import { LookupProps } from "../lookup.props"; import { useCheckProps } from "./use-check-props"; import { useSearchbar } from "./use-search-bar"; import { usePageInfo } from "./use-pageinfo"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "./use-http"; -import { navigationState, pageInfoState, searchState } from "./use-state"; import { treeGridRowOption } from "./use-treegrid-row-options"; export function useNavigation(props: LookupProps, context) { const useHttpComposition: UseHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const { loadData, lookupStates } = useHttpComposition; + const { navigationState, pageInfoState, searchState } = lookupStates; - const { renderSearchBar } = useSearchbar(props, true); - const { checkPaination, navIsList, navIsTreeList } = useCheckProps(props); - const { updatePageInfo } = usePageInfo(props); - const { loadData } = useHttpComposition; + const { renderSearchBar } = useSearchbar(props, true, lookupStates); + const { checkPaination, navIsList, navIsTreeList } = useCheckProps(props, lookupStates); + const { updatePageInfo } = usePageInfo(props, pageInfoState); const selectedItems = ref([]); if (navIsList()) { @@ -29,7 +31,8 @@ export function useNavigation(props: LookupProps, context) { const selectionOptions = { enableSelectRow: true, multiSelect: false, - showCheckbox: false + showCheckbox: false, + keepSelectingOnClick: false }; const columnOptions = { diff --git a/packages/ui-vue/components/lookup/src/composition/use-pageinfo.ts b/packages/ui-vue/components/lookup/src/composition/use-pageinfo.ts index fae96271d33..f90a7d79bf5 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-pageinfo.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-pageinfo.ts @@ -1,7 +1,7 @@ import { watch } from "vue"; -import { pageInfoState } from "./use-state"; +import { LookupProps } from "../lookup.props"; -export function usePageInfo(props: any){ +export function usePageInfo(props: LookupProps, pageInfoState){ watch(() => props.pagination, (newValue) => { pageInfoState.default = newValue; diff --git a/packages/ui-vue/components/lookup/src/composition/use-search-bar.tsx b/packages/ui-vue/components/lookup/src/composition/use-search-bar.tsx index 6d1a0deec99..b4fab0eb799 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-search-bar.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-search-bar.tsx @@ -1,11 +1,14 @@ -import { computed, reactive, ref, SetupContext, watch } from "vue"; +import { computed, ref, watch } from "vue"; + import LookupSearchBar from "../components/search-bar/search-bar.component"; import { LookupProps } from "../lookup.props"; import { useSearchFields } from "./use-search-fields"; -import { searchState } from "./use-state"; +import { LookupStates } from "./use-state"; + -export function useSearchbar(props: LookupProps, isNavigation: boolean) { - const {searchFieldItems, navSearchFieldItems} = useSearchFields(props); +export function useSearchbar(props: LookupProps, isNavigation: boolean, lookupStates: LookupStates) { + const { lookupState, searchState, navigationState } = lookupStates; + const {searchFieldItems, navSearchFieldItems} = useSearchFields(props, lookupState, navigationState); const searchFieldList: any = ref([]); const navSearchFieldList: any = ref([]); @@ -14,7 +17,7 @@ export function useSearchbar(props: LookupProps, isNavigation: boolean) { let newSearchFields = searchFields; - if (props.showAllSearchColumns) { + if (props.searchAnyField) { newSearchFields = [{label: '所有列', value: '*'}].concat(searchFields); } @@ -53,7 +56,7 @@ export function useSearchbar(props: LookupProps, isNavigation: boolean) { if (props.enableSearchBar && searchFields.value.length > 0) { return
diff --git a/packages/ui-vue/components/lookup/src/composition/use-search-fields.ts b/packages/ui-vue/components/lookup/src/composition/use-search-fields.ts index fc2659bdb03..ae5c2c55771 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-search-fields.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-search-fields.ts @@ -1,8 +1,8 @@ import { ref, watch } from "vue"; -import { SearchField } from "./types"; -import { lookupState, navigationState } from "./use-state"; +import { LookupProps } from "../lookup.props"; -export function useSearchFields(props: any) { + +export function useSearchFields(props: LookupProps, lookupState, navigationState) { const searchFieldItems = ref(props.searchFields || []); const navSearchFieldItems = ref(props.navigation?.searchFields || []); diff --git a/packages/ui-vue/components/lookup/src/composition/use-selections.ts b/packages/ui-vue/components/lookup/src/composition/use-selections.ts new file mode 100644 index 00000000000..4525deaaf1d --- /dev/null +++ b/packages/ui-vue/components/lookup/src/composition/use-selections.ts @@ -0,0 +1,141 @@ +import { VisualData } from "@farris/ui-vue/components/data-view"; +import { LookupStates } from "./use-state"; +import { LookupProps } from "../lookup.props"; +import { computed } from "vue"; + +export interface LookupSelectionsManager { + updateSelections: (data: any, checked?: boolean) => void; + clearSelections: () => void; + getSelectionIds: () => Array; + getSelections: () => any[]; + unSelectionsByIds: (itemIds: any) => void; + selectTreeNodes: (treeNodes: any[]) => void; + unSelectTreeNode: (treeNode: VisualData) => void; +} + +export const LOOKUP_SELECTIONS_MANAGER = Symbol('LOOKUP_SELECTIONS_MANAGER'); + +export function useSelections(props: LookupProps, lookupStates: LookupStates) : LookupSelectionsManager { + const { selectionState, unSelectDataId, lookupOptions } = lookupStates; + + const idField = computed(() => { + return lookupOptions.idField; + }); + + function getSelectionsMap() { + let selectionMap = new Map(); + if (selectionState.value && selectionState.value.length) { + selectionMap = new Map(selectionState.value.map<[string, any]>(n => [n[idField.value], n])); + } + + return selectionMap; + } + + + function clearSelections() { + selectionState.value = []; + } + + function getSelections() { + return selectionState.value || []; + } + + function getSelectionIds() { + return selectionState.value.map(item => item[idField.value]); + } + + function unSelectionsByIds(itemIds: any) { + if (!itemIds) { + return; + } + + if (!idField.value) { + console.error('idField is required'); + return; + } + const items = Array.isArray(itemIds) ? itemIds : [itemIds]; + const selectionMap = getSelectionsMap(); + items.forEach(n => { + selectionMap.delete(n); + }); + + selectionState.value = Array.from(selectionMap.values()); + unSelectDataId.value = items; + } + + function updateSelections(data: any, checked = true) { + if (!data) { + return; + } + + if (!idField.value) { + console.error('idField is required'); + return; + } + + const items = Array.isArray(data) ? data : [data]; + + if (!items.length) { + return; + } + + // Validate idField exists in all items + if (!items.every(item => idField.value in item)) { + console.error('Some items do not have the specified idField:', idField.value); + return; + } + + if (!lookupOptions.multiSelect) { + clearSelections(); + } + + const itemIds = items.map(item => item[idField.value]); + + const selectionMap = getSelectionsMap(); + + if (checked) { + const itemsMap = new Map(items.map<[string, any]>(n => [n[idField.value], n])); + // Add new items and deduplicate + itemIds.forEach(id => { + if (!selectionMap.has(id)) { + selectionMap.set(id, itemsMap.get(id)); + } + }); + } else { + itemIds.forEach(n => { + selectionMap.delete(n); + }); + + } + selectionState.value = Array.from(selectionMap.values()); + } + + + function selectTreeNodes(treeNodes: any[]) { + if (!treeNodes || !treeNodes.length) { + return; + } + + const items = treeNodes.map(treeNode => { + return treeNode.data; + }); + updateSelections(items); + } + + function unSelectTreeNode(treeNode: VisualData) { + if (treeNode) { + const rowId = treeNode.raw[idField.value]; + unSelectionsByIds(rowId); + } + } + + return { + updateSelections, + clearSelections, + getSelectionIds, + getSelections, + unSelectionsByIds, + selectTreeNodes, + unSelectTreeNode + }; +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-state.ts b/packages/ui-vue/components/lookup/src/composition/use-state.ts index ee12555b577..fa7ec46bff6 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-state.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-state.ts @@ -1,11 +1,59 @@ -import { reactive, ref } from "vue"; +import { Reactive, reactive, Ref, ref } from "vue"; import { LookupHttpResult, PagerInfoSate, QueryState, SearchState } from "./types"; +import { LookupProps } from "../lookup.props"; +export interface LookupStates { + pageInfoState: Reactive>; + lookupState: Reactive; + navigationState: Reactive; + queryState: Reactive; + searchState: Reactive; + selectionState: Ref; + unSelectDataId: Ref; + lookupOptions: Reactive> +} -export const pageInfoState = reactive>({}); -export const lookupState = reactive({}); -export const navigationState = reactive({}); -export const queryState = reactive({}); -export const searchState = reactive({}); -export const selectionState = ref([]); +export function useLookupState(props: LookupProps): LookupStates { + const pageInfoState = reactive>({}); + const lookupState = reactive({}); + const navigationState = reactive({}); + const queryState = reactive({}); + const searchState = reactive({}); + const selectionState = ref([]); + const unSelectDataId = ref(); + const lookupOptions = reactive>({}); + + const canUpdateKeys = [ + 'displayType', + 'treeToList', + 'navTreeToList', + 'showSelections', + 'showNavigation', + 'multiSelect', + 'mappingFields', + 'loader', + 'idField', + 'textField', + 'userDataKey' + ]; + + function initAllowSetOptions() { + canUpdateKeys.forEach((key) => { + lookupOptions[key] = props[key]; + }); + } + + initAllowSetOptions(); + + return { + pageInfoState, + lookupState, + navigationState, + queryState, + searchState, + selectionState, + unSelectDataId, + lookupOptions + }; +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-sync-select.ts b/packages/ui-vue/components/lookup/src/composition/use-sync-select.ts new file mode 100644 index 00000000000..82cb57bff01 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/composition/use-sync-select.ts @@ -0,0 +1,39 @@ +import { computed, Ref, watch } from "vue"; + +import { LookupTabs } from "./types"; +import { LookupStates } from "./use-state"; +import { LookupProps } from "../lookup.props"; + +export function useSyncSelect(props: LookupProps, gridRef: Ref, lookupState: LookupStates, currentTab?: Ref) { + const { selectionState, unSelectDataId, lookupOptions } = lookupState; + + const selectedItemsisEmpty = computed(() => { + return !(selectionState.value && selectionState.value.length); + }); + + + if (currentTab) { + watch(() => currentTab.value, (newValue, oldValue) => { + if (newValue === LookupTabs.dataList && newValue !== oldValue) { + if (!selectedItemsisEmpty.value) { + const itemIds = selectionState.value.map(item => item[lookupOptions.idField]); + gridRef.value?.selectItemByIds(itemIds); + } + } + }); + } + + watch(selectedItemsisEmpty, (newValue, oldValue) => { + if (newValue) { + gridRef.value?.clearSelection(); + } + }); + + if (props.showSelections && lookupOptions.multiSelect) { + watch(unSelectDataId, (newValue) => { + if (newValue) { + gridRef.value?.unSelectItemByIds(newValue); + } + }); + } +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index 9894c062b40..4aa3b3aeec6 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -1,61 +1,66 @@ -import { inject, ref, SetupContext, watch } from "vue"; -import { LookupProps } from "../lookup.props"; +import { inject, Ref, ref, SetupContext, watch } from "vue"; + +import { VisualData } from "@farris/ui-vue/components/data-view"; import { FTreeGrid } from '@farris/ui-vue/components/tree-grid'; + +import { LookupProps } from "../lookup.props"; import { useCheckProps } from "./use-check-props"; -import { lookupState, searchState, selectionState } from "./use-state"; -import { LookupHttpResult } from "./types"; -import { LOOKUP_HTTP_COMPOSITION, useHttp, UseHttpComposition } from "./use-http"; +import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "./types"; +import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "./use-http"; import { treeGridRowOption } from "./use-treegrid-row-options"; - +import { useFavorite } from "./use-favorite"; +import { useSyncSelect } from "./use-sync-select"; +import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "./use-selections"; +import { useLoadData } from "./use-load-data"; export function useTreegrid(props: LookupProps, context: SetupContext) { + const currentTab = inject(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; - const { checkMultiSelect, checkColumnOptions } = useCheckProps(props); + const { lookupStates } = useHttpComposition; + const { lookupState, searchState, lookupOptions } = lookupStates; + + + const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; + + const { checkMultiSelect, checkColumnOptions } = useCheckProps(props, lookupStates); + const { setColumns } = useFavorite(props, lookupOptions.idField); + const { selectTreeNodes, unSelectTreeNode, updateSelections } = lookupSelectionsManager; const selectionOptions = checkMultiSelect(); const columnOptions = checkColumnOptions(); const treegridRef = ref(); const selectionTreeValues = ref([]); - const selectedTreeNodes = ref([]); - const { loadData, idValues } = useHttpComposition; + const { loadData } = useHttpComposition; - function dataGridLoadData(items: any) { - treegridRef.value?.updateDataSource(items || []); - if (idValues.value) { - treegridRef.value?.selectItemByIds(idValues.value.split(props.separator)); - } - } + const { loadAdnSelect } = useLoadData(props, lookupStates); - function setDatagridColumns(columns: any[]) { - treegridRef.value?.updateColumns(columns); - } + useSyncSelect(props, treegridRef, lookupStates, currentTab); watch([() => lookupState?.columns, () => lookupState?.items, () => lookupState?.pageInfo, () => lookupState?.total, () => lookupState?.selectedData], ([newColumns, newItems, newPageInfo, newTotal, selectedData]) => { - newColumns && setDatagridColumns(newColumns); - dataGridLoadData(newItems); - if (selectedData && selectedData.length) { - selectedTreeNodes.value = selectedData; + updateSelections(selectedData); } - }); - watch(() => selectedTreeNodes.value, (newItems) => { - // context.emit("update:modelValue", newItems); - selectionState.value = newItems; + newColumns && setColumns(treegridRef.value, newColumns); + loadAdnSelect(treegridRef.value, newItems || []); }); function onSelectionChange(items: any[]) { - selectedTreeNodes.value = items; + selectTreeNodes(items); + } + + function onUnSelectItem(item: VisualData) { + unSelectTreeNode(item); } function httpRequest() { loadData({ search: searchState.default, action: 'list' }, (result: LookupHttpResult) => { - dataGridLoadData(result.items); + loadAdnSelect(treegridRef.value, result.items || []); }); } @@ -76,7 +81,7 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { ref={treegridRef} fit={true} data={props.data} - idField={props.idField} + idField={lookupOptions.idField} columns={props.columns} rowNumber={{ enable: false }} columnOption={columnOptions} @@ -86,12 +91,12 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { displayField={'code'} rowOption={treeGridRowOption} hierarchy={hierarchy} - onSelectionChange={onSelectionChange}>; + onSelectionChange={onSelectionChange} + onUnSelectItem={onUnSelectItem}>; }; return { treegridRef, - selectedTreeNodes, selectionTreeValues, renderTreeGrid }; diff --git a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts index f5f17764c9e..a8e6bd813ab 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts @@ -1,7 +1,9 @@ -import { inject, reactive, ref } from "vue"; - +import { computed, inject, reactive, ref } from "vue"; import { encrypt } from '@farris/ui-vue/components/common'; + import { F_LOOKUP_HTTP_SERVICE_TOKEN, LookupHttpResult, LookupHttpService, LookupRequestParams, LookupTabs } from "./types"; +import { LookupProps } from "../lookup.props"; +import { UseHttpComposition } from "./use-http"; export interface LookupUserData { pageSize?: number; @@ -27,17 +29,17 @@ export interface UserDataService { setDialogSize: (size: { width: number; height: number }) => void; } -export function useUserData(props: any, context: any): UserDataService { +export function useUserData(props: LookupProps, useHttpComposition: UseHttpComposition): UserDataService { const loadingService: any | null = inject('FLoadingService', null); - const httpService: LookupHttpService | null = inject(F_LOOKUP_HTTP_SERVICE_TOKEN, null); + const {lookupStates, lookupRequest, httpService} = useHttpComposition; + const {lookupOptions} = lookupStates; - const controlId = ref(props.id); - function builUserDataKey() { - return encrypt(controlId.value); - } + const dataKey = computed(() => { + return encrypt(lookupOptions.userDataKey || props.id); + }); - const userDataState = reactive({ key: builUserDataKey(), data: {} }); + const userDataState = reactive({ key: dataKey.value, data: {} }); function getUserData() { if (props.enableFavorite && httpService) { @@ -92,10 +94,11 @@ export function useUserData(props: any, context: any): UserDataService { function getFavoriteData() { const params = buildQueryParams({ favoriteIds: userDataState.data?.favorites }) as Partial; - loadingService?.show(); - if (httpService) { - return httpService.getData(props.uri, params).then((res: Partial) => { - loadingService?.clearAll(); + const loadingInstance = loadingService?.show(); + const loader = lookupRequest(); + if (loader) { + return loader(props.uri, params).then((res: Partial) => { + loadingInstance.value?.close(); userDataState.favoriteItems = res && res.items || []; return res; }); diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index cb6cfa9e209..7ca1670ce7d 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -13,21 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { defineComponent, inject, onMounted, onUnmounted, reactive, ref, watch } from 'vue'; -import { FButtonEdit } from '../../button-edit'; +import { computed, defineComponent, inject, onMounted, onUnmounted, reactive, ref, watch} from 'vue'; + +import { F_MODAL_SERVICE_TOKEN, FModalService } from '@farris/ui-vue/components/modal'; +import { FButtonEdit } from '@farris/ui-vue/components/button-edit'; + import LookupContainer from './components/lookup-container.component'; import LookupFavorite from './components/favorite/lookup-favorite.component'; import ModalContainer from './components/modal-container.component'; import { lookupProps, LookupProps } from './lookup.props'; import { useDialog } from './composition/use-dialog'; import { PagerChangeParams, SearchParams } from './composition/types'; -import { F_MODAL_SERVICE_TOKEN, FModalService } from '../../modal'; import { customData } from "./composition/use-customdata"; import { useLookupCallBack } from './composition/use-lookup-callback'; import { useInputChange } from './composition/use-input-change'; -import { selectionState } from './composition/use-state'; import { useHttp } from './composition/use-http'; import { useUserData } from './composition/use-user-data'; +import { useSelections } from './composition/use-selections'; + export default defineComponent({ name: 'FLookup', @@ -42,18 +45,33 @@ export default defineComponent({ customData.value = ref(props.customData); const useHttpComposition = useHttp(props, context); - const userDataService = useUserData(props, context); + const { lookupOptions, selectionState } = useHttpComposition.lookupStates; + + const userDataService = useUserData(props, useHttpComposition); + const showSelections = computed(() => { + return props.showSelections && lookupOptions.multiSelect; + }); + + + const showIncludeChildNodes = computed(() => { + return props.showIncludeChildNodes && props.showNavigation && !props.navTreeToList; + }); + + const selectionsManager = useSelections(props, useHttpComposition.lookupStates); function openDialog() { elementRef.value && !elementRef.value.getModal() && elementRef.value.openDialog(); } const {dictPicked} = useLookupCallBack(props); - const { modalOptions, beforeOpenDialog, dialogSize, customData: customQueryData, updateModelValue } = + const { modalOptions, beforeOpenDialog, dialogSize, customData: customQueryData, updateModelValue, + cancelDialog, submitDialog + } = useDialog(props, context as any, selectionState, { dictPicked, modelValue, - buttonEditInstance: elementRef, userDataService, - idValue: useHttpComposition.idValues + buttonEditInstance: elementRef, + userDataService, + useHttp: useHttpComposition }); const { onInputBlur, onEnterKeyDown } = useInputChange(props, context, @@ -97,7 +115,7 @@ export default defineComponent({ context.emit('update:modelValue', ''); context.emit('update:idValue', ''); - const clearParams = {items: null, mappingFields: props.mappingFields}; + const clearParams = {items: null, mappingFields: lookupOptions.mappingFields}; context.emit('clear', clearParams); if (props.context) { const { editor } = props.context; @@ -148,11 +166,29 @@ export default defineComponent({ } } + const selectedIds = computed(() => { + if (selectionState.value && selectionState.value.length) { + return selectionState.value.map(item => item[lookupOptions.idField]); + } else { + const idValues = useHttpComposition.idValues.value; + return idValues? idValues.split(props.separator) : []; + } + }); + + function updateLookupOptions(options: Record) { + for(const key in lookupOptions) { + if (options[key] !== undefined) { + lookupOptions[key] = options[key]; + } + } + } + context.expose({ openDialog, updateIdValue, - mappingFields: props.mappingFields, - idField: props.idField + mappingFields: lookupOptions.mappingFields, + idField: lookupOptions.idField, + setProps: updateLookupOptions }); return () => { @@ -177,7 +213,9 @@ export default defineComponent({ > onMaximizeModal($event)} - useHttpComposition= {useHttpComposition} userDataService={userDataService}> + useHttpComposition= {useHttpComposition} userDataService={userDataService} + useDialog={{cancelDialog, submitDialog}} showSelectedList={showSelections.value} + selectionsManager={ selectionsManager } showIncludeChildNodes={{show: showIncludeChildNodes.value, value: props.includeChildNodesValue}}> {{ default: () => ( ), fav: () => ( - + ) }} diff --git a/packages/ui-vue/components/lookup/src/lookup.props.ts b/packages/ui-vue/components/lookup/src/lookup.props.ts index 01910e92e14..1185b9d66b2 100644 --- a/packages/ui-vue/components/lookup/src/lookup.props.ts +++ b/packages/ui-vue/components/lookup/src/lookup.props.ts @@ -30,6 +30,7 @@ export const lookupProps = { } }, multiSelect: {type: Boolean, default: false}, + showSelections: {type: Boolean, default: true}, separator: {type: String, default: ','}, pagination: {type: Object as PropType, default: { enable: false, @@ -49,9 +50,12 @@ export const lookupProps = { beforeSelectData: {type: Function as PropType, default: null}, enableSearchBar: { type: Boolean, default: true }, searchFields: { type: Array as PropType, default: [] }, - showAllSearchColumns: { type: Boolean, default: true }, + searchAnyField: { type: Boolean, default: true }, navigation: { type: Object as PropType, default: null}, textChangeType: { type: String as PropType, default: 'any' }, + showNavigation: { type: Boolean, default: true }, + showIncludeChildNodes: { type: Boolean, default: true }, + includeChildNodesValue: { type: Boolean, default: true }, enableMultiFieldSearch: { type: Boolean, default: false }, treeToList: { type: Boolean, default: false }, navTreeToList: { type: Boolean, default: false }, @@ -60,9 +64,11 @@ export const lookupProps = { customData: { type: Object, default: null }, modelValue: { type: String, default: '' }, enableUserData: { type: Boolean, default: false }, + userDataKey: {type: String, default: ''}, onReady: { type: Function, default: null }, context: { type: Object, default: {} }, - placeholder: { type: String, default: '请选择' } + placeholder: { type: String, default: '请选择' }, + loader: { type: Function, default: null } } as Record; export type LookupProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts b/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts new file mode 100644 index 00000000000..be2ea057f66 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts @@ -0,0 +1,12 @@ +export const LookupEvents = [{ + label: 'dictPicking', + name: '帮助前事件' +}, +{ + label: 'dictPicked', + name: '帮助后事件' +}, +{ + label: 'beforeSelectData', + name: '数据选择确认前事件' +}]; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 61780f2b4fe..781dd64b9f0 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -7,6 +7,7 @@ import { lookupTextFieldConverter } from "./converters/lookup-property.converter"; import { DesignerComponentInstance } from "../../../designer-canvas/src/types"; +import { LookupEvents } from "./lookup-events"; export const LookupSchemaRepositoryToken = Symbol('schema_repository_token'); @@ -23,6 +24,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const appearance = this.getAppearanceConfig(); const behavior = this.getBehaviorConfig(propertyData); const lookup = this.getLookupConfig(propertyData.editor); + const eventsEditor = this.getEventPropConfig(propertyData); return { type: 'object', @@ -30,7 +32,8 @@ export class LookupPropertyConfig extends InputBaseProperty { basic, appearance, // behavior, - lookup + lookup, + eventsEditor } }; } @@ -40,22 +43,6 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "Basic Infomation", title: "行为", properties: { - editable: { - description: "", - title: "允许编辑", - type: "boolean", - $converter: lookupDefaultConverter - }, - readonly: { - description: "", - title: "只读", - type: "boolean", - $converter: lookupDefaultConverter, - editor: { - enableClear: true, - editable: true - } - }, required: { visible: false, description: "", @@ -99,6 +86,10 @@ export class LookupPropertyConfig extends InputBaseProperty { return false; } + private getDisplayType(propertyData) { + return propertyData.displayType? propertyData.displayType.toUpperCase(): ''; + } + private getLookupConfig(propertyData: any) { return { description: "Basic Infomation", @@ -263,6 +254,13 @@ export class LookupPropertyConfig extends InputBaseProperty { refreshPanelAfterChanged: true, visible: !this.isRelatedField() }, + showSelections: { + description: "显示已选记录", + $converter: lookupDefaultConverter, + title: "显示已选记录", + type: "boolean", + visible: !!propertyData.multiSelect + }, separator: { description: "多选分隔符", $converter: lookupDefaultConverter, @@ -282,15 +280,86 @@ export class LookupPropertyConfig extends InputBaseProperty { valueField: 'value' }, visible: !!propertyData.multiSelect + }, + enableSearchBar: { + description: "显示搜索工具条", + $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, + title: "启用搜索框", + type: "boolean", + }, + searchAnyField: { + description: "显示所有列", + $converter: lookupDefaultConverter, + title: "允许查询所有列", + type: "boolean", + visible: propertyData.enableSearchBar == null ? true: !!propertyData.enableSearchBar + }, + enableFavorite: { + description: "启用收藏夹", + $converter: lookupDefaultConverter, + title: "启用收藏夹", + type: "boolean", + }, + enableUserData: { + description: "保存界面状态", + $converter: lookupDefaultConverter, + title: "保存界面状态", + type: "boolean", + }, + treeToList: { + description: "以列表的形式展示树结构数据", + $converter: lookupDefaultConverter, + title: "树结构数据以列表的形式展示", + type: "boolean", + visible: this.getDisplayType(propertyData) === 'TREELIST' + }, + navTreeToList:{ + description: "以列表的形式展示树结构数据", + $converter: lookupDefaultConverter, + title: "树结构数据以列表的形式展示", + type: "boolean", + visible: this.getDisplayType(propertyData) === 'NAVTREELIST' + }, + showNavigation: { + description: "显示导航栏", + $converter: lookupDefaultConverter, + title: "显示导航栏", + type: "boolean", + visible: this.getDisplayType(propertyData).includes('NAV') } - // ,enableFavorite: { - // description: "启用收藏夹", - // $converter: lookupDefaultConverter, - // title: "启用收藏夹", - // type: "boolean", - // } } }; } + private getEventPropConfig(propertyData: any) { + const self = this; + const events = LookupEvents; + + const initialData = self.eventsEditorUtils['formProperties'](propertyData, self.viewModelId, events); + const properties = {}; + properties[self.viewModelId] = { + type: 'events-editor', + editor: { + initialData + } + }; + return { + title: '事件', + hideTitle: true, + properties, + // 这个属性,标记当属性变更得时候触发重新更新属性 + refreshPanelAfterChanged: true, + tabId: 'commands', + tabName: '交互', + setPropertyRelates(changeObject: any, data: any) { + const parameters = changeObject.propertyValue; + delete propertyData[self.viewModelId]; + if (parameters) { + parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后,调用此回调方法,用于处理联动属性 + self.eventsEditorUtils.saveRelatedParameters(propertyData, self.viewModelId, parameters['events'], parameters); + } + } + }; + } } diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index 53e63c83dd9..faf831fc91f 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -139,6 +139,46 @@ "fitColumns": { "type": "boolean", "default": true + }, + "enableFavorite": { + "type": "boolean", + "default": false + }, + "enableUserData": { + "type": "boolean", + "default": false + }, + "showSelections": { + "type": "boolean", + "default": true + }, + "treeToList": { + "type": "boolean", + "default": false + }, + "navTreeToList": { + "type": "boolean", + "default": false + }, + "showNavigation": { + "type": "boolean", + "default": true + }, + "dictPicking": { + "type": "object", + "default": null + }, + "dictPicked": { + "type": "object", + "default": null + }, + "enableSearchBar": { + "type": "boolean", + "default": true + }, + "searchAnyField": { + "type": "boolean", + "default": true } }, "required": [ diff --git a/packages/ui-vue/components/modal/src/composition/modal.service.tsx b/packages/ui-vue/components/modal/src/composition/modal.service.tsx index ff8a7dc10cf..24506a08a71 100644 --- a/packages/ui-vue/components/modal/src/composition/modal.service.tsx +++ b/packages/ui-vue/components/modal/src/composition/modal.service.tsx @@ -143,6 +143,14 @@ export default class ModalService { return app; } + close(modalRef?: any) { + if (!modalRef) { + this.getCurrentModal()?.close(); + } else { + modalRef.value?.close(); + } + } + open(options: ModalOptions): ModalFunctions { // 创建一个空白文档作为模态框容器,空白文档不属于DOM树,比创建一般节点性能较好,且仅渲染子元素 const container = document.createDocumentFragment(); @@ -257,7 +265,8 @@ export default class ModalService { return { update, destroy, - modalRef: this.activeModalInstance + modalRef: this.activeModalInstance, + close: this.close }; } } diff --git a/packages/ui-vue/components/modal/src/composition/type.ts b/packages/ui-vue/components/modal/src/composition/type.ts index 677b66761c0..857fb671e11 100644 --- a/packages/ui-vue/components/modal/src/composition/type.ts +++ b/packages/ui-vue/components/modal/src/composition/type.ts @@ -44,6 +44,7 @@ export interface ModalFunctions { update: (options: ModalOptions) => void; destroy: () => void; modalRef: any; + close: (modalRef?: any) => void; } export interface UseModal { diff --git a/packages/ui-vue/components/popover/src/composition/use-popup.ts b/packages/ui-vue/components/popover/src/composition/use-popup.ts index 5cbe0ceaef6..22caae73ca6 100644 --- a/packages/ui-vue/components/popover/src/composition/use-popup.ts +++ b/packages/ui-vue/components/popover/src/composition/use-popup.ts @@ -29,6 +29,10 @@ export function usePopup( } hidePopverOnClickBodyHandler = ($event: MouseEvent | Event) => { + if (!reference.value) { + return; + } + const isInReference = reference.value.contains($event.target as Node); if($event.type === 'scroll' || ($event.type === 'wheel' && isInReference)) { @@ -73,7 +77,7 @@ export function usePopup( } } - context.expose({ hide,popoverRef, show, shown }); + context.expose({ hide,popoverRef, show, shown, isShow: showPopover }); return { showPopover, hidePopverOnClickBodyHandler }; } diff --git a/packages/ui-vue/components/popover/src/composition/use-position.ts b/packages/ui-vue/components/popover/src/composition/use-position.ts index 5b67b8a8b7c..5a3a0d76437 100644 --- a/packages/ui-vue/components/popover/src/composition/use-position.ts +++ b/packages/ui-vue/components/popover/src/composition/use-position.ts @@ -15,8 +15,7 @@ export function usePosition( hostComposition: UseHost ): UsePosition { - const offsetX = ref(0); - const originalOffsetX = ref(props.offsetX?.value || 0); + const offsetX = ref(props.offsetX || 0); const popoverWidth = ref(-1); const originalReferenceTop = ref(-1); const originalReferenceLeft = ref(-1); @@ -29,8 +28,8 @@ export function usePosition( const { hostLeft, hostTop, hostWidth, hostHeight } = hostComposition; - watch(props.offsetX, (latestOffsetXValue: number) => { - offsetX.value = latestOffsetXValue - originalOffsetX.value; + watch(() => props.offsetX, (latestOffsetXValue: number) => { + offsetX.value = latestOffsetXValue; }); const popoverStyle = computed(() => { @@ -55,7 +54,8 @@ export function usePosition( const arrowStyle = computed(() => { const styleObject = { - left: `${arrowLeftPosition.value}px` + left: `${arrowLeftPosition.value}px`, + transform: `translateX(${props.arrowOffsetX}px)` } as Record; return styleObject; }); @@ -98,6 +98,19 @@ export function usePosition( return { popoverLeft, arrowLeft }; } + function calculateLeftPositionWhilePopupOnTop(intendingToPopoverLeft: number, popoverRect: DOMRect) { + const popoverLeftLimit = calculatePopoverLeftLimit(popoverRect, intendingToPopoverLeft); + const arrowLeft = intendingToPopoverLeft <= popoverLeftLimit ? arrowLeftPosition.value : intendingToPopoverLeft - popoverLeftLimit; + return { popoverLeft: intendingToPopoverLeft, arrowLeft }; + } + + function calcultePopoverPositionOnTopLeft(popoverRect: DOMRect, referenceRect: DOMRect, arrowRect: DOMRect): PopoverPosition { + const intendingToPopoverLeft = (referenceRect.left - hostLeft.value) + scrollLeft.value; + const { arrowLeft, popoverLeft } = calculateLeftPositionWhilePopupOnTop(intendingToPopoverLeft, popoverRect); + const {popoverTop} = calculatePopoverPostionOnTop(popoverRect, referenceRect, arrowRect); + return { popoverLeft, popoverTop, arrowLeft }; + } + function calculatePopoverPositionOnBottom(popoverRect: DOMRect, referenceRect: DOMRect, arrowRect: DOMRect): PopoverPosition { const intendingToPopoverLeft = ((referenceRect.left - hostLeft.value) + referenceRect.width / 2) - (arrowRect.width / 2 - (popoverRect.left - hostLeft.value)) + scrollLeft.value; @@ -149,6 +162,7 @@ export function usePosition( const postionMap = new Map PopoverPosition>([ ['top', calculatePopoverPostionOnTop], + ['top-left', calcultePopoverPositionOnTopLeft], ['bottom', calculatePopoverPositionOnBottom], ['bottom-left', calcultePopoverPositionOnBottomLeft], ['auto', calcultePopoverPositionOnAuto] @@ -159,6 +173,11 @@ export function usePosition( originalReferenceTop.value = referenceRect.top; originalReferenceLeft.value = referenceRect.left; const arrowRect = arrowRef.value?.getBoundingClientRect(); + + if (props.fitContent) { + popoverRef.value.style.width = 'auto'; + } + const popoverRect = popoverRef.value?.getBoundingClientRect(); popoverWidth.value = popoverRect.width; const calculatePopoverPosition = postionMap.get(position.value); diff --git a/packages/ui-vue/components/popover/src/popover.component.tsx b/packages/ui-vue/components/popover/src/popover.component.tsx index 46351413f15..2257ff0db1b 100644 --- a/packages/ui-vue/components/popover/src/popover.component.tsx +++ b/packages/ui-vue/components/popover/src/popover.component.tsx @@ -44,8 +44,14 @@ export default defineComponent({ const { onResize } = useResize(props, context, reference, shouldFitWidthToReference, positionComposition); const popoverClass = computed(() => { - const originPopover = `popover in popover-${position.value}`; - const bsPopover = `bs-popover-${position.value}`; + let placement = position.value; + + if (placement === 'top-left') { + placement = 'top'; + } + + const originPopover = `popover in popover-${placement}`; + const bsPopover = `bs-popover-${placement}`; const popoverClassObject = { 'popover-fitcontent': props.fitContent } as any; diff --git a/packages/ui-vue/components/popover/src/popover.directive.tsx b/packages/ui-vue/components/popover/src/popover.directive.tsx index 951906e829b..fcd72400c74 100644 --- a/packages/ui-vue/components/popover/src/popover.directive.tsx +++ b/packages/ui-vue/components/popover/src/popover.directive.tsx @@ -29,6 +29,26 @@ function hidePopover($event: Event, binding: Record) { popoverInstance.value.hide(); } +function togglePopover($event: Event, binding: Record, reference: any) { + $event.stopPropagation(); + const popoverInstance = binding.value as ComputedRef; + if (popoverInstance && popoverInstance.value) { + if (popoverInstance.value.isShow) { + hidePopover($event, binding); + } else { + showPopover($event, binding, reference); + } + } +} + +function onShowPopover($event: Event, binding: Record, element: any) { + if (binding.arg && binding.arg === 'toggle') { + togglePopover($event, binding, element); + } else { + showPopover($event, binding, element); + } +} + const popoverDirective = { mounted: (element: any, binding: Record, vnode: any) => { let app: App | null; @@ -36,9 +56,9 @@ const popoverDirective = { element.addEventListener('mouseenter', ($event: MouseEvent) => showPopover($event, binding, element)); element.addEventListener('mouseleave', ($event: MouseEvent) => hidePopover($event, binding)); } else if (binding.modifiers.click) { - element.addEventListener('click', ($event: Event) => showPopover($event, binding, element)); + element.addEventListener('click', ($event: Event) => onShowPopover($event, binding, element)); } else { - element.addEventListener('click', ($event: Event) => showPopover($event, binding, element)); + element.addEventListener('click', ($event: Event) => onShowPopover($event, binding, element)); // element.addEventListener('mouseenter', ($event: MouseEvent) => showPopover($event, binding, element)); // element.addEventListener('mouseleave', ($event: MouseEvent) => hidePopover($event, binding)); diff --git a/packages/ui-vue/components/popover/src/popover.props.ts b/packages/ui-vue/components/popover/src/popover.props.ts index d2a4673b206..28a46a56083 100644 --- a/packages/ui-vue/components/popover/src/popover.props.ts +++ b/packages/ui-vue/components/popover/src/popover.props.ts @@ -15,7 +15,7 @@ */ import { ExtractPropTypes, PropType, ref } from 'vue'; -export type PopoverPlacement = 'top' | 'bottom' | 'left' | 'right' | 'auto' | 'bottom-left'; +export type PopoverPlacement = 'top' | 'bottom' | 'left' | 'right' | 'auto' | 'bottom-left' | 'top-left'; export const popoverProps = { id: { type: String }, @@ -36,6 +36,7 @@ export const popoverProps = { visible: { type: Boolean, default: false }, class: { type: String }, offsetX: { type: Object as PropType, default: ref(0) }, + arrowOffsetX: { type: Number, default: 0 }, zIndex: { type: Number, default: -1 }, keepWidthWithReference: { type: Boolean, default: false }, fitContent: { type: Boolean, default: false }, diff --git a/packages/ui-vue/components/tree-grid/src/tree-grid.component.tsx b/packages/ui-vue/components/tree-grid/src/tree-grid.component.tsx index d9f4022bfc1..2aa8df089ad 100644 --- a/packages/ui-vue/components/tree-grid/src/tree-grid.component.tsx +++ b/packages/ui-vue/components/tree-grid/src/tree-grid.component.tsx @@ -343,6 +343,11 @@ export default defineComponent({ function getSelectionRow() { return useSelectionComposition.getSelectionRow(); } + + function unSelectItemByIds(dataItemIds: string[]) { + useSelectionComposition.unSelectItemByIds(dataItemIds); + } + context.expose({ addNewDataItem, addNewChildDataItem, @@ -357,7 +362,8 @@ export default defineComponent({ getSelectedItems, clearSelection, getSelectionRow, - clickRowItemById + clickRowItemById, + unSelectItemByIds }); return () => { diff --git a/packages/ui-vue/demos/lookup/basic.vue b/packages/ui-vue/demos/lookup/basic.vue index d2f54b5987b..467e3a5dc74 100644 --- a/packages/ui-vue/demos/lookup/basic.vue +++ b/packages/ui-vue/demos/lookup/basic.vue @@ -39,8 +39,8 @@ const onBeforeOpenDialog = (e) => { console.log('窗口打开前', e); lookupHttp.displayType = 'list'; - if (e.context && e.context.customData) { - e.context.customData.value = {id: '123', name: '张三'}; + if (e && e.customData) { + e.customData.value = {id: '123', name: '张三'}; } return { showDialog: true }; diff --git a/packages/ui-vue/demos/lookup/tree-list.vue b/packages/ui-vue/demos/lookup/tree-list.vue index 2ef90a060d0..35570013fd9 100644 --- a/packages/ui-vue/demos/lookup/tree-list.vue +++ b/packages/ui-vue/demos/lookup/tree-list.vue @@ -38,8 +38,8 @@ const onBeforeOpenDialog = (e) => { console.log('窗口打开前', e); lookupHttp.displayType = 'list'; - if (e.context && e.context.customData) { - e.context.customData.value = {id: '123', name: '张三'}; + if (e && e.customData) { + e.customData.value = {id: '123', name: '张三'}; } return { showDialog: true }; diff --git a/packages/ui-vue/demos/modal/modal-service.vue b/packages/ui-vue/demos/modal/modal-service.vue index 6a0b9e91fc8..2e19454ebd2 100644 --- a/packages/ui-vue/demos/modal/modal-service.vue +++ b/packages/ui-vue/demos/modal/modal-service.vue @@ -24,7 +24,10 @@ function toggleModal() { render: renderComponent(), acceptCallback, rejectCallback, - draggable:true + draggable:true, + resizeable: true, + showMaxButton: true, + fitContent: false }); } -- Gitee From d422cf086d7a5396d36dde53c4dcbe19856383a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 21 Feb 2025 11:43:40 +0800 Subject: [PATCH 003/156] =?UTF-8?q?fix:=20=E5=AD=97=E6=AE=B5=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=BC=96=E8=BE=91=E5=99=A8=E6=B8=85=E7=A9=BA=E5=90=8E?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=86=8D=E6=AC=A1=E6=B7=BB=E5=8A=A0=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/mapping-editor/src/mapping-editor.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index cd7792c3438..baa51da8846 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -109,7 +109,7 @@ export default defineComponent({ FMessageBoxService.question('确定要清空所有映射字段吗?', '', () => { mappingFields.value = {}; mappingFieldList.value = []; - datagridRef.value.updateDataSource([]); + datagridRef.value.updateDataSource(mappingFieldList.value); }, () => { }); } -- Gitee From 755d7fc370801dc1105131255c4b9d59f3bb0c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 21 Feb 2025 14:00:22 +0800 Subject: [PATCH 004/156] =?UTF-8?q?feature:=20=E8=AE=BE=E8=AE=A1=E5=99=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=A7=86=E5=9B=BE=E6=94=AF=E6=8C=81=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E5=AE=9A=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form-designer/form-designer.component.tsx | 7 ++++- .../monaco-editor/monaco-editor.component.tsx | 26 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/designer/src/components/components/form-designer/form-designer.component.tsx b/packages/designer/src/components/components/form-designer/form-designer.component.tsx index 0e597b7443c..516a51d223a 100644 --- a/packages/designer/src/components/components/form-designer/form-designer.component.tsx +++ b/packages/designer/src/components/components/form-designer/form-designer.component.tsx @@ -21,6 +21,7 @@ export default defineComponent({ const fillTabs = ref(true); const controlTreeRef = ref(); const entityTreeRef = ref(); + const monacoEditorRef = ref(); function onCanvasInitialized(dragula: any) { dragulaCompostion.value = dragula; @@ -106,6 +107,10 @@ export default defineComponent({ propertyPanelInstance?.value?.updateDesignerItem(null, selectionSchema.id); focusingSchema.value = selectionSchema; } + + if (activeDesignerView.value === 'formDesignerCode' && selectionSchema) { + monacoEditorRef.value?.setPosition(selectionSchema.id); + } } function reloadPropertyPanel() { @@ -159,7 +164,7 @@ export default defineComponent({ >
diff --git a/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx b/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx index bed516836da..c8e67576452 100644 --- a/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx +++ b/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx @@ -62,7 +62,31 @@ export default defineComponent({ resizeObserver.disconnect(); } }); - context.expose({ getContent }); + + const setPosition = (controlId: string) => { + if (!editorInstance || !controlId) { + return; + } + // 查找匹配的文本 + const matches = editorInstance.getModel().findMatches(controlId, false, false, false, null, true); + + if (matches.length > 0) { + // 获取第一个匹配项的位置 + const firstMatch = matches[0]; + const {range} = firstMatch; + + // 将光标定位到匹配的位置 + editorInstance.setPosition(range.getStartPosition()); + + // 滚动到匹配的位置 + editorInstance.revealRangeInCenter(range); + } + }; + + context.expose({ + getContent, + setPosition + }); return () => { return
; -- Gitee From 32f1e74cd7abe9fc45b74bbc3f16df5fd447b7c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 21 Feb 2025 17:15:07 +0800 Subject: [PATCH 005/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Ddatepicker?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E6=9C=88=E4=BB=BD=E9=80=89=E6=8B=A9=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 12 +++++++++--- .../src/components/month/month.component.tsx | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index a4cacf33b0f..63f5e15cb54 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -152,6 +152,12 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[selectedDateObj.value.month || '1'], displayTextOfYear: `${selectedDateObj.value.year}` }); + + selectedMonth.value = { + year: selectedDateObj.value.year? selectedDateObj.value.year: undefined, + month: selectedDateObj.value.month ? selectedDateObj.value.month: undefined, + }; + const initSecondaryYear = today.month === 12 ? (today.year || 1) + 1 : today.year; const initSecondaryMonth = (today.month || 1) < 12 ? (today.month || 1) + 1 : 1; const secondaryActiveMonth = ref({ @@ -475,9 +481,9 @@ export default defineComponent({ selectedMonth.value = currentMonth; activeMonth.value = { month: currentMonth.month || 1, - displayTextOfMonth: nameOfMonths.value[activeMonth.value.month || '1'], - year: activeMonth.value.year || 1, - displayTextOfYear: `${activeMonth.value.displayTextOfYear}` + displayTextOfMonth: nameOfMonths.value[currentMonth.month || '1'], + year: currentMonth.year || 1, + displayTextOfYear: `${currentMonth.year}` }; } diff --git a/packages/ui-vue/components/date-picker/src/components/month/month.component.tsx b/packages/ui-vue/components/date-picker/src/components/month/month.component.tsx index 1c7169cf780..19a27991eab 100644 --- a/packages/ui-vue/components/date-picker/src/components/month/month.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/month/month.component.tsx @@ -47,7 +47,7 @@ export default defineComponent({ if (target.disable) { return; } - context.emit('click', target); + context.emit('click', target.date); } function onKeyDown($event: KeyboardEvent, target: MonthViewItem) { -- Gitee From 074a402b6d2a6531000dd7d68bd941629fb6ec64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 21 Feb 2025 18:08:26 +0800 Subject: [PATCH 006/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=AF=AD?= =?UTF-8?q?=E6=B3=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/selected-list/lookup-selected-list.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx index 0280a9806e1..85d3aec0cfe 100644 --- a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx @@ -13,7 +13,7 @@ export default defineComponent({ props: lookupSelectedListProps, setup(props: LookupSelectedListProps, context) { - const messagerService: FMessageBoxService = inject('FMessageBoxService') as FMessageBoxService; + const messagerService: any = inject('FMessageBoxService'); const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; const { lookupState, selectionState } = useHttpComposition.lookupStates; -- Gitee From f1e1052dfe8662703bf34fe502c82fb12cdcd42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 22 Feb 2025 13:44:44 +0800 Subject: [PATCH 007/156] =?UTF-8?q?fix:=20=E5=85=83=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=E4=B8=8E=E5=AD=97=E6=AE=B5=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=BC=96=E8=BE=91=E5=99=A8=E6=98=93=E7=94=A8=E6=80=A7?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converters/lookup-property.converter.ts | 4 ++-- .../mapping-editor/src/mapping-editor.component.tsx | 9 ++++++++- .../src/schema-selector-editor.component.tsx | 8 +++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index e3001910cf0..27807879bf9 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -39,13 +39,13 @@ export const lookupDataSourceConverter = { convertTo: (schema: Record, propertyKey: string, propertyValue: any[]) => { if (propertyValue && propertyValue.length > 0) { const datasource = propertyValue[0]; - const {name, id, metadataContent} = datasource; + const {name, id, metadataContent, code} = datasource; if (!schema.editor.dataSource) { schema.editor.dataSource = {}; } - schema.editor.dataSource.displayName = name; + schema.editor.dataSource.displayName = `${name}(${code})` ; schema.editor['helpId'] = id; const { displayType, idField, textField } = metadataContent; diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index baa51da8846..7747a2c125a 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -33,6 +33,12 @@ export default defineComponent({ return visualData; }; + async function onBeforeOpenPopup(params: any) { + const { dataSource } = params; + console.log(dataSource); + return true; + } + const gridColumns = [ { field: 'sourceField', title: '数据源字段', dataType: 'string', editor: { type: 'combo-tree', @@ -43,7 +49,8 @@ export default defineComponent({ formatter: props.fromData.formatter, editorParams: props.fromData.editorParams, editable: false, - customRowStatus: treeNodeStatus + customRowStatus: treeNodeStatus, + beforeOpen: onBeforeOpenPopup }}, { field: 'targetField', title: '目标字段', dataType: 'string', editor: { type: 'combo-tree', diff --git a/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx b/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx index 07184a47638..7a38f77c0d8 100644 --- a/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx @@ -3,14 +3,15 @@ import FButtonEdit from '../../button-edit/src/button-edit.component'; import FSchemaSelector from './schema-selector.component'; import { SchemaSelectorEditorProps, schemaSelectorEditorProps } from "./schema-selector-editor.props"; import { SchemaItem } from "./composition/types"; +import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../../components/notify"; + export default defineComponent({ name: "FSchemaSelectorEditor", props: schemaSelectorEditorProps, emits: ['selectionChange', 'update:modelValue'], setup(props: SchemaSelectorEditorProps, context) { - - const messageService: any = inject('FMessageBoxService'); + const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; const buttonIcon = ''; const viewType = ref(props.viewType); const selected = ref(); @@ -89,7 +90,7 @@ export default defineComponent({ return true; } - messageService?.info('请选择数据源'); + notifyService?.warning('请选择数据源'); return false; } } @@ -99,6 +100,7 @@ export default defineComponent({ }; function onBeforeOpen() { + selected.value = null; if (props.beforeOpenDialog) { props.beforeOpenDialog({}); } -- Gitee From 62231b0ab78df8d3a2d5bbab7742f55f2e2e2683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 22 Feb 2025 16:39:39 +0800 Subject: [PATCH 008/156] =?UTF-8?q?fix:=20=E5=85=83=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../list-view/src/composition/use-item.ts | 16 ++- .../property-config/lookup.property-config.ts | 2 +- .../src/mapping-editor.component.tsx | 102 +++++++++++------- 3 files changed, 76 insertions(+), 44 deletions(-) diff --git a/packages/ui-vue/components/list-view/src/composition/use-item.ts b/packages/ui-vue/components/list-view/src/composition/use-item.ts index efcc924234a..e3905d9085d 100644 --- a/packages/ui-vue/components/list-view/src/composition/use-item.ts +++ b/packages/ui-vue/components/list-view/src/composition/use-item.ts @@ -25,6 +25,16 @@ export function useItem( const { activeIndex, focusedItemId, hoverIndex } = useHoverComposition; const { clearSelection, getSelectedItems, toggleSelectItem } = useSelectionComposition; const selectedItems: Ref = ref(getSelectedItems()); + const isSelected = (itemId: any) => { + if (selectedItems.value.length === 0) { + return false; + } + return selectedItems.value.some(item => item.data[identifyField.value] === itemId); + }; + + function getKey(item: VisualData, index: number) { + return item.raw[identifyField.value] || ''; + } function listViewItemClass(item: VisualData, index: number) { const classObject = { @@ -32,7 +42,7 @@ export function useItem( 'f-list-view-draggable-item': draggable.value, 'f-un-click': !item.checked, 'f-un-select': !!item.raw[disableField.value], - 'f-listview-active': item.raw.__fv_index__ === activeIndex.value, + 'f-listview-active': isSelected(getKey(item, index)), 'f-listview-hover': !isDragging.value && index === hoverIndex.value, 'moving': !!item.moving } as Record; @@ -44,10 +54,6 @@ export function useItem( return classObject; }; - function getKey(item: VisualData, index: number) { - return item.raw[identifyField.value] || ''; - } - const shouldFocusedItemOnCheck = computed(() => { return !enableMultiSelect.value; }); diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 61780f2b4fe..d324b0276af 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -20,7 +20,7 @@ export class LookupPropertyConfig extends InputBaseProperty { getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { const basic = this.getBasicProperties(propertyData, componentInstance); - const appearance = this.getAppearanceConfig(); + const appearance = this.getAppearanceProperties(propertyData, componentInstance); const behavior = this.getBehaviorConfig(propertyData); const lookup = this.getLookupConfig(propertyData.editor); diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index 7747a2c125a..23990fe5438 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -4,6 +4,7 @@ import { FDataGrid } from "../../data-grid"; import { FMessageBoxService } from '../../message-box'; import { mappingEditorProps, MappingEditorProps } from "./mapping-editor.props"; import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../../components/notify"; +import { cloneDeep } from "lodash-es"; export interface ComboTreeRepository { getData(params?: any): Promise; @@ -25,44 +26,41 @@ export default defineComponent({ const repository = inject(props.fromData.repositoryToken); const toDataRepository = inject(props.toData.repositoryToken); const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; - + const treeNodeStatus = (visualData: any) => { - if (visualData.raw.$type !== 'SimpleField') { + if (visualData.raw.$type !== 'SimpleField' || visualData.raw.selectable === false) { visualData.disabled = true; } return visualData; }; - async function onBeforeOpenPopup(params: any) { - const { dataSource } = params; - console.log(dataSource); - return true; - } - const gridColumns = [ - { field: 'sourceField', title: '数据源字段', dataType: 'string', editor: { - type: 'combo-tree', - data: fromDataSource.value, - idField: props.fromData.idField || 'id', - textField: props.fromData.textField || 'name', - valueField: props.fromData.valueField || 'id', - formatter: props.fromData.formatter, - editorParams: props.fromData.editorParams, - editable: false, - customRowStatus: treeNodeStatus, - beforeOpen: onBeforeOpenPopup - }}, - { field: 'targetField', title: '目标字段', dataType: 'string', editor: { - type: 'combo-tree', - data: toDataSource.value, - idField: props.toData.idField || 'id', - textField: props.toData.textField || 'name', - valueField: props.toData.valueField || 'id', - formatter: props.toData.formatter, - editorParams: props.toData.editorParams, - editable: false, - customRowStatus: treeNodeStatus - } } + { + field: 'sourceField', title: '数据源字段', dataType: 'string', editor: { + type: 'combo-tree', + data: fromDataSource.value, + idField: props.fromData.idField || 'id', + textField: props.fromData.textField || 'name', + valueField: props.fromData.valueField || 'id', + formatter: props.fromData.formatter, + editorParams: props.fromData.editorParams, + editable: false, + customRowStatus: treeNodeStatus + } + }, + { + field: 'targetField', title: '目标字段', dataType: 'string', editor: { + type: 'combo-tree', + data: toDataSource.value, + idField: props.toData.idField || 'id', + textField: props.toData.textField || 'name', + valueField: props.toData.valueField || 'id', + formatter: props.toData.formatter, + editorParams: props.toData.editorParams, + editable: false, + customRowStatus: treeNodeStatus + } + } ]; function createId() { @@ -103,7 +101,7 @@ export default defineComponent({ if (selectedItems.value.length) { datagridRef.value.endEditCell(); const itemIndex = mappingFieldList.value.findIndex((item: any) => item.id === selectedItems.value[0].id); - if (itemIndex> -1) { + if (itemIndex > -1) { selectedItems.value = []; datagridRef.value.removeDataItem(itemIndex + 1); } @@ -139,7 +137,7 @@ export default defineComponent({ const emptyFields = mappingFieldList.value.filter((item: any) => !item.sourceField || !item.targetField); return emptyFields.length; } - + const modalOptions = { title: props.title, fitContent: false, @@ -199,25 +197,52 @@ export default defineComponent({ const helpId = props.editorParams?.propertyData?.helpId; if (!helpId) { - notifyService?.warning({message: '请先配置数据源!', position: 'top-center'}); + notifyService?.warning({ message: '请先配置数据源!', position: 'top-center' }); return false; } const promises: Array> = []; - const fromDataPromise = repository? repository.getData(props.editorParams): Promise.resolve(fromDataSource.value); + const fromDataPromise = repository ? repository.getData(props.editorParams) : Promise.resolve(fromDataSource.value); promises.push(fromDataPromise); - const toDataPromise = toDataRepository? toDataRepository.getData(props.editorParams): Promise.resolve(toDataSource.value); + const toDataPromise = toDataRepository ? toDataRepository.getData(props.editorParams) : Promise.resolve(toDataSource.value); promises.push(toDataPromise); return Promise.all(promises).then(([fromData, toData]) => { - gridColumns[0].editor.data = fromData; - gridColumns[1].editor.data = toData; + fromDataSource.value = fromData; + toDataSource.value = toData; + + // gridColumns[0].editor.data = fromData; + // gridColumns[1].editor.data = toData; return true; }); } + function resetTreeDataSource(dataSource: any, disableFields: string[]) { + dataSource.forEach((item: any) => { + item.selectable = !disableFields.includes(item.data.bindingPath); + if (item.children) { + resetTreeDataSource(item.children, disableFields); + } + }); + } + + function onBeforeEditCell(event: any) { + console.log(event); + const { column } = event; + const { field, editor } = column; + if (field === 'sourceField' && editor) { + const disabledFields = mappingFieldList.value.map((item: any) => { + return item.sourceField; + }); + + resetTreeDataSource(fromDataSource.value, disabledFields); + editor.data = cloneDeep(fromDataSource.value); + } + return true; + } + // const canRemove = computed(() => { // return selectedItems?.value.length > 0; // }); @@ -259,6 +284,7 @@ export default defineComponent({ data={mappingFieldList.value} newDataItem={createNewDataItem} onSelectionChange={onSelectionChange} + beforeEditCell={onBeforeEditCell} >
); }; -- Gitee From 7ee87ccd38cbf31568fa69b6558d762eab1761e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 24 Feb 2025 09:57:36 +0800 Subject: [PATCH 009/156] =?UTF-8?q?fix:=20lookup=E4=BB=85=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E5=AD=97=E7=AC=A6=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=90=AF=E7=94=A8=E5=A4=9A=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../list-view/src/composition/use-item.ts | 10 +++++++++- .../property-config/lookup.property-config.ts | 20 ++++++++++++------- .../composition/entity/input-base-property.ts | 9 +++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/list-view/src/composition/use-item.ts b/packages/ui-vue/components/list-view/src/composition/use-item.ts index e3905d9085d..db251f69559 100644 --- a/packages/ui-vue/components/list-view/src/composition/use-item.ts +++ b/packages/ui-vue/components/list-view/src/composition/use-item.ts @@ -29,7 +29,15 @@ export function useItem( if (selectedItems.value.length === 0) { return false; } - return selectedItems.value.some(item => item.data[identifyField.value] === itemId); + return selectedItems.value.some(item => { + let value = ''; + if (item.data) { + value = item.data[identifyField.value]; + } else { + value = item[identifyField.value]; + } + return value === itemId; + }); }; function getKey(item: VisualData, index: number) { diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index d324b0276af..634bd223ac7 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -18,6 +18,7 @@ export class LookupPropertyConfig extends InputBaseProperty { editable: false }; + getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { const basic = this.getBasicProperties(propertyData, componentInstance); const appearance = this.getAppearanceProperties(propertyData, componentInstance); @@ -85,18 +86,23 @@ export class LookupPropertyConfig extends InputBaseProperty { }; } - private isRelatedField() { + private isSimpleStringField() { const fullPath = this.designViewModelField?.path || ''; - - if (fullPath && fullPath.indexOf('.') > -1) { - const field = fullPath.split('.')[0]; + if (fullPath) { + const field = fullPath.indexOf('.') > -1 ? fullPath.split('.')[0] : fullPath; const fields = this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId); if (fields && fields.length) { const fieldInfo = fields.map(node => node.data).find(data => data.code === field); - return fieldInfo?.type?.$type === 'EntityType'; + return fieldInfo?.type?.$type === "StringType" && fieldInfo?.$type === 'SimpleField'; } + return false; } - return false; + return true; + } + + // 绑定字段更新后,处理lookup 的相关属性 + private changeBindingField(propertyData, changeObject) { + propertyData.editor.multiSelect = false; } private getLookupConfig(propertyData: any) { @@ -261,7 +267,7 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "boolean", editor: this.comboListEditor, refreshPanelAfterChanged: true, - visible: !this.isRelatedField() + visible: this.isSimpleStringField() }, separator: { description: "多选分隔符", diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts index d6e49dcbe72..3ca59d27a5b 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts @@ -91,10 +91,19 @@ export class InputBaseProperty extends BaseControlProperty { changeObject.needRefreshControlTree = true; break; } + case 'binding': { + self.changeBindingField(propertyData, changeObject); + break; + } } } }; } + + public changeBindingField(propertyData, changeObject): any { + } + + public getAppearanceProperties(propertyData, componentInstance): any { const self = this; -- Gitee From 703baa2bda1a4017bf526dc0097a80fb8d8fcc3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 24 Feb 2025 10:24:39 +0800 Subject: [PATCH 010/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 634bd223ac7..4a714d52ff5 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -101,7 +101,7 @@ export class LookupPropertyConfig extends InputBaseProperty { } // 绑定字段更新后,处理lookup 的相关属性 - private changeBindingField(propertyData, changeObject) { + changeBindingField(propertyData, changeObject) { propertyData.editor.multiSelect = false; } -- Gitee From 9d05601fa601eb3ee3972517c625757fd763259f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 24 Feb 2025 16:32:13 +0800 Subject: [PATCH 011/156] =?UTF-8?q?fix:=20=E6=97=A5=E6=9C=9F=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 17 ++++++++++++++--- .../date-picker-container.props.ts | 2 +- .../date-picker/src/date-picker.props.ts | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 63f5e15cb54..f4e204efe5b 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -33,6 +33,7 @@ import { TimeValueText } from "../../../../time-picker/src/composition/types"; import { convertToDate, convertToString } from "../../../../time-picker/src/composition/utils"; import { useDateFormat } from '../../../../common/date/use-date-format'; import { CalenderDayItem } from "../../types/calendar"; +import { cloneDeep } from "lodash-es"; export default defineComponent({ name: 'FDateView', @@ -586,7 +587,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[today.month || '1'], displayTextOfYear: `${today.year}` }; - selectedDate.value = today; + selectedDate.value = cloneDeep(today); } const shouldShowSecondCalendar = computed(() => { @@ -646,6 +647,16 @@ export default defineComponent({ } }; + const btnTodayStyle = computed(() => { + return (date: any) => { + const todayIsDisable = refDisableDate.isDisabledDate(date); + return { + "pointer-events": todayIsDisable ?"none": "auto", + opacity: todayIsDisable?0.3: 1 + }; + }; + }); + return () => { return (
- {shouldShowCalendarView.value && } + {shouldShowCalendarView.value && } {shouldShowMonthView.value && } {shouldShowYearView.value && }
@@ -691,7 +702,7 @@ export default defineComponent({ } { showConfirmButton.value &&
- + 确定
diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.props.ts b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.props.ts index ed09480cd5f..fac44e36fdc 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.props.ts +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.props.ts @@ -65,7 +65,7 @@ export const datePickerContainerProps = { /** 是否高亮周日 */ highlightSunday: { Type: Boolean, default: false }, /** 最晚年限 */ - maxYear: { Type: Number, default: 2500 }, + maxYear: { Type: Number, default: 10000 }, /** 最早年限 */ minYear: { Type: Number, default: 1 }, /** 模式;Embedded;popup; */ diff --git a/packages/ui-vue/components/date-picker/src/date-picker.props.ts b/packages/ui-vue/components/date-picker/src/date-picker.props.ts index 418a378cf55..482db57b957 100644 --- a/packages/ui-vue/components/date-picker/src/date-picker.props.ts +++ b/packages/ui-vue/components/date-picker/src/date-picker.props.ts @@ -50,7 +50,7 @@ export const datePickerProps = { /** 是否高亮周日 */ highlightSunday: { Type: Boolean, default: false }, /** 最晚年限 */ - maxYear: { Type: Number, default: 2500 }, + maxYear: { Type: Number, default: 10000 }, /** 最早年限 */ minYear: { Type: Number, default: 1 }, /** 组件值 */ -- Gitee From 307db961adad6b65ae3c32dd52dc4c05f2b74305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 24 Feb 2025 17:33:21 +0800 Subject: [PATCH 012/156] =?UTF-8?q?fix:=20=E5=88=97=E8=A1=A8=E5=9C=A8?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E5=86=85=E7=BC=96=E8=BE=91=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/data-view/composition/use-edit.tsx | 13 +++++++++---- .../date-picker-container.component.tsx | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/ui-vue/components/data-view/composition/use-edit.tsx b/packages/ui-vue/components/data-view/composition/use-edit.tsx index ce0a18eff9f..69e2dbed817 100644 --- a/packages/ui-vue/components/data-view/composition/use-edit.tsx +++ b/packages/ui-vue/components/data-view/composition/use-edit.tsx @@ -119,7 +119,12 @@ export function useEdit(props: DataViewOptions, context: SetupContext, useIdenti return; } - const clickingCellElement = (payload.target as any).closest('.fv-grid-cell'); + const target = payload.target as any; + if (target?.closest('.popover')) { + return; + } + + const clickingCellElement = target.closest('.fv-grid-cell'); const clickingEditingCell = editingCell && editingCell.ref && editingCell.ref === clickingCellElement; if (clickingEditingCell) { return; @@ -131,7 +136,7 @@ export function useEdit(props: DataViewOptions, context: SetupContext, useIdenti editingRow = undefined; } } - document.body.removeEventListener('click', onClickOutOfCell); + document.body.removeEventListener('click', onClickOutOfCell, true); } function onClickCell(payload: MouseEvent, cell: VisualDataCell, row: VisualData, column: Partial = {}) { @@ -157,8 +162,8 @@ export function useEdit(props: DataViewOptions, context: SetupContext, useIdenti .then(value => { if (value) { beginEditCell(cell, row, column); - document.body.removeEventListener('click', onClickOutOfCell); - document.body.addEventListener('click', onClickOutOfCell); + document.body.removeEventListener('click', onClickOutOfCell, true); + document.body.addEventListener('click', onClickOutOfCell, true); } }); } diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index f4e204efe5b..7fcd7441187 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -565,7 +565,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[today.month || '1'], displayTextOfYear: `${today.year}` }; - selectedDate.value = today; + selectedDate.value = cloneDeep(today); context.emit('datePicked', today); } @@ -576,7 +576,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[today.month || '1'], displayTextOfYear: `${today.year}` }; - selectedDate.value = today; + selectedDate.value = cloneDeep(today); selectedMonth.value = { year: today.year, month: today.month }; } -- Gitee From e38bb5e80437c71abe61f7c127ea02e040d582da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 24 Feb 2025 19:01:59 +0800 Subject: [PATCH 013/156] =?UTF-8?q?fix:=20=E5=AD=97=E6=AE=B5=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=BC=96=E8=BE=91=E5=99=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../button-edit/src/button-edit.component.tsx | 1 + .../combo-tree/src/combo-tree.component.tsx | 24 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/button-edit/src/button-edit.component.tsx b/packages/ui-vue/components/button-edit/src/button-edit.component.tsx index 127fbd851f2..f9e844b9561 100644 --- a/packages/ui-vue/components/button-edit/src/button-edit.component.tsx +++ b/packages/ui-vue/components/button-edit/src/button-edit.component.tsx @@ -93,6 +93,7 @@ export default defineComponent({ commitValue, elementRef: buttonEditRef, hidePopup, + popoverRef: popupComposition.popoverRef, shouldPopupContent, togglePopup, openDialog: () => { diff --git a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx index a1b9a764bcd..6681d0021e2 100644 --- a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx @@ -1,8 +1,9 @@ -import { Ref, SetupContext, computed, defineComponent, ref, watch } from "vue"; +import { Ref, SetupContext, computed, defineComponent, ref, watch, watchEffect } from "vue"; import FButtonEdit from '@farris/ui-vue/components/button-edit'; import { ComboTreeProps, comboTreeProps, Option } from "./combo-tree.props"; import ComboTreeContainer from './components/tree-container.component'; import { useDataSource } from "./composition/use-data-source"; +import { cloneDeep } from "lodash-es"; export default defineComponent({ name: 'FComboTree', @@ -60,6 +61,20 @@ export default defineComponent({ } ); + const originalValue = ref(); + + const onBeforeOpen = () => { + originalValue.value = cloneDeep(dataSource.value); + }; + + const showPopover = computed(() => { + const popoverInstance = comboEditorRef.value.popoverRef; + if (popoverInstance) { + return popoverInstance.shown; + } + return false; + }); + return ( - + >} ); }; -- Gitee From 94faee99a3cc793a81efe37ac959004be1e0c31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 25 Feb 2025 19:09:31 +0800 Subject: [PATCH 014/156] =?UTF-8?q?fix:=20=E5=93=8D=E5=BA=94=E5=BC=8F?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E6=A0=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../combo-tree/src/composition/use-data-source.ts | 13 ++++++++++--- .../converters/lookup-property.converter.ts | 5 ----- .../src/property-config/lookup.property-config.ts | 1 + .../dropdown/toolbar-dropdown-menu.component.tsx | 6 ++++-- .../src/response-toolbar.component.tsx | 14 +++++++++++--- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/ui-vue/components/combo-tree/src/composition/use-data-source.ts b/packages/ui-vue/components/combo-tree/src/composition/use-data-source.ts index fb85a26c31e..17e0037284d 100644 --- a/packages/ui-vue/components/combo-tree/src/composition/use-data-source.ts +++ b/packages/ui-vue/components/combo-tree/src/composition/use-data-source.ts @@ -44,11 +44,18 @@ export function useDataSource(props: ComboTreeProps): UseDataSource { return [optionText, true]; }); const displayTextMap = new Map(displayTextArray); + + let flatItems: any = []; // 如果是树结构 需要平铺数据 - if(dataSource.value[0].children){ - flatTreeNodes(dataSource.value, []); + if(dataSource.value[0].data){ + flatTreeNodes(dataSource.value, flatItems); + } else { + flatItems = dataSource.value; } - return dataSource.value.filter((item: Option) => displayTextMap.has(item[props.textField])); + + flatItems = flatItems.map((item: Option) => item.data? item.data : item); + + return flatItems.filter((item: Option) => displayTextMap.has(item[props.textField]) || displayTextMap.has(item[props.valueField])); } function buildSelectedItemByDisplayText(displayText: string) { diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index 27807879bf9..0e4d017f733 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -54,11 +54,6 @@ export const lookupDataSourceConverter = { schema.editor.textField = textField; schema.editor.dataSource.type = "ViewObject"; - // if (lookupDataSourceConverter['entityCode']) { - // const code = lookupDataSourceConverter['entityCode']; - // const field = schema.editor.dataSource.bindingField; - // schema.editor.dataSource.uri = `${code}.${field}`; - // } if (!schema.editor.dataSource.uri) { schema.editor.dataSource.uri = generateSourceUri(schema.id); } diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 4a714d52ff5..dd858ffd07b 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -151,6 +151,7 @@ export class LookupPropertyConfig extends InputBaseProperty { repositoryToken: LookupSchemaRepositoryToken, onSubmitModal: (dataSourceSchema: any) => { if (dataSourceSchema) { + delete propertyData.mappingFields; const formInfo = this.formSchemaUtils.getFormMetadataBasicInfo(); // 获取数据源详细配置信息 return this.metadataService.getPickMetadata(formInfo.relativePath, dataSourceSchema[0].data) diff --git a/packages/ui-vue/components/response-toolbar/src/components/dropdown/toolbar-dropdown-menu.component.tsx b/packages/ui-vue/components/response-toolbar/src/components/dropdown/toolbar-dropdown-menu.component.tsx index b0df8dfb09d..26376ea5fb7 100644 --- a/packages/ui-vue/components/response-toolbar/src/components/dropdown/toolbar-dropdown-menu.component.tsx +++ b/packages/ui-vue/components/response-toolbar/src/components/dropdown/toolbar-dropdown-menu.component.tsx @@ -23,7 +23,8 @@ export default function (context, useIconComposition: UseIcon) { const classObject = { disabled: !item.enable, 'dropdown-submenu': true, - 'f-rt-dropdown': true + 'f-rt-dropdown': true, + 'text-truncate': true } as Record; const classNames = item.dropdownClass.split(' '); if (classNames && classNames.length) { @@ -40,6 +41,7 @@ export default function (context, useIconComposition: UseIcon) { disabled: !item.enable, 'dropdown-item': true, 'f-rt-btn': true, + 'text-truncate': true } as Record; const classNames = item.class.split(' '); if (classNames && classNames.length) { @@ -132,7 +134,7 @@ export default function (context, useIconComposition: UseIcon) { display: item.expanded ? 'block' : 'none', position: 'fixed', maxWidth: '300px', - width: 'auto', + width: '180px', minWidth: '120px' }; const screenWidth = document.getElementsByTagName('body')[0].getClientRects()[0].width; diff --git a/packages/ui-vue/components/response-toolbar/src/response-toolbar.component.tsx b/packages/ui-vue/components/response-toolbar/src/response-toolbar.component.tsx index 5ac460a08b6..d3a225b4071 100644 --- a/packages/ui-vue/components/response-toolbar/src/response-toolbar.component.tsx +++ b/packages/ui-vue/components/response-toolbar/src/response-toolbar.component.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, ref, onMounted, onUnmounted, watch } from 'vue'; +import { computed, defineComponent, ref, onMounted, onUnmounted, watch, nextTick } from 'vue'; import { ResponseToolbarProps, responseToolbarProps } from './response-toolbar.props'; import { ResponseToolbarDropDownItem } from './types/response-toolbar-dropdwon-item'; import { ResponseToolbarItem } from './types/response-toolbar-item'; @@ -115,7 +115,10 @@ export default defineComponent({ (moreElement as HTMLElement).getBoundingClientRect().width + (marginRightOfMoreElement ? marginRightOfMoreElement.value : 0); availableSpace -= moreElementWidth; + } else { + availableSpace -= 72; } + const toolbarItemElements = allElements.filter((element: Element) => element.id !== '__more_buttons__'); for (const toolbarItem of toolbarItemElements) { @@ -183,6 +186,9 @@ export default defineComponent({ observer.observe(element); document.body.addEventListener('click', collapseAllDropdownMenu); document.body.addEventListener('wheel', collapseAllDropdownMenu); + + const containerWidth = element.getBoundingClientRect().width; + resetToolbarItemsForWidthChanged(containerWidth); }); onUnmounted(() => { @@ -195,8 +201,10 @@ export default defineComponent({ () => props.items, () => { toolbarItems.value = buildResponseToolbarItems(props.items); - // 解决工具栏项数据变更,之前的下拉等数据消失问题 - resetToolbarItemsForWidthChanged(); + nextTick(() => { + // 解决工具栏项数据变更,之前的下拉等数据消失问题 + resetToolbarItemsForWidthChanged(); + }); }, { deep: true -- Gitee From 7b4db973e6dc04e508b84a2fab6743ac28f77bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 25 Feb 2025 19:18:24 +0800 Subject: [PATCH 015/156] =?UTF-8?q?fix:=20combo-tree=20=E5=8F=96=E6=95=B0?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui-vue/components/combo-tree/src/combo-tree.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx index 6681d0021e2..165873e6817 100644 --- a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx @@ -68,7 +68,7 @@ export default defineComponent({ }; const showPopover = computed(() => { - const popoverInstance = comboEditorRef.value.popoverRef; + const popoverInstance = comboEditorRef.value?.popoverRef; if (popoverInstance) { return popoverInstance.shown; } -- Gitee From c87b175ea0bb9d168b59b5308d679f9b5f1b972f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 26 Feb 2025 11:00:24 +0800 Subject: [PATCH 016/156] =?UTF-8?q?fix:=20combo-tree=20=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../combo-tree/src/combo-tree.component.tsx | 112 +++++++++--------- .../popover/src/composition/use-popup.ts | 3 + 2 files changed, 58 insertions(+), 57 deletions(-) diff --git a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx index 165873e6817..17a8d9e7598 100644 --- a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx @@ -10,73 +10,72 @@ export default defineComponent({ props: comboTreeProps, emits: ['clear', 'update:modelValue', 'change'], setup(props: ComboTreeProps, context: SetupContext) { - return () => { - const comboEditorRef: Ref = ref(); - const disable = ref(props.disabled); - const enableClear = ref(props.enableClear); - const enableSearch = ref(props.enableSearch); - const readonly = ref(props.readonly); - const { dataSource, displayText, editable, modelValue, getSelectedItemsByDisplayText } = useDataSource(props); + const comboEditorRef: Ref = ref(); + const disable = ref(props.disabled); + const enableClear = ref(props.enableClear); + const enableSearch = ref(props.enableSearch); + const readonly = ref(props.readonly); + const { dataSource, displayText, editable, modelValue, getSelectedItemsByDisplayText } = useDataSource(props); - const isMultiSelect = computed(() => props.multiSelect); + const isMultiSelect = computed(() => props.multiSelect); - const comboEditorWidth = computed(() => { - return comboEditorRef.value ? (comboEditorRef.value.elementRef as HTMLElement).getBoundingClientRect().width : 0; - }); + const comboEditorWidth = computed(() => { + return comboEditorRef.value ? (comboEditorRef.value.elementRef as HTMLElement).getBoundingClientRect().width : 0; + }); - function tryHidePopupOnSelect() { - const shouldHidePopupOnSelect = !isMultiSelect.value; - if (shouldHidePopupOnSelect && comboEditorRef.value) { - comboEditorRef.value.hidePopup(); - } + function tryHidePopupOnSelect() { + const shouldHidePopupOnSelect = !isMultiSelect.value; + if (shouldHidePopupOnSelect && comboEditorRef.value) { + comboEditorRef.value.hidePopup(); } + } - function onSelectionChange(selectedItems: Option[]) { - displayText.value = selectedItems.map((item: Option) => item[props.textField]).join(props.separator); - modelValue.value = selectedItems.map((item: Option) => item[props.valueField]).join(props.separator); - context.emit('update:modelValue', modelValue.value); - context.emit('change', selectedItems, modelValue.value); - tryHidePopupOnSelect(); - } + function onSelectionChange(selectedItems: Option[]) { + displayText.value = selectedItems.map((item: Option) => item[props.textField]).join(props.separator); + modelValue.value = selectedItems.map((item: Option) => item[props.valueField]).join(props.separator); + context.emit('update:modelValue', modelValue.value); + context.emit('change', selectedItems, modelValue.value); + tryHidePopupOnSelect(); + } - function onClear($event: Event) { - modelValue.value = ''; - context.emit('update:modelValue', ''); - context.emit('clear'); - } + function onClear($event: Event) { + modelValue.value = ''; + context.emit('update:modelValue', ''); + context.emit('clear'); + } - function onDisplayTextChange(displayText: string) { - const selectedItems = getSelectedItemsByDisplayText(displayText); - onSelectionChange(selectedItems); - } + function onDisplayTextChange(displayText: string) { + const selectedItems = getSelectedItemsByDisplayText(displayText); + onSelectionChange(selectedItems); + } - watch( - [() => props.disabled, () => props.editable, () => props.enableClear, () => props.enableSearch, () => props.readonly], - ([newDisabled, newEditable, newEnableClear, newEnableSearch, newReadonly]) => { - disable.value = newDisabled; - editable.value = newEditable; - enableClear.value = newEnableClear; - enableSearch.value = newEnableSearch; - readonly.value = newReadonly; - } - ); + watch( + [() => props.disabled, () => props.editable, () => props.enableClear, () => props.enableSearch, () => props.readonly], + ([newDisabled, newEditable, newEnableClear, newEnableSearch, newReadonly]) => { + disable.value = newDisabled; + editable.value = newEditable; + enableClear.value = newEnableClear; + enableSearch.value = newEnableSearch; + readonly.value = newReadonly; + } + ); - const originalValue = ref(); + const originalValue = ref(); - const onBeforeOpen = () => { - originalValue.value = cloneDeep(dataSource.value); - }; + const onBeforeOpen = () => { + originalValue.value = cloneDeep(dataSource.value); + }; - const showPopover = computed(() => { - const popoverInstance = comboEditorRef.value?.popoverRef; - if (popoverInstance) { - return popoverInstance.shown; - } - return false; - }); + const showPopover = computed(() => { + const popoverInstance = comboEditorRef.value?.popoverRef; + if (popoverInstance) { + return popoverInstance.shown; + } + return false; + }); - return ( - { + return } - - ); + ; }; } }); diff --git a/packages/ui-vue/components/popover/src/composition/use-popup.ts b/packages/ui-vue/components/popover/src/composition/use-popup.ts index 5cbe0ceaef6..4c457a8c25d 100644 --- a/packages/ui-vue/components/popover/src/composition/use-popup.ts +++ b/packages/ui-vue/components/popover/src/composition/use-popup.ts @@ -64,6 +64,9 @@ export function usePopup( document.body.addEventListener('mousedown', hidePopverOnClickBodyHandler); document.body.addEventListener('wheel', hidePopverOnClickBodyHandler, true); document.addEventListener('scroll', hidePopverOnClickBodyHandler); + if (top?.document !== document) { + top?.document.addEventListener('mousedown', hidePopverOnClickBodyHandler); + } const closestPopover = referenceElement.closest('.popover') as HTMLElement; if (closestPopover) { -- Gitee From e6b3c4c0754f3ad244c1431fea633513f49bffe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 26 Feb 2025 16:26:22 +0800 Subject: [PATCH 017/156] =?UTF-8?q?fix:=20lookup=20=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E8=A7=A6=E5=8F=91onClear?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-input-change.ts | 11 ++++++++--- .../ui-vue/components/lookup/src/lookup.component.tsx | 9 ++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts index 74dac1fee55..68c9ef993f0 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts @@ -20,12 +20,16 @@ export function useInputChange(props: any, context: any, options: LookupInputCha const {beforeOpenDialog, updateModelValue, selectedItems, openDialog, modelValue, useHttpComposition} = options; const {updateSearchFieldTitle} = useHttpComposition; + const isClear = ref(false); + + function isTextChange(text: string) { - if (isEmpty(text)) { + const isChange = props.modelValue !== text; + if (isEmpty(text) && isChange) { + isClear.value = true; return false; } - const isChange = props.modelValue !== text; if (isChange) { queryState.value = text; } else { @@ -96,6 +100,7 @@ export function useInputChange(props: any, context: any, options: LookupInputCha changeOnBlur, changeOnEnter, onInputBlur, - onEnterKeyDown + onEnterKeyDown, + isClear }; } diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index cb6cfa9e209..151f0ed546a 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -56,7 +56,7 @@ export default defineComponent({ idValue: useHttpComposition.idValues }); - const { onInputBlur, onEnterKeyDown } = useInputChange(props, context, + const { onInputBlur, onEnterKeyDown, isClear } = useInputChange(props, context, { beforeOpenDialog, updateModelValue, selectedItems: selectionState, openDialog, modelValue, useHttpComposition }); const modalConfigs = reactive(modalOptions); @@ -107,6 +107,13 @@ export default defineComponent({ } } + watch(() => isClear.value, (newValue) => { + if (newValue) { + onClear(); + isClear.value = false; + } + }); + function onSearch($event: SearchParams) { context.emit('search', $event); } -- Gitee From 0648584c6b34a15b5cb4a264141c7d3c3521c9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 26 Feb 2025 16:46:18 +0800 Subject: [PATCH 018/156] =?UTF-8?q?fix:=20lookup=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/lookup.component.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index 151f0ed546a..0ed6d48493b 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -95,8 +95,7 @@ export default defineComponent({ async function onClear() { selectionState.value = []; context.emit('update:modelValue', ''); - context.emit('update:idValue', ''); - + updateIdValue(''); const clearParams = {items: null, mappingFields: props.mappingFields}; context.emit('clear', clearParams); if (props.context) { -- Gitee From 5d6e9d0bc2dd56dc0fcbea9b61d1b1a5a905de13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 26 Feb 2025 17:30:46 +0800 Subject: [PATCH 019/156] =?UTF-8?q?fix:=20input-group=20=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=98=BE=E7=A4=BA=E6=97=B6=E6=9C=BA=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/text-box/composition/use-clear.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/common/text-box/composition/use-clear.ts b/packages/ui-vue/components/common/text-box/composition/use-clear.ts index 74957c969a7..a17d7c8bb07 100644 --- a/packages/ui-vue/components/common/text-box/composition/use-clear.ts +++ b/packages/ui-vue/components/common/text-box/composition/use-clear.ts @@ -22,6 +22,10 @@ export function useClear( } }); + watch(() => hasFocused?.value, (focused) => { + !focused && toggleClearIcon(false); + }); + const clearButtonClass = computed(() => ({ 'input-group-text': true, 'input-group-clear': true @@ -46,8 +50,8 @@ export function useClear( } function onMouseEnter(event: MouseEvent) { - if (shouldShowClearButton.value && !isEmpty.value) { - toggleClearIcon(true); + if (shouldShowClearButton.value) { + toggleClearIcon(!!(event.target as any).querySelector('input').value); } } -- Gitee From 0b0793f9530c9e0f8ddfe95b3cfaa0dd0c060b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 26 Feb 2025 18:43:22 +0800 Subject: [PATCH 020/156] =?UTF-8?q?fix:=20lookup=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/lookup/src/composition/use-input-change.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts index 68c9ef993f0..98c05f0f7c8 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts @@ -54,8 +54,9 @@ export function useInputChange(props: any, context: any, options: LookupInputCha useHttpComposition.loadData(searchParams, (data: LookupHttpResult) => { const onlyOne = data.items && data.items.length === 1 && (!data.items[0].children || !data.items[0].children.length); if (onlyOne) { - selectedItems.value = data.items || []; + selectedItems.value = (data.items || []).map(item => item.data ? item.data: item); updateModelValue(); + queryState.value = ''; document.body.classList.remove('lookup-modal-open'); return; } -- Gitee From 47083624e8207dc0a9611e4f86bc81b888ea0554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 27 Feb 2025 14:57:31 +0800 Subject: [PATCH 021/156] =?UTF-8?q?fix:=20notify=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/notify/src/components/toast.component.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/notify/src/components/toast.component.tsx b/packages/ui-vue/components/notify/src/components/toast.component.tsx index a1db655836d..590f8f486ea 100644 --- a/packages/ui-vue/components/notify/src/components/toast.component.tsx +++ b/packages/ui-vue/components/notify/src/components/toast.component.tsx @@ -107,9 +107,9 @@ export default defineComponent({ return () => { return ( -
+
{shouldShowCloseButton.value && ( - )} -- Gitee From 421ccf34d2aa0fede7dd9782ef6d6952aecbeb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 27 Feb 2025 19:02:33 +0800 Subject: [PATCH 022/156] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84lookup?= =?UTF-8?q?=E5=8F=AF=E9=85=8D=E7=BD=AE=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui-vue/components/lookup/src/schema/lookup.schema.json | 4 ++++ .../ui-vue/components/lookup/src/schema/schema-mapper.ts | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index 53e63c83dd9..35a778224fd 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -139,6 +139,10 @@ "fitColumns": { "type": "boolean", "default": true + }, + "idField": { + "type": "string", + "default": "" } }, "required": [ diff --git a/packages/ui-vue/components/lookup/src/schema/schema-mapper.ts b/packages/ui-vue/components/lookup/src/schema/schema-mapper.ts index a5b207bf8c9..1edbf85731d 100644 --- a/packages/ui-vue/components/lookup/src/schema/schema-mapper.ts +++ b/packages/ui-vue/components/lookup/src/schema/schema-mapper.ts @@ -24,5 +24,11 @@ export const schemaMapper = new Map([ return {uri: value}; } return {uri: resolvedSchema?.dataSource?.uri}; + }], + ['idField', (key: string, value: any, resolvedSchema) => { + if (value) { + return {idField: value}; + } + return {idField: resolvedSchema?.dataSource?.idField}; }] ]); -- Gitee From d1c40029453b3200fe421b7826998d0c8b811a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 28 Feb 2025 10:35:57 +0800 Subject: [PATCH 023/156] =?UTF-8?q?fix:=20=E5=BC=B9=E7=AA=97=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/field-selector.component.tsx | 2 +- .../property-config/lookup.property-config.ts | 12 ++++---- .../components/modal/src/modal.component.tsx | 30 ++++++++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/ui-vue/components/field-selector/src/field-selector.component.tsx b/packages/ui-vue/components/field-selector/src/field-selector.component.tsx index d2e3ecc2d14..cdc6cd93070 100644 --- a/packages/ui-vue/components/field-selector/src/field-selector.component.tsx +++ b/packages/ui-vue/components/field-selector/src/field-selector.component.tsx @@ -63,7 +63,7 @@ export default defineComponent({ function checkBindingData(): boolean { if (!bindingData.value || !bindingData.value.length) { - notifyService.warning({ message: '请先配置数据源!' }); + notifyService.warning({ message: '请先选择一条数据!' }); return false; } return true; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 818fd6207db..bc8232bf65b 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -71,11 +71,6 @@ export class LookupPropertyConfig extends InputBaseProperty { visible:false, $converter: lookupVisibleConverter }, - placeholder: { - title: "提示文本", - type: "string", - $converter: lookupDefaultConverter - }, "tabindex": { visible: false, description: "", @@ -111,6 +106,11 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "Basic Infomation", title: "编辑器", properties: { + placeholder: { + title: "提示文本", + type: "string", + $converter: lookupDefaultConverter + }, editable: { description: "", title: "允许编辑", @@ -269,7 +269,7 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "boolean", editor: this.comboListEditor, refreshPanelAfterChanged: true, - visible: this.isSimpleStringField() + visible: false // this.isSimpleStringField() }, separator: { description: "多选分隔符", diff --git a/packages/ui-vue/components/modal/src/modal.component.tsx b/packages/ui-vue/components/modal/src/modal.component.tsx index 858cbbd0f4c..702682421cc 100644 --- a/packages/ui-vue/components/modal/src/modal.component.tsx +++ b/packages/ui-vue/components/modal/src/modal.component.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { computed, defineComponent, ref, SetupContext, Teleport, watch, Transition, onMounted, onUnmounted, provide, nextTick } from 'vue'; +import { computed, defineComponent, ref, SetupContext, Teleport, watch, Transition, onMounted, onUnmounted, provide, nextTick, onBeforeMount } from 'vue'; import { ModalButton, ModalOptions } from './composition/type'; import { ModalProps, modalProps } from './modal.props'; import { useResizeable } from './composition/use-resizeable'; @@ -47,6 +47,7 @@ export default defineComponent({ const containment = ref(props.containment || null); const modalContainerRef = ref(); + const hasModal = ref(false); function close($event: MouseEvent, accept?: boolean) { modelValue.value = false; @@ -88,6 +89,10 @@ export default defineComponent({ resizedEventParam, allowDrag, unWindowResizeHandle } = useResizeable(props, context); const { registerDraggle } = useDraggable(props, context, allowDrag); + function hasOpenModal() { + const modalTotal = document.querySelectorAll('.farris-modal').length; + return !!modalTotal && document.body.classList.contains('modal-open'); + } function removeModalOpenStyle() { const modalTotal = document.querySelectorAll('.farris-modal').length; @@ -111,11 +116,15 @@ export default defineComponent({ watch(() => props.modelValue, (newValue, oldValue) => { if (newValue !== oldValue) { modelValue.value = newValue; - + if (!newValue) { removeModalOpenStyle(); } } + + if (modelValue.value) { + hasModal.value = hasOpenModal(); + } }); // 监听是否展示标题变化 watch(() => props.showHeader, (newValue, oldValue) => { @@ -251,22 +260,35 @@ export default defineComponent({ } } + + const modalContainerStyle = computed(() => { + const styleObject = { display: 'inline-block' }; + if (hasModal.value) { + styleObject['background-color'] = 'transparent'; + } + return styleObject; + }); + let escEventHandler: any = null; let enterEventHandler: any = null; + onBeforeMount(() => { + hasModal.value = hasOpenModal(); + }); + onMounted(() => { if (modalElementRef.value && !containment.value) { containment.value = (modalElementRef.value as HTMLElement).parentElement; boundingElement.value = containment.value; registerDraggle(modalHeaderRef.value, modalElementRef.value, boundingElement.value); } + if (showModal.value) { document.body.classList.add('modal-open'); } escEventHandler = useEsc(props, context); enterEventHandler = useEnter(props, context); - }); onUnmounted(() => { @@ -349,7 +371,7 @@ export default defineComponent({ {showModal.value && -
-- Gitee From b604782cd611ae3beb2548da483e214cfcd487b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 28 Feb 2025 11:52:01 +0800 Subject: [PATCH 024/156] =?UTF-8?q?fix:=20lookup=E6=A0=91=E8=A1=A8=20?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E8=8A=82=E7=82=B9=E7=A6=81=E6=AD=A2=E9=80=89?= =?UTF-8?q?=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-treegrid-row-options.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts index bf535067896..e4dfdc691e0 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts @@ -5,6 +5,10 @@ export const treeGridRowOption: Partial = { if (visualData.collapse === undefined) { visualData.collapse = !visualData.raw.expanded; } + + if (visualData.raw.addtional || visualData.raw.selectable === false) { + visualData.disabled = true; + } return visualData; } }; -- Gitee From 8de4451fdcf25ae09733116031ce336740a3ecf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 28 Feb 2025 15:35:40 +0800 Subject: [PATCH 025/156] =?UTF-8?q?fix:=20datepicker=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=BD=8D=E7=BD=AE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/property-config/lookup.property-config.ts | 14 +++++++------- .../popover/src/composition/use-position.ts | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index bc8232bf65b..7fe8bad3fef 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -106,6 +106,13 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "Basic Infomation", title: "编辑器", properties: { + readonly: { + description: "", + title: "只读", + type: "boolean", + $converter: lookupDefaultConverter, + editor: {...this.comboListEditor, editable: true} + }, placeholder: { title: "提示文本", type: "string", @@ -118,13 +125,6 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDefaultConverter, editor: this.comboListEditor }, - readonly: { - description: "", - title: "只读", - type: "boolean", - $converter: lookupDefaultConverter, - editor: {...this.comboListEditor, editable: true} - }, dataSource: { description: "数据源", title: "数据源", diff --git a/packages/ui-vue/components/popover/src/composition/use-position.ts b/packages/ui-vue/components/popover/src/composition/use-position.ts index 5b67b8a8b7c..25ebd68cdbf 100644 --- a/packages/ui-vue/components/popover/src/composition/use-position.ts +++ b/packages/ui-vue/components/popover/src/composition/use-position.ts @@ -137,7 +137,11 @@ export function usePosition( if (window.innerHeight - intendingToPopoverTop > referenceRect.top) { popoverTop = intendingToPopoverTop + scrollTop.value; + if (popoverRect.height > referenceRect.top) { + popoverTop = window.innerHeight - popoverRect.height; + } } else { + popoverTop = popoverTop< 0 ? 0: popoverTop; arrowPosition = 'top'; } } -- Gitee From 63cf3e5d5f38984ec7517ea5b36bbf0f121824c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 3 Mar 2025 10:00:39 +0800 Subject: [PATCH 026/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E9=9B=86=E6=88=90=E5=88=86=E9=A1=B5=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/lookup-container.component.tsx | 17 +- .../lookup/src/composition/types.ts | 2 + .../lookup/src/composition/use-dialog.ts | 27 +-- .../lookup/src/composition/use-state.ts | 3 +- .../converters/lookup-property.converter.ts | 104 +++++++++++ .../property-config/lookup.property-config.ts | 163 +++++++++++++++--- .../lookup/src/schema/lookup.schema.json | 12 ++ .../src/property-panel.component.tsx | 3 +- 8 files changed, 291 insertions(+), 40 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx index b57ddb68901..2fbaeb08c53 100644 --- a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx @@ -10,7 +10,7 @@ import { useSearchbar } from "../composition/use-search-bar"; import { useCheckProps } from "../composition/use-check-props"; import { useNavigation } from "../composition/use-navigation"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../composition/use-http"; -import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "../composition/types"; +import { DefaultDialogTitle, LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "../composition/types"; export default defineComponent({ name: "LookupContainer", @@ -22,7 +22,7 @@ export default defineComponent({ const currentTab = inject>(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; const { lookupStates } = useHttpComposition; - const { lookupState, navigationState, queryState } = lookupStates; + const { lookupState, navigationState, queryState, lookupOptions} = lookupStates; const { renderSearchBar } = useSearchbar(props, false, lookupStates); const { isDoubleList, getNavigationSize, isTreeList } = useCheckProps(props, lookupStates); @@ -57,6 +57,14 @@ export default defineComponent({ } } + function setDialogTitle(title: string) { + const dialogTitle = lookupOptions.dialog?.title; + if (dialogTitle || dialogTitle !== DefaultDialogTitle) { + title = dialogTitle; + } + context.emit('changeDialogOptions', {title}); + } + function initData() { const params: Record = {}; if (props.enableToSelect) { @@ -86,13 +94,10 @@ export default defineComponent({ lookupState[key] = result[key]; }); - context.emit('changeDialogOptions', {title: result.title}); + setDialogTitle(result.title || ''); }); } - watch(() => currentTab.value, (newValue, oldValue) => { - // console.log(newValue, oldValue); - }); onMounted(() => { initData(); diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 8f06b80efdc..7220b5f78a9 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -1,3 +1,5 @@ +export const DefaultDialogTitle = '请选择'; + export interface SearchParams { field: string; value: string; diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index fe676abdd44..e34c8d7d0a7 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -27,7 +27,7 @@ export function useDialog( const notifyService: FNotifyService | null = inject(F_NOTIFY_SERVICE_TOKEN, null); const loadingService: any | null = inject('FLoadingService'); - const dialogOptions = ref(props.dialog); + const dialogSize = ref(); const dialogCloseType = ref(CloseType.accept); const customData = ref(); @@ -35,6 +35,9 @@ export function useDialog( const { lookupStates } = useHttp; const { queryState, lookupState, navigationState, pageInfoState, searchState, selectionState, lookupOptions } = lookupStates; const { isDoubleList } = useCheckProps(props, lookupStates); + + const dialogOptions = lookupOptions.dialog; + async function updateModelValue() { const displayText = selectedItems.value.map((item: any) => { return item[lookupOptions.textField]; @@ -123,17 +126,17 @@ export function useDialog( } function getDefaultDialogSize() { - const height = dialogOptions.value?.height || 620; - const width = dialogOptions.value?.width || 590; - const minWidth = dialogOptions.value?.minWidth || 300; - const minHeight = dialogOptions.value?.minHeight || 200; + const height = dialogOptions?.height || 620; + const width = dialogOptions?.width || 590; + const minWidth = dialogOptions?.minWidth || 300; + const minHeight = dialogOptions?.minHeight || 200; const defaultSize = { height, width, minWidth, minHeight }; if (isDoubleList()) { - defaultSize.width = dialogOptions.value?.width || 960; + defaultSize.width = dialogOptions?.width || 960; } return defaultSize; @@ -142,7 +145,7 @@ export function useDialog( const { width, height, minHeight, minWidth } = getDefaultDialogSize(); const modalOptions = { - title: dialogOptions.value?.title, + title: dialogOptions?.title, fitContent: false, showHeader: false, dragHandle: '.lookup-modal-header', @@ -184,9 +187,11 @@ export function useDialog( }, showButtons: false, resizeHandle: ($event: any) => { - dialogSize.value = $event; - const { width, height } = $event.newSize.size; - userDataService.setDialogSize({ width: Math.round(width), height: Math.round(height) }); + if (props.dialog?.rememberSize) { + dialogSize.value = $event; + const { width, height } = $event.newSize.size; + userDataService.setDialogSize({ width: Math.round(width), height: Math.round(height) }); + } }, enableEnter: true, onEnter: ($event: any) => { @@ -213,7 +218,7 @@ export function useDialog( let shouldContinue = true; await userDataService.getUserData(); - if (userDataService?.userDataState?.data) { + if (userDataService?.userDataState?.data && props.enableUserData && props.dialog?.rememberSize) { const { size } = userDataService.userDataState.data; if (size) { Object.assign(modalOptions, size); diff --git a/packages/ui-vue/components/lookup/src/composition/use-state.ts b/packages/ui-vue/components/lookup/src/composition/use-state.ts index fa7ec46bff6..78b56a633ca 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-state.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-state.ts @@ -35,7 +35,8 @@ export function useLookupState(props: LookupProps): LookupStates { 'loader', 'idField', 'textField', - 'userDataKey' + 'userDataKey', + 'dialog' ]; function initAllowSetOptions() { diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index e3001910cf0..9ebe00b23b2 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -1,3 +1,5 @@ +import { DefaultDialogTitle } from "../../composition/types"; + export const lookupDefaultConverter = { convertFrom: (schema: Record, propertyKey: string) => { if (propertyKey === 'multiSelect') { @@ -32,6 +34,20 @@ function generateSourceUri(ctrlId: string) { return 'lookup.' + code; } +function setPageInfo(editor: any, pageInfo: any) { + const { enablePager, pageSize, pageList } = pageInfo; + editor.pagination = editor.pagination || {}; + + Object.assign(editor.pagination, { + enable: enablePager, + sizeLimits: pageList, + size: pageSize, + showLimits: true, + showGoto: false, + mode: 'server' + }); +} + export const lookupDataSourceConverter = { convertFrom: (schema: Record, propertyKey: string) => { return schema.editor[propertyKey]?.displayName; @@ -54,6 +70,10 @@ export const lookupDataSourceConverter = { schema.editor.textField = textField; schema.editor.dataSource.type = "ViewObject"; + + const {pageInfo} = metadataContent.dataSource; + setPageInfo(schema.editor, pageInfo); + // if (lookupDataSourceConverter['entityCode']) { // const code = lookupDataSourceConverter['entityCode']; // const field = schema.editor.dataSource.bindingField; @@ -98,3 +118,87 @@ export const lookupDisplayTypeConverter = { schema.editor.displayType = propertyValue; } }; + +export const lookupDialogOptionsConverter = { + convertFrom: (schema: Record, propertyKey: string) => { + const options = schema.editor.dialog || {}; + if (propertyKey === 'title') { + return options[propertyKey] || DefaultDialogTitle; + } + + if (propertyKey === 'width') { + if (schema.editor.displayType?.toUpperCase().startsWith('NAV')) { + return options[propertyKey] || 960; + } + return options[propertyKey] || 590; + } + + if (propertyKey === 'height') { + return options[propertyKey] || 620; + } + + if (propertyKey === 'rememberSize') { + return options[propertyKey] === undefined? !!schema.editor.enableUserData: options[propertyKey]; + } + + if (propertyKey ==='navigatorWidth') { + return options[propertyKey] || 300; + } + + }, + convertTo: (schema: Record, propertyKey: string, propertyValue: any) => { + schema.editor.dialog = schema.editor.dialog || {}; + schema.editor.dialog[propertyKey] = propertyValue; + } +}; + + +export function getPageList(limitStr) { + if (limitStr) { + let pageSizeList: any = []; + if (typeof limitStr === 'string') { + pageSizeList = limitStr.replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '').split(','); + } + if (Array.isArray(limitStr)) { + pageSizeList = limitStr; + } + + return pageSizeList.map((item) => { + return {value: parseInt(item, 10) }; + }); + } + return []; +} + +export const lookupPaginationConverter = { + convertFrom: (schema: Record, propertyKey: string) => { + const options = schema.editor.pagination || {}; + if (propertyKey === 'enable') { + return options[propertyKey] || true; + } + if (propertyKey === 'showLimits') { + return options[propertyKey] || true; + } + + if (propertyKey === 'sizeLimits') { + const limitStr = options[propertyKey] || '[10, 20, 50, 100]'; + return getPageList(limitStr); + } + + if (propertyKey === 'size') { + return options[propertyKey] || 20; + } + }, + convertTo: (schema: Record, propertyKey: string, propertyValue: any) => { + schema.editor.pagination = schema.editor.pagination || {}; + if (propertyKey === 'sizeLimits') { + const limitStr = propertyValue.value.map((item) => { + return item.value; + }).join(','); + schema.editor.pagination[propertyKey] = `[${limitStr}]`; + return; + } + + schema.editor.pagination[propertyKey] = propertyValue; + } +}; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 781dd64b9f0..a0682655bab 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -4,7 +4,10 @@ import { lookupDataSourceConverter, lookupDisplayTypeConverter, lookupIdFieldConverter, lookupDefaultConverter, lookupVisibleConverter, - lookupTextFieldConverter + lookupTextFieldConverter, + lookupDialogOptionsConverter, + lookupPaginationConverter, + getPageList } from "./converters/lookup-property.converter"; import { DesignerComponentInstance } from "../../../designer-canvas/src/types"; import { LookupEvents } from "./lookup-events"; @@ -25,6 +28,8 @@ export class LookupPropertyConfig extends InputBaseProperty { const behavior = this.getBehaviorConfig(propertyData); const lookup = this.getLookupConfig(propertyData.editor); const eventsEditor = this.getEventPropConfig(propertyData); + const dialog = this.getDialogPropertyConfig(propertyData); + const pager = this.getPageConfig(propertyData.editor); return { type: 'object', @@ -33,7 +38,9 @@ export class LookupPropertyConfig extends InputBaseProperty { appearance, // behavior, lookup, - eventsEditor + eventsEditor, + dialog, + pager } }; } @@ -86,11 +93,11 @@ export class LookupPropertyConfig extends InputBaseProperty { return false; } - private getDisplayType(propertyData) { - return propertyData.displayType? propertyData.displayType.toUpperCase(): ''; + private getDisplayType(editorOptions: any) { + return editorOptions.displayType? editorOptions.displayType.toUpperCase(): ''; } - private getLookupConfig(propertyData: any) { + private getLookupConfig(editorOptions: any) { return { description: "Basic Infomation", title: "编辑器", @@ -118,7 +125,7 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "schema-selector", title: "选择数据源", editorParams: { - propertyData, + propertyData: editorOptions, formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo() }, viewOptions: [ @@ -177,7 +184,7 @@ export class LookupPropertyConfig extends InputBaseProperty { textField: 'bindingPath', idField: 'bindingPath', editorParams: { - propertyData, + propertyData: editorOptions, formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo() }, columns: [ @@ -199,7 +206,7 @@ export class LookupPropertyConfig extends InputBaseProperty { textField: 'bindingPath', idField: 'bindingPath', editorParams: { - propertyData, + propertyData: editorOptions, formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo() }, columns: [ @@ -221,7 +228,7 @@ export class LookupPropertyConfig extends InputBaseProperty { modalHeight: 600, editable: false, editorParams: { - propertyData, + propertyData: editorOptions, formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo() }, fromData: { @@ -259,7 +266,7 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDefaultConverter, title: "显示已选记录", type: "boolean", - visible: !!propertyData.multiSelect + visible: !!editorOptions.multiSelect }, separator: { description: "多选分隔符", @@ -279,7 +286,7 @@ export class LookupPropertyConfig extends InputBaseProperty { idField: 'value', valueField: 'value' }, - visible: !!propertyData.multiSelect + visible: !!editorOptions.multiSelect }, enableSearchBar: { description: "显示搜索工具条", @@ -293,7 +300,7 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDefaultConverter, title: "允许查询所有列", type: "boolean", - visible: propertyData.enableSearchBar == null ? true: !!propertyData.enableSearchBar + visible: editorOptions.enableSearchBar == null ? true: !!editorOptions.enableSearchBar }, enableFavorite: { description: "启用收藏夹", @@ -301,37 +308,151 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "启用收藏夹", type: "boolean", }, - enableUserData: { - description: "保存界面状态", - $converter: lookupDefaultConverter, - title: "保存界面状态", - type: "boolean", - }, treeToList: { description: "以列表的形式展示树结构数据", $converter: lookupDefaultConverter, title: "树结构数据以列表的形式展示", type: "boolean", - visible: this.getDisplayType(propertyData) === 'TREELIST' + visible: this.getDisplayType(editorOptions) === 'TREELIST' }, navTreeToList:{ description: "以列表的形式展示树结构数据", $converter: lookupDefaultConverter, title: "树结构数据以列表的形式展示", type: "boolean", - visible: this.getDisplayType(propertyData) === 'NAVTREELIST' + visible: this.getDisplayType(editorOptions) === 'NAVTREELIST' }, showNavigation: { description: "显示导航栏", $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, title: "显示导航栏", type: "boolean", - visible: this.getDisplayType(propertyData).includes('NAV') + visible: this.getDisplayType(editorOptions).includes('NAV') + }, + enableUserData: { + description: "保存界面状态", + $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, + title: "保存界面状态", + type: "boolean", } } }; } + showNavigatiorWidth(editorOptions: any) { + const isDoubleList = this.getDisplayType(editorOptions).startsWith('NAV'); + if (isDoubleList) { + return editorOptions.showNavigation === undefined ? true: !!editorOptions.showNavigation; + } + return false; + } + + private getDialogPropertyConfig(propertyData: any) { + return { + description: "帮助窗口尺寸配置", + title: "帮助窗口", + properties: { + title: { + description: "帮助标题", + title: "帮助标题", + type: "string", + $converter: lookupDialogOptionsConverter + }, + width: { + description: "", + title: "窗口宽度", + type: "number", + $converter: lookupDialogOptionsConverter + }, + height: { + title: "窗口高度", + type: "number", + $converter: lookupDialogOptionsConverter + }, + navigatorWidth: { + title: "导航栏宽度", + type: "number", + $converter: lookupDialogOptionsConverter, + visible: this.showNavigatiorWidth(propertyData.editor) + }, + rememberSize: { + description: "记录窗口尺寸", + title: "记录窗口尺寸", + type: "boolean", + $converter: lookupDialogOptionsConverter, + visible: !!propertyData.editor.enableUserData + } + } + }; + } + + private showPagerProperty(editorOptions: any, propertyName?: string) { + const show = this.getDisplayType(editorOptions) !== 'TREELIST' && editorOptions.pagination && editorOptions.pagination.enable; + if (propertyName && show) { + return editorOptions.pagination[propertyName]; + } + return show; + } + + private getPageConfig(editorOptions: any) { + return { + hide: this.getDisplayType(editorOptions) === 'TREELIST', + description: "分页配置", + title: "分页", + properties: { + enable: { + description: "启用分页", + title: "启用分页", + type: "boolean", + refreshPanelAfterChanged: true, + $converter: lookupPaginationConverter + }, + showLimits: { + description: "显示每页条数选择器", + title: "显示每页条数选择器", + type: "boolean", + refreshPanelAfterChanged: true, + $converter: lookupPaginationConverter, + visible: this.showPagerProperty(editorOptions) + }, + sizeLimits: { + description: "每页可显示条数", + title: "每页可显示条数", + type: "array", + $converter: lookupPaginationConverter, + refreshPanelAfterChanged: true, + visible: this.showPagerProperty(editorOptions, 'showLimits'), + editor: { + columns: [ + { field: 'value', title: '值', dataType: 'number' }, + ], + type: "item-collection-editor", + valueField: 'value', + nameField: 'value', + requiredFields: ['value'], + uniqueFields: ['value'], + modelValue: getPageList(editorOptions.pagination?.sizeLimits) + } + }, + size: { + description: "默认显示条数", + title: "默认显示条数", + type: "number", + visible: this.showPagerProperty(editorOptions), + $converter: lookupPaginationConverter, + editor: { + ...this.comboListEditor, + data: getPageList(editorOptions.pagination?.sizeLimits), + textField: 'value', + valueField: 'value' + } + }, + } + }; + } + private getEventPropConfig(propertyData: any) { const self = this; const events = LookupEvents; diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index faf831fc91f..2ac6d7d2467 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -179,6 +179,18 @@ "searchAnyField": { "type": "boolean", "default": true + }, + "dialog": { + "type": "object", + "default": null + }, + "idField": { + "type": "string", + "default": "id" + }, + "pagination": { + "type": "object", + "default": null } }, "required": [ diff --git a/packages/ui-vue/components/property-panel/src/property-panel.component.tsx b/packages/ui-vue/components/property-panel/src/property-panel.component.tsx index c9463d4476a..be9bd7a0ced 100644 --- a/packages/ui-vue/components/property-panel/src/property-panel.component.tsx +++ b/packages/ui-vue/components/property-panel/src/property-panel.component.tsx @@ -398,8 +398,9 @@ export default defineComponent({
    {selectedTab.value?.categoryList?.map((category: ElementPropertyConfig) => { return ( + !category.hide &&
  • - {!category.hide && !category.hideTitle && ( + {!category.hideTitle && ( changeStatus(category)}> Date: Mon, 3 Mar 2025 15:26:39 +0800 Subject: [PATCH 027/156] =?UTF-8?q?fix:=20=E9=9B=86=E6=88=90=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=8A=A0=E8=BD=BD=E5=89=8D=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/types.ts | 9 ++ .../lookup/src/composition/use-context.ts | 8 ++ .../lookup/src/composition/use-dialog.ts | 8 +- .../lookup/src/composition/use-freeinput.ts | 12 ++ .../lookup/src/composition/use-http.ts | 14 ++- .../src/composition/use-input-change.ts | 10 +- .../lookup/src/lookup.component.tsx | 17 +-- .../components/lookup/src/lookup.props.ts | 11 +- .../converters/lookup-property.converter.ts | 12 +- .../src/property-config/lookup-events.ts | 27 +++-- .../property-config/lookup.property-config.ts | 108 +++++++++++++++--- .../lookup/src/schema/lookup.schema.json | 26 ++++- 12 files changed, 195 insertions(+), 67 deletions(-) create mode 100644 packages/ui-vue/components/lookup/src/composition/use-context.ts create mode 100644 packages/ui-vue/components/lookup/src/composition/use-freeinput.ts diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 7220b5f78a9..8db8c8e8f2e 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -20,6 +20,12 @@ export enum LoadTreeDataType { async = 'async' } +export enum OnlySelectLeaf { + default = 'default', + yes = 'yes', + no = 'no' +} + export interface PagerChangeParams{ pageIndex?: number; @@ -36,6 +42,7 @@ export type BeforeOpenDialogFunction = (params?: any) => Promise CanSelectResult; export type CallBackFunction = (items: any[], options: Record) => Promise; + export const LOOKUP_ACTIVE_TAB = '__lookup_active_tab__'; export const LOOKUP_USER_DATA_ID = '__lookup_user_data_id__'; @@ -253,3 +260,5 @@ export interface PagerInfoSate { navigation?: LookupPagination; default: LookupPagination; } + +export type BeforeLoadData = (params: {data: LookupHttpResult}) => Promise; diff --git a/packages/ui-vue/components/lookup/src/composition/use-context.ts b/packages/ui-vue/components/lookup/src/composition/use-context.ts new file mode 100644 index 00000000000..30de872e0f4 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/composition/use-context.ts @@ -0,0 +1,8 @@ +export function useContext(props: any, params: { items: any, mappingFields: any}) { + if (props.context) { + const { editor } = props.context; + if (editor) { + Object.assign(editor, params); + } + } +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index e34c8d7d0a7..20bcd733c23 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -6,6 +6,7 @@ import { LookupProps } from "../lookup.props"; import { useCheckProps } from "./use-check-props"; import { UserDataService } from "./use-user-data"; import { UseHttpComposition } from "./use-http"; +import { useContext } from "./use-context"; /** 窗口关闭类型 */ enum CloseType { @@ -55,12 +56,7 @@ export function useDialog( const mappingInfo = { items: selectedItems.value, mappingFields: lookupOptions.mappingFields }; context.emit('update:dataMapping', mappingInfo); - if (props.context) { - const { editor } = props.context; - if (editor) { - Object.assign(editor, mappingInfo); - } - } + useContext(props, mappingInfo); await dictPicked({ items: selectedItems.value }); diff --git a/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts b/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts new file mode 100644 index 00000000000..20611a75d02 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts @@ -0,0 +1,12 @@ +import { useContext } from "./use-context"; + +export function useFreeInput(props: any, context: any, inputValue: string, lookupOptions: any) { + if (!props.editable) { + return; + } + context.emit('update:modelValue', inputValue); + context.emit('update:idValue', ''); + const clearParams = {items: null, mappingFields: lookupOptions.mappingFields}; + useContext(props, clearParams); + +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 3fe5189b6c1..eac7d2d4edd 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -252,14 +252,16 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { }); } - function loadData(event: any, callback: (e: LookupHttpResult) => void) { + async function loadData(event: any, callback: (e: LookupHttpResult) => void) { const params = buildQueryParams(event) as Partial; const loadingInstance = loadingService?.show(); - getData(params).then((req: Partial) => { - // loadingService?.clearAll(); - loadingInstance.value?.close(); - callback(req); - }); + let httpResult = await getData(params); + loadingInstance.value?.close(); + + if (props.beforeLoadData) { + httpResult = await props.beforeLoadData({data: httpResult}); + } + callback(httpResult); } function updateIncludeChilds(checked: boolean) { diff --git a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts index 4f7efcdad12..17d2317742c 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts @@ -4,6 +4,7 @@ import { isEmpty } from "lodash-es"; import { UseHttpComposition } from "./use-http"; import { BeforeOpenDialogFunction, LookupHttpResult } from "./types"; import { LookupProps } from "../lookup.props"; +import { useFreeInput } from "./use-freeinput"; export type LookupInputChangeOptions = { updateModelValue: () => void; @@ -12,13 +13,14 @@ export type LookupInputChangeOptions = { beforeOpenDialog: BeforeOpenDialogFunction; modelValue: Ref; useHttpComposition: UseHttpComposition; + lookupOptions: any }; export function useInputChange(props: LookupProps, context: any, options: LookupInputChangeOptions) { const changeOnBlur = computed(() => props.textChangeType === 'blur' || props.textChangeType === 'any'); const changeOnEnter = computed(() => props.textChangeType === 'enter' || props.textChangeType === 'any'); - const {beforeOpenDialog, updateModelValue, selectedItems, openDialog, modelValue, useHttpComposition} = options; + const {beforeOpenDialog, updateModelValue, selectedItems, openDialog, lookupOptions, useHttpComposition} = options; const {updateSearchFieldTitle} = useHttpComposition; const isClear = ref(false); @@ -78,6 +80,12 @@ export function useInputChange(props: LookupProps, context: any, options: Lookup if (searchText !== '') { searchText = searchText.trim(); } + + if (props.allowFreeInput) { + useFreeInput(props, context, searchText, lookupOptions); + return; + } + if (isTextChange(searchText)) { if (props.uri) { queryDataBySearchKeys(searchText); diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index f7a0c3b6858..3f2fe74e35d 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -30,6 +30,7 @@ import { useInputChange } from './composition/use-input-change'; import { useHttp } from './composition/use-http'; import { useUserData } from './composition/use-user-data'; import { useSelections } from './composition/use-selections'; +import { useContext } from './composition/use-context'; export default defineComponent({ @@ -75,7 +76,7 @@ export default defineComponent({ }); const { onInputBlur, onEnterKeyDown, isClear } = useInputChange(props, context, - { beforeOpenDialog, updateModelValue, selectedItems: selectionState, openDialog, modelValue, useHttpComposition }); + { beforeOpenDialog, updateModelValue, selectedItems: selectionState, openDialog, modelValue, useHttpComposition, lookupOptions }); const modalConfigs = reactive(modalOptions); @@ -98,12 +99,7 @@ export default defineComponent({ }); onUnmounted(() => { - if (props.context) { - const { editor } = props.context; - if (editor) { - Object.assign(editor, { items: [], mappingFields: {} }); - } - } + useContext(props, { items: [], mappingFields: {} }); }); watch(() => dialogSize.value, (newSizeValue) => { @@ -117,12 +113,7 @@ export default defineComponent({ const clearParams = {items: null, mappingFields: lookupOptions.mappingFields}; context.emit('clear', clearParams); - if (props.context) { - const { editor } = props.context; - if (editor) { - Object.assign(editor, clearParams); - } - } + useContext(props, clearParams); } watch(() => isClear.value, (newValue) => { diff --git a/packages/ui-vue/components/lookup/src/lookup.props.ts b/packages/ui-vue/components/lookup/src/lookup.props.ts index 1185b9d66b2..4e487828237 100644 --- a/packages/ui-vue/components/lookup/src/lookup.props.ts +++ b/packages/ui-vue/components/lookup/src/lookup.props.ts @@ -6,8 +6,9 @@ import { schemaMapper } from './schema/schema-mapper'; import lookupSchema from './schema/lookup.schema.json'; import { schemaResolver } from './schema/schema-resolver'; import { BeforeOpenDialogFunction, BeforeSubmitFunction, CallBackFunction, LoadTreeDataType, - LookupDisplayType, LookupIdValueType, LookupPagination, - NavigationOptions, SearchField, TextChangedType } from "./composition/types"; + LookupDisplayType, LookupIdValueType, LookupPagination, OnlySelectLeaf, + NavigationOptions, SearchField, TextChangedType, + BeforeLoadData} from "./composition/types"; export const lookupProps = { id: {type: String, require: true}, @@ -48,6 +49,7 @@ export const lookupProps = { dictPicking: {type: Function as PropType, default: null}, dictPicked: {type: Function as PropType, default: null}, beforeSelectData: {type: Function as PropType, default: null}, + beforeLoadData: {type: Function as PropType, default: null}, enableSearchBar: { type: Boolean, default: true }, searchFields: { type: Array as PropType, default: [] }, searchAnyField: { type: Boolean, default: true }, @@ -68,7 +70,10 @@ export const lookupProps = { onReady: { type: Function, default: null }, context: { type: Object, default: {} }, placeholder: { type: String, default: '请选择' }, - loader: { type: Function, default: null } + loader: { type: Function, default: null }, + allowFreeInput: { type: Boolean, default: false }, + onlySelectLeaf: { type: String as PropType, default: OnlySelectLeaf.default }, + enableFullTree: { type: Boolean, default: true } } as Record; export type LookupProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index 96430139714..1054e0b7cca 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -154,20 +154,18 @@ export const lookupDialogOptionsConverter = { export function getPageList(limitStr) { + let pageSizeList: any = [10, 20, 30, 50, 100]; if (limitStr) { - let pageSizeList: any = []; if (typeof limitStr === 'string') { pageSizeList = limitStr.replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '').split(','); } if (Array.isArray(limitStr)) { pageSizeList = limitStr; } - - return pageSizeList.map((item) => { - return {value: parseInt(item, 10) }; - }); } - return []; + return pageSizeList.map((item) => { + return {value: parseInt(item, 10) }; + }); } export const lookupPaginationConverter = { @@ -181,7 +179,7 @@ export const lookupPaginationConverter = { } if (propertyKey === 'sizeLimits') { - const limitStr = options[propertyKey] || '[10, 20, 50, 100]'; + const limitStr = options[propertyKey]; return getPageList(limitStr); } diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts b/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts index be2ea057f66..b68d1a1bc5c 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup-events.ts @@ -1,12 +1,15 @@ -export const LookupEvents = [{ - label: 'dictPicking', - name: '帮助前事件' -}, -{ - label: 'dictPicked', - name: '帮助后事件' -}, -{ - label: 'beforeSelectData', - name: '数据选择确认前事件' -}]; +export const LookupEvents = [ + { + label: 'dictPicking', + name: '帮助前事件' + }, { + label: 'dictPicked', + name: '帮助后事件' + }, { + label: 'beforeSelectData', + name: '数据选择确认前事件' + }, { + label: 'beforeLoadData', + name: '数据加载前事件' + } +]; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 8d50311fff3..dd0e9f38798 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -31,6 +31,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const eventsEditor = this.getEventPropConfig(propertyData); const dialog = this.getDialogPropertyConfig(propertyData); const pager = this.getPageConfig(propertyData.editor); + const treeConfig = this.getTreePropConfig(propertyData.editor); return { type: 'object', @@ -39,6 +40,7 @@ export class LookupPropertyConfig extends InputBaseProperty { appearance, // behavior, lookup, + treeConfig, eventsEditor, dialog, pager @@ -121,8 +123,17 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "允许编辑", type: "boolean", $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, editor: this.comboListEditor }, + allowFreeInput: { + description: "", + title: "任意输入", + type: "boolean", + $converter: lookupDefaultConverter, + editor: this.comboListEditor, + visible: !!editorOptions.editable + }, dataSource: { description: "数据源", title: "数据源", @@ -150,7 +161,7 @@ export class LookupPropertyConfig extends InputBaseProperty { repositoryToken: LookupSchemaRepositoryToken, onSubmitModal: (dataSourceSchema: any) => { if (dataSourceSchema) { - delete propertyData.mappingFields; + delete editorOptions.mappingFields; const formInfo = this.formSchemaUtils.getFormMetadataBasicInfo(); // 获取数据源详细配置信息 return this.metadataService.getPickMetadata(formInfo.relativePath, dataSourceSchema[0].data) @@ -267,7 +278,7 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "boolean", editor: this.comboListEditor, refreshPanelAfterChanged: true, - visible: false // this.isSimpleStringField() + visible: this.isSimpleStringField() }, showSelections: { description: "显示已选记录", @@ -316,20 +327,7 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "启用收藏夹", type: "boolean", }, - treeToList: { - description: "以列表的形式展示树结构数据", - $converter: lookupDefaultConverter, - title: "树结构数据以列表的形式展示", - type: "boolean", - visible: this.getDisplayType(editorOptions) === 'TREELIST' - }, - navTreeToList:{ - description: "以列表的形式展示树结构数据", - $converter: lookupDefaultConverter, - title: "树结构数据以列表的形式展示", - type: "boolean", - visible: this.getDisplayType(editorOptions) === 'NAVTREELIST' - }, + showNavigation: { description: "显示导航栏", $converter: lookupDefaultConverter, @@ -419,7 +417,7 @@ export class LookupPropertyConfig extends InputBaseProperty { }, showLimits: { description: "显示每页条数选择器", - title: "显示每页条数选择器", + title: "显示条数选择器", type: "boolean", refreshPanelAfterChanged: true, $converter: lookupPaginationConverter, @@ -427,7 +425,7 @@ export class LookupPropertyConfig extends InputBaseProperty { }, sizeLimits: { description: "每页可显示条数", - title: "每页可显示条数", + title: "每页显示条数", type: "array", $converter: lookupPaginationConverter, refreshPanelAfterChanged: true, @@ -461,6 +459,80 @@ export class LookupPropertyConfig extends InputBaseProperty { }; } + private showLoadType(editorOptions: any) { + const displayType = this.getDisplayType(editorOptions); + return (displayType === 'TREELIST' || displayType === 'NAVTREELIST') && + !editorOptions.treeToList && !editorOptions.navTreeToList; + } + + private getTreePropConfig(editorOptions: any) { + return { + hide: this.getDisplayType(editorOptions) !== 'TREELIST', + description: "树形数据配置", + title: "树形数据配置", + properties: { + treeToList: { + description: "以列表的形式展示树结构数据", + $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, + title: "以列表形式展示", + type: "boolean", + visible: this.getDisplayType(editorOptions) === 'TREELIST' + }, + navTreeToList:{ + description: "以列表的形式展示树结构数据", + $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, + title: "以列表形式展示", + type: "boolean", + visible: this.getDisplayType(editorOptions) === 'NAVTREELIST' + }, + enableFullTree: { + description: "启用构造完整树", + $converter: lookupDefaultConverter, + title: "构造完整树", + type: "boolean", + visible: !editorOptions.treeToList && !editorOptions.navTreeToList + }, + onlySelectLeaf: { + description: "仅选择叶子节点", + $converter: lookupDefaultConverter, + title: "仅选择叶子节点", + type: "string", + visible: this.getDisplayType(editorOptions) === 'TREELIST' && !editorOptions.treeToList, + editor: { + ...this.comboListEditor, + data: [ + { value: 'default', text: '默认' }, + { value: 'yes', text: '是' }, + { value: 'no', text: '否'} + ], + textField: 'text', + valueField: 'value' + } + }, + loadTreeDataType: { + description: "树形数据加载方式", + $converter: lookupDefaultConverter, + title: "数据加载方式", + type: "string", + editor: { + ...this.comboListEditor, + data: [ + { value: 'default', text: '默认' }, + { value: 'all', text: '全部加载' }, + { value: 'async', text: '分层加载'} + ], + textField: 'text', + valueField: 'value' + }, + visible: this.showLoadType(editorOptions) + } + + } + }; + } + private getEventPropConfig(propertyData: any) { const self = this; const events = LookupEvents; diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index 2ac6d7d2467..bea650f73c5 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -35,7 +35,7 @@ "editable": { "description": "", "type": "boolean", - "default": true + "default": false }, "enableLinkLabel": { "description": "", @@ -191,6 +191,30 @@ "pagination": { "type": "object", "default": null + }, + "allowFreeInput": { + "type": "boolean", + "default": false + }, + "loadTreeDataType": { + "type": "string", + "default": "default" + }, + "onlySelectLeaf": { + "type": "boolean", + "default": false + }, + "enableFullTree": { + "type": "boolean", + "default": true + }, + "beforeLoadData": { + "type": "object", + "default": null + }, + "beforeSelectData": { + "type": "object", + "default": null } }, "required": [ -- Gitee From be25667e0a8d5d59d03e6018fae18228ea05ea63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 3 Mar 2025 16:25:20 +0800 Subject: [PATCH 028/156] =?UTF-8?q?fix:=20lookup=E6=A0=91=E5=BD=A2?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E6=95=B0=E6=8D=AE=E6=9F=A5=E8=AF=A2=E5=90=8E?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E6=89=80=E6=9C=89=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-http.ts | 17 ++++++++++++++++- .../lookup/src/composition/use-navigation.tsx | 5 ++++- .../lookup/src/composition/use-treegrid.tsx | 7 ++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 8e29f451635..b26936c1a9b 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -16,6 +16,7 @@ export interface UseHttpComposition { loadData: (event: any, callback: (data: LookupHttpResult) => void) => void; getData: (params: any) => Promise; updateSearchFieldTitle: (searchFields: any[], columns: any[]) => any[]; + expandAllNodes: (treeNodes: any[]) => any[]; } export function useHttp(props: any, context: any): UseHttpComposition { @@ -233,10 +234,24 @@ export function useHttp(props: any, context: any): UseHttpComposition { }); } + function expandAllNodes(nodes: any[]): any[] { + if (nodes && nodes.length) { + return nodes.map((node: any) => { + if (node.children && node.children.length) { + node.expanded = true; + expandAllNodes(node.children); + } + return node; + }); + } + return nodes; + }; + return { idValues, getData, loadData, - updateSearchFieldTitle + updateSearchFieldTitle, + expandAllNodes }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index b31ec89e325..e1c0a093078 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -16,7 +16,7 @@ export function useNavigation(props: LookupProps, context) { const { renderSearchBar } = useSearchbar(props, true); const { checkPaination, navIsList, navIsTreeList } = useCheckProps(props); const { updatePageInfo } = usePageInfo(props); - const { loadData } = useHttpComposition; + const { loadData, expandAllNodes } = useHttpComposition; const selectedItems = ref([]); if (navIsList()) { @@ -58,6 +58,9 @@ export function useNavigation(props: LookupProps, context) { updatePageInfo(value, true); leftDatagridRef.value?.updateDataSource(items); } else if (navIsTreeList()) { + if (searchState.navigation?.value) { + items = expandAllNodes(items); + } leftTreegridRef.value?.updateDataSource(items); } } diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index 9894c062b40..0d749528451 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -19,9 +19,14 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { const selectionTreeValues = ref([]); const selectedTreeNodes = ref([]); - const { loadData, idValues } = useHttpComposition; + const { loadData, idValues, expandAllNodes } = useHttpComposition; function dataGridLoadData(items: any) { + + if (searchState.default?.value) { + items = expandAllNodes(items); + } + treegridRef.value?.updateDataSource(items || []); if (idValues.value) { treegridRef.value?.selectItemByIds(idValues.value.split(props.separator)); -- Gitee From f0d1bec39421fa23467bb07c0f6474a7f5347ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 3 Mar 2025 17:05:16 +0800 Subject: [PATCH 029/156] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9lookup?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/schema/lookup.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index bea650f73c5..a13687b4ea5 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -198,7 +198,7 @@ }, "loadTreeDataType": { "type": "string", - "default": "default" + "default": "all" }, "onlySelectLeaf": { "type": "boolean", -- Gitee From c585d284351302c1d930e81b13581aa83b78bc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 5 Mar 2025 14:54:54 +0800 Subject: [PATCH 030/156] =?UTF-8?q?feature:=20=E6=A0=91=E8=A1=A8lookup=20?= =?UTF-8?q?=E9=9B=86=E6=88=90=E7=BA=A7=E8=81=94=E9=80=89=E6=8B=A9=E6=8E=A7?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../combo-list/src/combo-list.component.tsx | 3 +- .../combo-list/src/combo-list.props.ts | 4 +- .../src/schema/combo-list.schema.json | 5 + .../cascade/tree-cascade.component.tsx | 31 ++++++ .../favorite/lookup-favorite.component.tsx | 32 +++++-- .../components/lookup-container.component.tsx | 38 +++----- .../components/modal-container.component.tsx | 20 +++- .../src/components/modal-container.props.ts | 4 +- .../lookup-selected-list.component.tsx | 2 +- .../lookup/src/composition/types.ts | 28 +++++- .../lookup/src/composition/use-check-props.ts | 5 +- .../lookup/src/composition/use-favorite.tsx | 22 +++-- .../lookup/src/composition/use-http.ts | 94 ++++++++++++++++++- .../lookup/src/composition/use-navigation.tsx | 7 +- .../lookup/src/composition/use-state.ts | 7 +- .../composition/use-treegrid-row-options.ts | 19 +++- .../lookup/src/composition/use-treegrid.tsx | 19 ++-- .../lookup/src/lookup.component.tsx | 14 ++- .../components/lookup/src/lookup.props.ts | 18 +++- .../converters/lookup-property.converter.ts | 4 + .../property-config/lookup.property-config.ts | 86 ++++++++++++----- .../lookup/src/schema/lookup.schema.json | 29 +++++- .../popover/src/composition/use-popup.ts | 2 +- 23 files changed, 389 insertions(+), 104 deletions(-) create mode 100644 packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx diff --git a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx index 2ec7b144790..145a7b6695f 100644 --- a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx +++ b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx @@ -136,7 +136,8 @@ export default defineComponent({ onChange={onDisplayTextChange} onInput={onInput} beforeOpen={props.beforeOpen} - placement={'auto'} + placement={props.placement} + popupMinWidth={props.panelMinWidth} > ; export type ComboListProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json b/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json index 5ec9a43fb6f..80b8025b9ae 100644 --- a/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json +++ b/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json @@ -134,6 +134,11 @@ "description": "", "type": "number", "default": 350 + }, + "panelMinWidth": { + "description": "", + "type": "number", + "default": 160 } }, "required": [ diff --git a/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx b/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx new file mode 100644 index 00000000000..df0d037b5d0 --- /dev/null +++ b/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx @@ -0,0 +1,31 @@ +import { defineComponent, ref } from "vue"; + +import { FComboList } from "../../../../combo-list"; +import { cascadeItems } from "../../composition/types"; + +export default defineComponent({ + name: 'FLookupCascadeSelector', + props: ['modelValue'], + emits: [], + setup(props, context) { + const cascadeRef = ref(); + + const modelValue = ref(props.modelValue); + + return () => { + return
    + +
    ; + }; + } +}); diff --git a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx index 112f488bdc6..d6ec66dbc87 100644 --- a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx @@ -10,16 +10,18 @@ import { useCheckProps } from "../../composition/use-check-props"; import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "../../composition/use-selections"; import { useSyncSelect } from "../../composition/use-sync-select"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "../../composition/use-http"; +import { LOOKUP_TREEROW_OPTIONS, useTreeRowOptions } from "../../composition/use-treegrid-row-options"; export default defineComponent({ name: 'FLookupFavorite', props: lookupFavoriteComponentProps, setup(props, context) { + const treeRowOptions = inject(LOOKUP_TREEROW_OPTIONS); const {userDataState, getFavoriteData}: any = inject(LOOKUP_USER_DATA_SERVICE); const currentTab = inject>(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; - const { lookupStates} = useHttpComposition; + const { lookupStates, expandAllNodes} = useHttpComposition; const idField = computed(() => { return lookupStates.lookupOptions.idField || 'id'; @@ -27,10 +29,6 @@ export default defineComponent({ const selectIds = ref(props.selectedIds); - watch(() => props.selectedIds, (newValue) => { - selectIds.value = newValue; - }); - const { setColumns, removeFavoriteItem } = useFavorite(props, idField.value); const { isTreeList } = useCheckProps(props, lookupStates); const { updateSelections, unSelectTreeNode, selectTreeNodes} = lookupSelectionsManager; @@ -42,7 +40,6 @@ export default defineComponent({ return isTreeList() ? favoriteTreeGridRef.value : favoriteDataGridRef.value; }); - useSyncSelect(props, gridRef, lookupStates); function hasFavorites() { @@ -56,11 +53,27 @@ export default defineComponent({ } } + + watch(() => props.selectedIds, (newValue, oldValue) => { + if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) { + selectIds.value = newValue; + if (selectIds.value.length) { + selectItem(selectIds.value); + } else { + gridRef.value.clearSelection(); + } + } + }); + function loadFavoriteData(items: any, columns: any) { if (columns && columns.length) { - setColumns(gridRef.value, columns); + setColumns(gridRef.value, columns, isTreeList()); + } + + if (items) { + items = expandAllNodes(items); + gridRef.value.updateDataSource(items || []); } - items && gridRef.value.updateDataSource(items || []); selectItem(selectIds.value || []); } @@ -80,7 +93,7 @@ export default defineComponent({ if (hasFavorites()) { queryFavoriteData(); } else { - loadFavoriteData([], null); + loadFavoriteData([], lookupStates.lookupState?.columns); } } }); @@ -135,6 +148,7 @@ export default defineComponent({ selection={selectionOption} showBorder={true} virtualized={true} + rowOption={treeRowOptions} onSelectionChange={onSelectionChange} onUnSelectItem={onUnSelectItem}>; }; diff --git a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx index 2fbaeb08c53..dc0f927d455 100644 --- a/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/lookup-container.component.tsx @@ -21,7 +21,7 @@ export default defineComponent({ setup(props: LookupProps, context) { const currentTab = inject>(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; - const { lookupStates } = useHttpComposition; + const { lookupStates, getIdQueryParams } = useHttpComposition; const { lookupState, navigationState, queryState, lookupOptions} = lookupStates; const { renderSearchBar } = useSearchbar(props, false, lookupStates); @@ -41,25 +41,10 @@ export default defineComponent({ const leftPanelWidth = getNavigationSize(); - function getIdValues() { - try { - const idvalues = useHttpComposition.idValues.value; - - if (idvalues !== '' && idvalues != null) { - return idvalues; - } - - return ''; - - } catch (error) { - console.error('Error in getIdValues:', error); - return ''; - } - } - + function setDialogTitle(title: string) { const dialogTitle = lookupOptions.dialog?.title; - if (dialogTitle || dialogTitle !== DefaultDialogTitle) { + if (dialogTitle && dialogTitle !== DefaultDialogTitle) { title = dialogTitle; } context.emit('changeDialogOptions', {title}); @@ -68,12 +53,8 @@ export default defineComponent({ function initData() { const params: Record = {}; if (props.enableToSelect) { - let currentIdValues = getIdValues() || []; - if (!Array.isArray(currentIdValues)) { - currentIdValues = (''+ currentIdValues).split(props.separator); - } - - params.selectedInfo = { selectedIds: currentIdValues, selected: true }; + + params.selectedInfo = getIdQueryParams(); if (queryState.value != null) { params.search = {'field': '*', value: queryState.value, type: 'like'}; @@ -87,9 +68,16 @@ export default defineComponent({ navigationState[key] = result.navigation?.[key]; }); + if (result.navigation.treeInfo) { + useHttpComposition?.setTreeInfo(result.navigation.treeInfo, true); + } + delete result.navigation; } - + + if (result.treeInfo) { + useHttpComposition?.setTreeInfo(result.treeInfo); + } Object.keys(result).forEach(key => { lookupState[key] = result[key]; }); diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx index f4d7041c6a1..e7d618554b9 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx @@ -7,7 +7,8 @@ import { LOOKUP_HTTP_COMPOSITION } from "../composition/use-http"; import SelectedList from "./selected-list/lookup-selected-list.component"; import { LOOKUP_SELECTIONS_MANAGER } from "../composition/use-selections"; import LookupIncludeChildCheckbox from './include-child-checkbox/include-child-checkbox.component'; - +import CascadeControl from './cascade/tree-cascade.component'; +import { LOOKUP_TREEROW_OPTIONS, useTreeRowOptions } from "../composition/use-treegrid-row-options"; export default defineComponent({ name: 'FLookupModalContainer', @@ -27,9 +28,21 @@ export default defineComponent({ const { lookupOptions } = props.useHttpComposition.lookupStates; + const isNavigation = lookupOptions.displayType.toUpperCase() === LookupDisplayType.TreeList; + + const treeRowOptions = useTreeRowOptions(lookupOptions, isNavigation); + provide(LOOKUP_TREEROW_OPTIONS, treeRowOptions); + + + const cascadeControlRef = ref(); + + function isTree() { + return lookupOptions.displayType && lookupOptions.displayType.toUpperCase() === LookupDisplayType.Tree; + } + const showIncludeChildNodes = computed(() => { - return includeChildNodesInfo.show && activeTab.value === LookupTabs.dataList && lookupOptions.displayType && - lookupOptions.displayType.toUpperCase() === LookupDisplayType.TreeList; + return includeChildNodesInfo.show && activeTab.value === LookupTabs.dataList + && lookupOptions.displayType && isNavigation; }); const popoverOffsetX = computed(() => { @@ -135,6 +148,7 @@ export default defineComponent({ {showIncludeChildNodes.value && } {props.showSelectedList && } + {props.showCascadeControl && }
diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.props.ts b/packages/ui-vue/components/lookup/src/components/modal-container.props.ts index 9c993f679bb..ebf52c63671 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.props.ts +++ b/packages/ui-vue/components/lookup/src/components/modal-container.props.ts @@ -12,6 +12,8 @@ export const lookupModalContainerProps = { useDialog: { type: Object, default: {} }, selectionsManager: { type: Object, default: {} }, showSelectedList: { type: Boolean, default: false}, - showIncludeChildNodes: { type: Object, default: { show: true, value: false}} + showIncludeChildNodes: { type: Object, default: { show: true, value: false}}, + showCascadeControl: { type: Boolean, default: false }, + cascadeValue: { type: String, default: 'both' } }; export type LookupModalContainerProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx index 0280a9806e1..2c40c04c2af 100644 --- a/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/selected-list/lookup-selected-list.component.tsx @@ -151,7 +151,7 @@ export default defineComponent({ return (<>
已选{selectionState.value.length}
- {showClearButton.value && } + {showClearButton.value && }
Promise; + +export interface CascadeOptions { + /** 是否启用级联控制 */ + enable: boolean; + /** 是否显示级联控制选项 */ + showCascadeControl: boolean; + /** 控制选项中允许的值 */ + cascadeItems: { + both: boolean; + up: boolean; + down: boolean; + disable: boolean; + }; + /** 级联控制默认状态 */ + defaultStatus: 'up'|'down'|'both'|'disable'; +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts index 2ca03a15698..4fc4bfe5a7e 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts @@ -1,5 +1,5 @@ import { LookupProps } from "../lookup.props"; -import { LookupDisplayType, LookupPagination, TreeInfo } from "./types"; +import { LoadTreeDataType, LookupDisplayType, LookupPagination, TreeInfo } from "./types"; import { LookupStates } from "./use-state"; export function useCheckProps(props: LookupProps, lookupStates: LookupStates) { @@ -80,7 +80,8 @@ export function useCheckProps(props: LookupProps, lookupStates: LookupStates) { } function isLoadAll(treeInfo?: TreeInfo) { - return props.loadTreeDataType === 'all' || (props.loadTreeDataType === 'default' && treeInfo?.loadDataType === 'all'); + const {loadTreeDataType} = lookupOptions; + return loadTreeDataType === LoadTreeDataType.all || (loadTreeDataType === 'default' && treeInfo?.loadDataType === 'all'); } function isPathCodeTree(treeInfo?: TreeInfo) { diff --git a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx index 9b632400a87..99e16898876 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx @@ -59,18 +59,28 @@ export function useFavorite(props: LookupProps, idField: string) { updateFavorites({id: itemId, data: row.raw}, !isFavorite.value(row) ? 'add' : 'remove'); } + const favoriteColumnFormatter = (cell, row) => { + return ; + }; + + const favoriteColumnFormatterForTree = (cell, row) => { + if (row.disabled) { + return ''; + } + return favoriteColumnFormatter(cell, row); + }; + const favoriteColumn = { field: favoriteFieldName, title: '', width: 50, fixed: 'right', align: 'center', - formatter: (cell, row) => { - return ; - } + formatter: favoriteColumnFormatter }; - function setColumns(gridInstance: any, columns: any) { + function setColumns(gridInstance: any, columns: any, isTree = false) { const newColumns = cloneDeep(columns); if (props.enableFavorite) { + favoriteColumn.formatter = isTree? favoriteColumnFormatterForTree: favoriteColumnFormatter; newColumns.push(favoriteColumn); } gridInstance?.updateColumns(newColumns); diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 11df2392c5b..4a2e19f2215 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -1,5 +1,5 @@ import { inject, Ref, ref, toRaw } from "vue"; -import { flatten } from "lodash-es"; +import { flatten, isNaN } from "lodash-es"; import { FLoadingService } from "@farris/ui-vue/components/loading"; import { resolveField as getFieldValue } from '@farris/ui-vue/components/common'; @@ -8,7 +8,10 @@ import { resolveField as getFieldValue } from '@farris/ui-vue/components/common import { Compare, FilterRelation, LOAD_DATA_TYPE, F_LOOKUP_HTTP_SERVICE_TOKEN, LookupHttpResult, LookupHttpService, LookupRequestParams, SearchParam, - TreeInfo + TreeInfo, + LookupDisplayType, + LoadTreeDataType, + OnlySelectLeaf } from "./types"; import { useSearchFields } from "./use-search-fields"; import { LookupStates, useLookupState } from "./use-state"; @@ -30,6 +33,8 @@ export interface UseHttpComposition { httpService?: LookupHttpService; lookupRequest: () => (uri, params) => Promise; expandAllNodes: (treeNodes: any[]) => any[]; + getIdQueryParams: () => any; + setTreeInfo: (resData: TreeInfo, isNavigation?: boolean) => void; } export function useHttp(props: LookupProps, context: any): UseHttpComposition { @@ -44,6 +49,51 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { const includeChilds = ref(false); + const isTree = () => { + const displayType = lookupOptions.displayType?.toUpperCase(); + return displayType === LookupDisplayType.Tree || displayType === LookupDisplayType.TreeList; + }; + + const setTreeInfo = (resData: TreeInfo, isNavigation = false) => { + if (resData) { + const { layerType, dataField, parentField, + pathField, layerField, isDetailField, loadDataType, + onlySelectLeaf } = resData; + const treeInfo: TreeInfo = { + layerType, + dataField, + parentField, + pathField, + layerField, + isDetailField, + loadDataType + }; + + const { onlySelectLeaf: selectLeaf, loadTreeDataType } = lookupOptions; + if (typeof selectLeaf === 'boolean') { + treeInfo.onlySelectLeaf = selectLeaf? OnlySelectLeaf.yes: OnlySelectLeaf.no; + } else { + if (selectLeaf === OnlySelectLeaf.default) { + treeInfo.onlySelectLeaf = onlySelectLeaf ? OnlySelectLeaf.yes: OnlySelectLeaf.no; + } else { + treeInfo.onlySelectLeaf = selectLeaf; + } + } + + if (loadTreeDataType === LoadTreeDataType.default) { + lookupOptions.loadTreeDataType = loadDataType === 'all' ? LoadTreeDataType.all: LoadTreeDataType.async; + } else { + treeInfo.loadDataType = loadTreeDataType === LoadTreeDataType.all? 'all': 'async'; + } + + if (isNavigation) { + lookupOptions.navTreeInfo = Object.assign(lookupOptions.navTreeInfo || {}, treeInfo); + } else { + lookupOptions.treeInfo = Object.assign(lookupOptions.treeInfo || {}, treeInfo); + } + }; + }; + function buildConditionsWhenSearchAnyFields(searchFields: any[], searchValues: string): any[] { // 处理空值或只包含空格的情况 if (searchValues == null || !searchValues.trim()) { @@ -131,6 +181,14 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } } + if (isTree()) { + let {expandLevel} = lookupOptions; + if (expandLevel && !isNaN(expandLevel)) { + expandLevel = expandLevel < -1 ? -1: expandLevel; + searchParam.layerNum = expandLevel; + } + } + return { searchParam, navSearchConditions, @@ -177,7 +235,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { queryParams.treeToList = props.treeToList; queryParams.navTreeToList = props.navTreeToList; - queryParams.loadTreeDataType = props.loadTreeDataType; + queryParams.loadTreeDataType = lookupOptions.loadTreeDataType; if (event?.relationFilter) { queryParams.relationFilter = [...event.relationFilter]; @@ -309,6 +367,32 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return nodes; }; + function getIdValues() { + try { + const idvalues = idValues.value; + + if (idvalues !== '' && idvalues != null) { + return idvalues; + } + + return ''; + + } catch (error) { + console.error('Error in getIdValues:', error); + return ''; + } + } + + + function getIdQueryParams() { + let currentIdValues = getIdValues() || []; + if (!Array.isArray(currentIdValues)) { + currentIdValues = (''+ currentIdValues).split(props.separator); + } + + return { selectedIds: currentIdValues, selected: true }; + } + return { includeChilds, updateIncludeChilds, @@ -321,6 +405,8 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { lookupStates, httpService, lookupRequest, - expandAllNodes + expandAllNodes, + getIdQueryParams, + setTreeInfo }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index ccf7129c4c9..7f6a9dcf76f 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -9,12 +9,13 @@ import { useSearchbar } from "./use-search-bar"; import { usePageInfo } from "./use-pageinfo"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "./use-http"; -import { treeGridRowOption } from "./use-treegrid-row-options"; +import { LOOKUP_TREEROW_OPTIONS } from "./use-treegrid-row-options"; export function useNavigation(props: LookupProps, context) { + const treeRowOptions = inject(LOOKUP_TREEROW_OPTIONS); const useHttpComposition: UseHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; const { loadData, lookupStates, expandAllNodes } = useHttpComposition; - const { navigationState, pageInfoState, searchState } = lookupStates; + const { navigationState, pageInfoState, searchState, lookupOptions } = lookupStates; const { renderSearchBar } = useSearchbar(props, true, lookupStates); const { checkPaination, navIsList, navIsTreeList } = useCheckProps(props, lookupStates); @@ -134,7 +135,7 @@ export function useNavigation(props: LookupProps, context) { selection={selectionOptions} virtualized={false} showBorder={ true } - rowOption={treeGridRowOption} + rowOption={treeRowOptions} onSelectionChange={onTreegridSelectionChange}>; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-state.ts b/packages/ui-vue/components/lookup/src/composition/use-state.ts index 78b56a633ca..34e5b7c87bd 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-state.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-state.ts @@ -36,7 +36,12 @@ export function useLookupState(props: LookupProps): LookupStates { 'idField', 'textField', 'userDataKey', - 'dialog' + 'dialog', + 'expandLevel', + 'treeInfo', + 'navTreeInfo', + 'onlySelectLeaf', + 'loadTreeDataType' ]; function initAllowSetOptions() { diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts index e4dfdc691e0..a6cc994efad 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts @@ -1,7 +1,11 @@ import { RowOptions, VisualData } from "@farris/ui-vue/components/data-view"; -export const treeGridRowOption: Partial = { - customRowStatus: (visualData: VisualData) => { +export const LOOKUP_TREEROW_OPTIONS = Symbol('LOOKUP_TREEROW_OPTIONS'); + + +export function useTreeRowOptions(lookupOptions: any, isNavigation = false) { + + function customRowStatus(visualData: VisualData) { if (visualData.collapse === undefined) { visualData.collapse = !visualData.raw.expanded; } @@ -9,6 +13,15 @@ export const treeGridRowOption: Partial = { if (visualData.raw.addtional || visualData.raw.selectable === false) { visualData.disabled = true; } + + const treeinfo = isNavigation? lookupOptions.navTreeInfo : lookupOptions.treeInfo; + + if (treeinfo.onlySelectLeaf === 'yes') { + visualData.disabled = !visualData.raw.leaf; + } + return visualData; } -}; + + return {customRowStatus}; +} diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index 7150c96318d..256fe3958b6 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -7,7 +7,7 @@ import { LookupProps } from "../lookup.props"; import { useCheckProps } from "./use-check-props"; import { LOOKUP_ACTIVE_TAB, LookupHttpResult, LookupTabs } from "./types"; import { LOOKUP_HTTP_COMPOSITION, UseHttpComposition } from "./use-http"; -import { treeGridRowOption } from "./use-treegrid-row-options"; +import { LOOKUP_TREEROW_OPTIONS } from "./use-treegrid-row-options"; import { useFavorite } from "./use-favorite"; import { useSyncSelect } from "./use-sync-select"; import { LOOKUP_SELECTIONS_MANAGER, LookupSelectionsManager } from "./use-selections"; @@ -16,10 +16,11 @@ import { useLoadData } from "./use-load-data"; export function useTreegrid(props: LookupProps, context: SetupContext) { const currentTab = inject(LOOKUP_ACTIVE_TAB, ref(LookupTabs.dataList)); const useHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; + const treeRowOptions = inject(LOOKUP_TREEROW_OPTIONS); + const { lookupStates } = useHttpComposition; const { lookupState, searchState, lookupOptions } = lookupStates; - const lookupSelectionsManager = inject(LOOKUP_SELECTIONS_MANAGER) as LookupSelectionsManager; const { checkMultiSelect, checkColumnOptions } = useCheckProps(props, lookupStates); @@ -56,7 +57,7 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { updateSelections(selectedData); } - newColumns && setColumns(treegridRef.value, newColumns); + newColumns && setColumns(treegridRef.value, newColumns, true); treeGridLoadData(newItems); }); @@ -83,7 +84,12 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { }); - const hierarchy = { cascadeOption: { autoCheckChildren: false, autoCheckParent: false } }; + const hierarchy = { + cascadeOption: { autoCheckChildren: false, autoCheckParent: false } }; + + function onExpandNode(node: any) { + return console.log(node); + } function renderTreeGrid() { @@ -99,10 +105,11 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { showBorder={true} virtualized={false} displayField={'code'} - rowOption={treeGridRowOption} + rowOption={treeRowOptions} hierarchy={hierarchy} onSelectionChange={onSelectionChange} - onUnSelectItem={onUnSelectItem}>; + onUnSelectItem={onUnSelectItem} + onExpandNode={onExpandNode}>; }; return { diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index 3f2fe74e35d..2d28015443d 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -23,7 +23,7 @@ import LookupFavorite from './components/favorite/lookup-favorite.component'; import ModalContainer from './components/modal-container.component'; import { lookupProps, LookupProps } from './lookup.props'; import { useDialog } from './composition/use-dialog'; -import { PagerChangeParams, SearchParams } from './composition/types'; +import { LookupDisplayType, PagerChangeParams, SearchParams } from './composition/types'; import { customData } from "./composition/use-customdata"; import { useLookupCallBack } from './composition/use-lookup-callback'; import { useInputChange } from './composition/use-input-change'; @@ -164,13 +164,16 @@ export default defineComponent({ } } + const showCascadeControl = computed(() => { + return lookupOptions.multiSelect && props.showCascadeControl && props.enableCascade && + LookupDisplayType.Tree === lookupOptions.displayType.toUpperCase(); + }); + const selectedIds = computed(() => { if (selectionState.value && selectionState.value.length) { return selectionState.value.map(item => item[lookupOptions.idField]); - } else { - const idValues = useHttpComposition.idValues.value; - return idValues? idValues.split(props.separator) : []; } + return []; }); function updateLookupOptions(options: Record) { @@ -213,7 +216,8 @@ export default defineComponent({ onCloseModal={onCloseModal} onMaximize={ ($event) => onMaximizeModal($event)} useHttpComposition= {useHttpComposition} userDataService={userDataService} useDialog={{cancelDialog, submitDialog}} showSelectedList={showSelections.value} - selectionsManager={ selectionsManager } showIncludeChildNodes={{show: showIncludeChildNodes.value, value: props.includeChildNodesValue}}> + selectionsManager={ selectionsManager } showIncludeChildNodes={{show: showIncludeChildNodes.value, value: props.includeChildNodesValue}} + showCascadeControl={showCascadeControl.value}> {{ default: () => ( , default: LoadTreeDataType.all }, + loadTreeDataType:{ type: String as PropType, default: LoadTreeDataType.default }, enableToSelect: { type: Boolean, default: true }, customData: { type: Object, default: null }, modelValue: { type: String, default: '' }, @@ -73,7 +74,18 @@ export const lookupProps = { loader: { type: Function, default: null }, allowFreeInput: { type: Boolean, default: false }, onlySelectLeaf: { type: String as PropType, default: OnlySelectLeaf.default }, - enableFullTree: { type: Boolean, default: true } + enableFullTree: { type: Boolean, default: true }, + enableCascade: { type: Boolean, default: false }, + showCascadeControl: { type: Boolean, default: false }, + cascadeItems: { type: Object, default: { + both: true, + up: true, + down: true, + disable: true + } }, + cascadeStatus: { type: String, default: 'both' }, + /** 0: 不展开; -1: 全部展开;>0: 展开到指定级数 */ + expandLevel: { type: Number, default: 0 }, } as Record; export type LookupProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index 1054e0b7cca..e809347fc1a 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -10,6 +10,10 @@ export const lookupDefaultConverter = { return schema.editor[propertyKey] || ','; } + if (propertyKey === 'loadTreeDataType' || propertyKey === 'onlySelectLeaf') { + return schema.editor[propertyKey] || 'default'; + } + return schema.editor[propertyKey]; }, convertTo: (schema: Record, propertyKey: string, propertyValue: any) => { diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index dd0e9f38798..c9a7ee54b35 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -11,6 +11,7 @@ import { } from "./converters/lookup-property.converter"; import { DesignerComponentInstance } from "../../../designer-canvas/src/types"; import { LookupEvents } from "./lookup-events"; +import { cascadeItems } from "../composition/types"; export const LookupSchemaRepositoryToken = Symbol('schema_repository_token'); @@ -395,26 +396,26 @@ export class LookupPropertyConfig extends InputBaseProperty { } private showPagerProperty(editorOptions: any, propertyName?: string) { - const show = this.getDisplayType(editorOptions) !== 'TREELIST' && editorOptions.pagination && editorOptions.pagination.enable; + const show = this.getDisplayType(editorOptions) !== 'TREELIST' || editorOptions.treeToList; if (propertyName && show) { - return editorOptions.pagination[propertyName]; + return editorOptions.pagination && editorOptions.pagination[propertyName]; } return show; } private getPageConfig(editorOptions: any) { return { - hide: this.getDisplayType(editorOptions) === 'TREELIST', + hide: this.getDisplayType(editorOptions) === 'TREELIST' || !editorOptions.helpId, description: "分页配置", title: "分页", properties: { - enable: { - description: "启用分页", - title: "启用分页", - type: "boolean", - refreshPanelAfterChanged: true, - $converter: lookupPaginationConverter - }, + // enable: { + // description: "启用分页", + // title: "启用分页", + // type: "boolean", + // refreshPanelAfterChanged: true, + // $converter: lookupPaginationConverter + // }, showLimits: { description: "显示每页条数选择器", title: "显示条数选择器", @@ -465,9 +466,13 @@ export class LookupPropertyConfig extends InputBaseProperty { !editorOptions.treeToList && !editorOptions.navTreeToList; } + private showOnlySelectLeaf(editorOptions: any) { + return this.getDisplayType(editorOptions) === 'TREELIST' && !editorOptions.treeToList; + } + private getTreePropConfig(editorOptions: any) { return { - hide: this.getDisplayType(editorOptions) !== 'TREELIST', + hide: this.getDisplayType(editorOptions) !== 'TREELIST' && this.getDisplayType(editorOptions) !== 'NAVTREELIST', description: "树形数据配置", title: "树形数据配置", properties: { @@ -492,14 +497,31 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDefaultConverter, title: "构造完整树", type: "boolean", - visible: !editorOptions.treeToList && !editorOptions.navTreeToList + visible: !editorOptions.treeToList || !editorOptions.navTreeToList + }, + loadTreeDataType: { + description: "树形数据加载方式", + $converter: lookupDefaultConverter, + title: "数据加载方式", + type: "string", + editor: { + ...this.comboListEditor, + data: [ + { value: 'default', text: '默认' }, + { value: 'laodall', text: '全部加载' }, + { value: 'layerload', text: '分层加载'} + ], + textField: 'text', + valueField: 'value' + }, + visible: this.showLoadType(editorOptions) }, onlySelectLeaf: { description: "仅选择叶子节点", $converter: lookupDefaultConverter, title: "仅选择叶子节点", type: "string", - visible: this.getDisplayType(editorOptions) === 'TREELIST' && !editorOptions.treeToList, + visible: this.showOnlySelectLeaf(editorOptions), editor: { ...this.comboListEditor, data: [ @@ -511,24 +533,40 @@ export class LookupPropertyConfig extends InputBaseProperty { valueField: 'value' } }, - loadTreeDataType: { - description: "树形数据加载方式", + enableCascade: { + description: "启用级联选择", $converter: lookupDefaultConverter, - title: "数据加载方式", + refreshPanelAfterChanged: true, + title: "启用级联选择", + type: "boolean", + visible: this.showOnlySelectLeaf(editorOptions) && !!editorOptions.multiSelect + }, + showCascadeControl: { + description: "显示级联选择控件", + $converter: lookupDefaultConverter, + title: "显示级联选择控件", + type: "boolean", + visible: !!editorOptions.enableCascade && this.showOnlySelectLeaf(editorOptions) + }, + cascadeStatus: { + description: "级联选择默认状态", + $converter: lookupDefaultConverter, + title: "级联状态", type: "string", + visible: !!editorOptions.enableCascade && this.showOnlySelectLeaf(editorOptions), editor: { ...this.comboListEditor, - data: [ - { value: 'default', text: '默认' }, - { value: 'all', text: '全部加载' }, - { value: 'async', text: '分层加载'} - ], + data: cascadeItems, textField: 'text', valueField: 'value' - }, - visible: this.showLoadType(editorOptions) + } + }, + expandLevel: { + description: "默认展开层级: 0: 不展开; -1: 全部展开;>0: 展开到指定级数 ", + $converter: lookupDefaultConverter, + title: "默认展开级别", + type: "number" } - } }; } diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index a13687b4ea5..cf04af5b491 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -198,11 +198,11 @@ }, "loadTreeDataType": { "type": "string", - "default": "all" + "default": "default" }, "onlySelectLeaf": { "type": "boolean", - "default": false + "default": "default" }, "enableFullTree": { "type": "boolean", @@ -215,6 +215,31 @@ "beforeSelectData": { "type": "object", "default": null + }, + "enableCascade": { + "type": "boolean", + "default":false + }, + "showCascadeControl": { + "type": "boolean", + "default": false + }, + "cascadeItems": { + "type": "object", + "default": { + "both": true, + "up": true, + "down": true, + "disable": true + } + }, + "cascadeStatus": { + "type": "string", + "default": "both" + }, + "expandLevel": { + "type": "number", + "default": 0 } }, "required": [ diff --git a/packages/ui-vue/components/popover/src/composition/use-popup.ts b/packages/ui-vue/components/popover/src/composition/use-popup.ts index 87a1f0e63d9..aa1cb3ae203 100644 --- a/packages/ui-vue/components/popover/src/composition/use-popup.ts +++ b/packages/ui-vue/components/popover/src/composition/use-popup.ts @@ -21,7 +21,7 @@ export function usePopup( function hide() { showPopover.value = false; - document.body.addEventListener('click', hidePopverOnClickBodyHandler); + document.body.removeEventListener('click', hidePopverOnClickBodyHandler); document.body.removeEventListener('mousedown', hidePopverOnClickBodyHandler); document.body.removeEventListener('wheel', hidePopverOnClickBodyHandler, true); document.removeEventListener('scroll', hidePopverOnClickBodyHandler); -- Gitee From 3c23825da3bf46566abdff62ff8bd3a0bc4f7dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 5 Mar 2025 19:17:30 +0800 Subject: [PATCH 031/156] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84lookup?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=97=B6=E7=9B=B8=E5=85=B3=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-http.ts | 2 ++ .../composition/use-treegrid-row-options.ts | 19 +++++++++++++++- .../property-config/lookup.property-config.ts | 22 ++++++++++++------- .../lookup/src/schema/lookup.schema.json | 4 ++++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 4a2e19f2215..57825411188 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -226,6 +226,8 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { queryParams.navSearchConditions = navSearchConditions; } + queryParams.enableFullTree = props.enableFullTree; + queryParams.searchValue = JSON.stringify(searchParam); const { pageIndex, pageSize } = getPageInfo(action); diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts index a6cc994efad..011ab8e572c 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts @@ -3,11 +3,28 @@ import { RowOptions, VisualData } from "@farris/ui-vue/components/data-view"; export const LOOKUP_TREEROW_OPTIONS = Symbol('LOOKUP_TREEROW_OPTIONS'); +function shoudExpand(expandLevel: number, layer: number) { + if (expandLevel === -1) { + // -1 全展开 + return true; + } else if (expandLevel === 0) { + // 0 为不展开 + return false ; + } else { + // 没有启用分层加载,通过展开层级确定是否展开该节点 + return layer <= expandLevel; + } +} + export function useTreeRowOptions(lookupOptions: any, isNavigation = false) { function customRowStatus(visualData: VisualData) { if (visualData.collapse === undefined) { - visualData.collapse = !visualData.raw.expanded; + if (lookupOptions.expandLevel !== undefined && lookupOptions.expandLevel !== 0) { + visualData.collapse = !shoudExpand(lookupOptions.expandLevel, visualData.raw.layer); + } else { + visualData.collapse = !visualData.raw.expanded; + } } if (visualData.raw.addtional || visualData.raw.selectable === false) { diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index c9a7ee54b35..a447d7f8ec7 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -119,6 +119,11 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "string", $converter: lookupDefaultConverter }, + enableClear:{ + title: "启用清除按钮", + type: "boolean", + $converter: lookupDefaultConverter + }, editable: { description: "", title: "允许编辑", @@ -492,13 +497,6 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "boolean", visible: this.getDisplayType(editorOptions) === 'NAVTREELIST' }, - enableFullTree: { - description: "启用构造完整树", - $converter: lookupDefaultConverter, - title: "构造完整树", - type: "boolean", - visible: !editorOptions.treeToList || !editorOptions.navTreeToList - }, loadTreeDataType: { description: "树形数据加载方式", $converter: lookupDefaultConverter, @@ -516,6 +514,13 @@ export class LookupPropertyConfig extends InputBaseProperty { }, visible: this.showLoadType(editorOptions) }, + enableFullTree: { + description: "启用构造完整树", + $converter: lookupDefaultConverter, + title: "构造完整树", + type: "boolean", + visible: this.showLoadType(editorOptions) + }, onlySelectLeaf: { description: "仅选择叶子节点", $converter: lookupDefaultConverter, @@ -565,7 +570,8 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "默认展开层级: 0: 不展开; -1: 全部展开;>0: 展开到指定级数 ", $converter: lookupDefaultConverter, title: "默认展开级别", - type: "number" + type: "number", + visible: this.showLoadType(editorOptions) } } }; diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index cf04af5b491..25703cc17a7 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -240,6 +240,10 @@ "expandLevel": { "type": "number", "default": 0 + }, + "enableClear": { + "type": "boolean", + "default": true } }, "required": [ -- Gitee From 99009545563f430efce27aee032596863d20ec74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 7 Mar 2025 10:21:08 +0800 Subject: [PATCH 032/156] =?UTF-8?q?feature:=20lookup=E9=9B=86=E6=88=90?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E6=9D=A1=E4=BB=B6=E7=BC=96=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/lookup-field-selector.service.ts | 105 +++++++++ .../combo-tree/src/combo-tree.component.tsx | 3 +- .../combo-tree/src/combo-tree.props.ts | 3 +- .../src/schema/combo-tree.schema.json | 5 + .../dynamic-view/src/components/maps.ts | 2 + .../filter-condition-editor/index.ts | 17 ++ .../filter-condition-actions.component.tsx | 55 +++++ .../filter-condition-grid.component.tsx | 186 +++++++++++++++ .../components/filter-condition-grid.props.ts | 22 ++ .../src/composition/types.ts | 41 ++++ .../src/composition/use-condition-data.ts | 217 ++++++++++++++++++ .../src/composition/use-constant-data.ts | 62 +++++ .../src/filter-condition-editor.component.tsx | 172 ++++++++++++++ .../src/filter-condition-editor.props.ts | 53 +++++ .../src/schema/filter-condition-editor.json | 48 ++++ packages/ui-vue/components/index.ts | 4 +- .../property-config/lookup.property-config.ts | 21 +- .../demos/filter-condition-editor/basic.vue | 13 ++ packages/ui-vue/src/app.vue | 4 +- 19 files changed, 1028 insertions(+), 5 deletions(-) create mode 100644 packages/ui-vue/components/filter-condition-editor/index.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx create mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx create mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/composition/types.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx create mode 100644 packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json create mode 100644 packages/ui-vue/demos/filter-condition-editor/basic.vue diff --git a/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts b/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts index 76ad877ff55..e6dc9c4f0fe 100644 --- a/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts +++ b/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts @@ -1,6 +1,9 @@ +import axios from 'axios'; + import { MetadataService } from "../../metadata.service"; export class LookupFieldSelectorService { + constructor(private metadataService: MetadataService) { } @@ -54,4 +57,106 @@ export class LookupFieldSelectorService { }); } + private async getMetadata(id: string) { + return await this.metadataService.queryMetadataById('', id).then(res => res.data); + } + + async getLookupConditions(editorParams: any) { + const { viewModelId, propertyData } = editorParams; + const {helpId, dataSource} = propertyData; + const helpUri = dataSource.uri; + if (viewModelId) { + const voMetadata = await this.getMetadata(viewModelId); + if (voMetadata && voMetadata.content) { + const voMetadataContent = JSON.parse(voMetadata.content); + // 提取帮助过滤条件 + const valueHelpConfigs = voMetadataContent.ValueHelpConfigs || []; + const helpConfig = valueHelpConfigs.find(config => config.ElementID === helpUri.replace('.', '/') && config.HelperID === helpId); + if (helpConfig && helpConfig.HelpExtend.BeforeHelp && helpConfig.HelpExtend.BeforeHelp.length > 0) { + const {ParameterCollection} = helpConfig.HelpExtend.BeforeHelp[0]; + + const filterCondition = ParameterCollection && ParameterCollection.length > 0 ? ParameterCollection.find(param => param.ParamCode === 'filterCondition') : null; + if (filterCondition && filterCondition.ParamActualValue && filterCondition.ParamActualValue.Enable && filterCondition.ParamActualValue.HasValue) { + const actualValue = filterCondition.ParamActualValue.Value || ''; + if (actualValue) { + return JSON.parse(actualValue); + } + } + } + } + } + + return null; + } + + async saveFilterConditionToVo(conditions, editorParams) { + conditions = conditions.filter(c => c.filterField); + const conditionsStr = JSON.stringify(conditions); + const { propertyData, formBasicInfo, viewModelId } = editorParams; + const {helpId, dataSource} = propertyData; + const helpUri = dataSource.uri; + + const voMetadata = await this.getMetadata(viewModelId); + const voMetadataContent = JSON.parse(voMetadata.content); + + const filterComponentEntityId = '07156c90-f6ee-4d1b-ad57-a40e4027c50c'; // 过滤筛选构件id + const valueHelpConfigs = voMetadataContent.ValueHelpConfigs; + const helpConfig = valueHelpConfigs.find(config => config.ElementID === helpUri.replace('.', '/')); + + const requestHelpConfig: any = { + filterCondition: conditionsStr, + helpConfig: { + ElementID: helpUri.replace('.', '/'), + HelperID: helpId, + FilterExpression: '', + CustomizationInfo: null, + EnableCustomHelpAuth: false, + HelpExtend: {} + }, + path: formBasicInfo.relativePath, + sortCondition: '' + }; + + // vo中已有帮助配置 + if (helpConfig) { + requestHelpConfig.helpConfig.FilterExpression = helpConfig.FilterExpression; + requestHelpConfig.helpConfig.CustomizationInfo = helpConfig.CustomizationInfo; + requestHelpConfig.helpConfig.EnableCustomHelpAuth = helpConfig.EnableCustomHelpAuth; + requestHelpConfig.helpConfig.HelpExtend = helpConfig.HelpExtend || {}; + + if (helpConfig.HelpExtend && helpConfig.HelpExtend.BeforeHelp) { + const oldFilterConfig = helpConfig.HelpExtend.BeforeHelp.find(config => config.ComponentEntityId === filterComponentEntityId); + if (oldFilterConfig && oldFilterConfig.ParameterCollection) { + const sortCondition = oldFilterConfig.ParameterCollection.find(param => param.ParamName === 'orderByCondition'); + if (sortCondition && sortCondition.ParamActualValue && sortCondition.ParamActualValue.Enable) { + requestHelpConfig.sortCondition = sortCondition.ParamActualValue.Value || ''; + } + } + } + } + requestHelpConfig.helpConfig = JSON.stringify(requestHelpConfig.helpConfig); + + + // 调用接口获取全量的voHelpConfig + const convertHelpConfigFilterSortUrl = '/api/dev/main/v1.0/bff/handleHelpConfigFilterSort'; + + return axios.put(convertHelpConfigFilterSortUrl, requestHelpConfig).then((res: any) => { + const {data} = res; + if (!data || !data.HelpExtend || !data.HelpExtend.BeforeHelp) { + return; + } + + if (helpConfig) { + Object.assign(helpConfig, data); + } else { + voMetadataContent.ValueHelpConfigs.push(data); + } + + // 保存vo元数据 + voMetadata.content = JSON.stringify(voMetadataContent); + return this.metadataService.saveMetadata(voMetadata); + }); + + } + } diff --git a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx index 17a8d9e7598..d2edd614329 100644 --- a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx @@ -97,7 +97,8 @@ export default defineComponent({ focusOnCreated={props.focusOnCreated} selectOnCreated={props.selectOnCreated} beforeOpen={onBeforeOpen} - placement={'auto'}> + placement={props.placement} + popupMinWidth={props.panelMinWidth}> {showPopover.value && ; export type ComboTreeProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json index db0d97c5cbd..b5aa8ff0bf5 100644 --- a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json +++ b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json @@ -122,6 +122,11 @@ "customRowStatus": { "type": "object", "default": null + }, + "panelMinWidth": { + "description": "", + "type": "number", + "default": 160 } }, "required": [ diff --git a/packages/ui-vue/components/dynamic-view/src/components/maps.ts b/packages/ui-vue/components/dynamic-view/src/components/maps.ts index 9429fb3f26c..699562c5542 100644 --- a/packages/ui-vue/components/dynamic-view/src/components/maps.ts +++ b/packages/ui-vue/components/dynamic-view/src/components/maps.ts @@ -58,6 +58,7 @@ import FTextArea from '@farris/ui-vue/components/textarea'; import FSchemaSelector from '@farris/ui-vue/components/schema-selector'; import FTreeGrid from '@farris/ui-vue/components/tree-grid'; import FEventParameter from '@farris/ui-vue/components/event-parameter'; +import FFilterConditionEditor from '@farris/ui-vue/components/filter-condition-editor'; // import FExternalContainer from '@farris/ui-vue/components/external-container'; const componentMap: Record = {}; @@ -91,6 +92,7 @@ function loadRegister() { // FExternalContainer.register(componentMap, componentPropsConverter); FFilterBar.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FFieldSelector.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); + FFilterConditionEditor.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FImageCropper.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FInputGroup.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FLayout.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); diff --git a/packages/ui-vue/components/filter-condition-editor/index.ts b/packages/ui-vue/components/filter-condition-editor/index.ts new file mode 100644 index 00000000000..676a917a832 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/index.ts @@ -0,0 +1,17 @@ +import type { App } from 'vue'; +import FilterConditionEditor from './src/filter-condition-editor.component'; +import { propsResolver } from './src/filter-condition-editor.props'; + +export * from './src/filter-condition-editor.props'; + +export { FilterConditionEditor }; + +export default { + install(app: App): void { + app.component(FilterConditionEditor.name as string, FilterConditionEditor); + }, + register(componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record): void { + componentMap['filter-condition-editor'] = FilterConditionEditor; + propsResolverMap['filter-condition-editor'] = propsResolver; + }, +}; diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx new file mode 100644 index 00000000000..6a46da3c272 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx @@ -0,0 +1,55 @@ +import { defineComponent } from "vue"; +import { FMessageBoxService } from "../../../../components/message-box"; + +export default defineComponent({ + name: "filter-condition-actions", + props: ['canClear', 'canMove'], + emits: ['add', 'clear', 'moveTop', 'movePrev', 'moveNext', 'moveBottom'], + setup(props, ctx) { + + function onAddFilter() { + ctx.emit('add'); + } + + function onClear() { + FMessageBoxService.question('确定要清空所有条件吗?', '', () => { + ctx.emit('clear'); + }, () => { }); + } + + function onMoveTop() { + ctx.emit('moveTop'); + } + + function onMovePrev() { + ctx.emit('movePrev'); + } + + function onMoveNext() { + ctx.emit('moveNext'); + } + + function onMoveBottom() { + ctx.emit('moveBottom'); + } + + + return () => { + return
+ + + + + + +
; + } + } +}); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx new file mode 100644 index 00000000000..188af9dba01 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -0,0 +1,186 @@ +import { computed, defineComponent, onUpdated, ref, watch, watchEffect } from "vue"; +import { filterConditionGridProps } from "./filter-condition-grid.props"; +import { FComboList } from "../../../combo-list"; +import { FComboTree } from "../../../combo-tree"; +import { FButtonEdit } from '../../../button-edit'; + + +import { FilterCondition } from "../composition/types"; +import { useConstantData } from "../composition/use-constant-data"; + +export default defineComponent({ + name: 'filter-condition-grid', + props: filterConditionGridProps, + emits: ['insert', 'remove', 'rowClick'], + setup(props, context) { + const activeIndex = ref(props.activeIndex); + const { compareOperators, leftBracketItems, valueTypes, + treeNodeStatus,relationItems, righttBracketItems + } = useConstantData(); + + const tbodyRef = ref(); + + const fields = ref(props.fields); + watch(() => props.fields, (newValue) => { + fields.value = newValue; + }); + + watch(() => props.activeIndex, (newValue) => { + activeIndex.value = newValue; + }); + + const selectedRowRef = computed(() => { + return tbodyRef.value.querySelector(`tr[index="${activeIndex.value}"]`); + }); + + function itemIntoView() { + const tr = selectedRowRef.value; + if (tr){ + if (tr.scrollIntoViewIfNeeded) { + tr.scrollIntoViewIfNeeded(false); + } else { + tr.scrollIntoView({block: 'nearest'}); + } + } + } + + const activeRowCls = computed(() => { + return (index) => { + return { + 'fv-grid-row-selected' : index === activeIndex.value + }; + }; + }); + + const conditions = ref>(props.conditions as Array); + + watch(() => props.conditions,(newValue) => { + conditions.value = newValue; + }); + + function onInsert(index: number, $event: MouseEvent) { + context.emit('insert', { index, $event }); + } + + function onRemove(index: number, $event: MouseEvent) { + context.emit('remove', { index, $event }); + } + + function onRowClick(item: FilterCondition, index: number) { + activeIndex.value = index; + context.emit('rowClick', { item, index }); + } + + onUpdated(() => { + itemIntoView(); + }); + + return () => { + return
+ + + + + + + + + + + + + + + { + conditions.value.map((item: FilterCondition, index: number) => { + return onRowClick(item, index)}> + + + + + + + + + + }) + } + +
左括号字段操作符值类型右括号关系
+ + + + + + + + + + + + ':''} + v-model={item.value}> + + + + +
+
; + }; + } +}); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts new file mode 100644 index 00000000000..eca3b5a3721 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts @@ -0,0 +1,22 @@ +import { FilterCondition } from "../composition/types"; + +export const filterConditionGridProps = { + conditions: { + type: Array, + default: [], + }, + fields: { + type: Array<{label: string, value: string}>, + default: [], + }, + activeIndex: { + type: Number, + default: -1, + }, + formatter: { + type: Function, + default: (cell, data) => { + return `${data.raw['name']} [${data.raw['path']}]`; + } + } +}; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts new file mode 100644 index 00000000000..eb97baffaa1 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts @@ -0,0 +1,41 @@ + +export enum Compare { + Equal = 0, + NotEqual = 1, + Greater = 2, + GreaterOrEqual = 3, + Less = 4, + LessOrEqual = 5, + Like = 6, + LikeStartWith = 7, + LikeEndWith = 8, + NotLike = 9, + NotLikeStartWith = 10, + NotLikeEndWith = 11, + Is = 12, + IsNot = 13, + In = 14, + NotIn = 15 +} + +export enum FilterRelation { + Empty = 0, + And = 1, + Or = 2 +} + +export enum ExpressValueType { + Value = 0, // 值 + Expression = 1, // 表达式 +} + + +export interface FilterCondition { + lbracket?: string; + filterField: string; + compare?: Compare; + value: string; + rbracket?: string; + relation?: FilterRelation; + expresstype?: ExpressValueType; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts new file mode 100644 index 00000000000..21e973a3bb6 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -0,0 +1,217 @@ +import { computed, ref } from "vue"; +import { Compare, ExpressValueType, FilterCondition, FilterRelation } from "./types"; + +export function useConditionData(props, conditions) { + + const activeRow = ref({ index: -1, condition: null }); + + const newCondition: FilterCondition = { + filterField: '', + value: '', + lbracket: '', + rbracket: '', + relation: FilterRelation.Empty, + compare: Compare.Equal, + expresstype: ExpressValueType.Value + }; + + + const canClear = computed(() => { + return conditions.value.length > 0; + }); + + const canMove = computed(() => { + return (direction: 'up'| 'down' = 'down') => { + if (conditions.value.length > 1) { + if (direction === 'up') { + return activeRow.value.index > 0; + } else { + return activeRow.value.index < conditions.value.length - 1; + } + } + + return false; + }; + }); + + + function onAddFilter() { + const newItem = Object.assign({}, newCondition); + conditions.value.forEach(n => { + if (n.relation === FilterRelation.Empty || !n.relation) { + n.relation = FilterRelation.And; + } + }); + conditions.value = [...conditions.value, newItem]; + const newIdx = conditions.value.length - 1; + activeRow.value = { index: newIdx, condition: newItem }; + } + + function insertCondition({index}) { + + const _newCondition = Object.assign({}, newCondition, { relation: FilterRelation.And }); + if (props.insertType === 'above') { + if (index === 0) { + conditions.value.unshift(_newCondition); + } else { + conditions.vlaue.splice(index, 0, _newCondition); + } + } else { + conditions.value.splice(index + 1, 0, _newCondition); + } + + } + + function removeCondition({index}) { + conditions.value.splice(index, 1); + + if (activeRow.value) { + if (index === activeRow.value.index) { + if (conditions.value[index]) { + activeRow.value = { index: index, condition: conditions.value[index] }; + } else { + if (conditions.value[index - 1]) { + activeRow.value = { index: index - 1, condition: conditions.value[index - 1] }; + } else { + activeRow.value = null; + } + } + } else { + if (!conditions.value[activeRow.value.index]) { + if (activeRow.value.index > index) { + activeRow.value.index = activeRow.value.index - 1; + } else { + activeRow.value.index = activeRow.value.index + 1 ; + } + } + } + } + } + + function onClear() { + conditions.value = []; + } + + function onMoveTop() { + if (activeRow.value) { + conditions.value.unshift(activeRow.value.condition); + conditions.value.splice(activeRow.value.index + 1, 1); + + activeRow.value.index = 0; + } + } + + function onMovePrev() { + if (activeRow.value) { + const {index} = activeRow.value; + const tempArr = conditions.value.splice(index, 1); + conditions.value.splice(index - 1, 0, ...tempArr); + + activeRow.value.index = index - 1; + } + } + + function onMoveNext() { + if (activeRow.value) { + const {index} = activeRow.value; + const tempArr = conditions.value.splice(index, 1); + conditions.value.splice(index + 1, 0, ...tempArr); + + activeRow.value.index = index + 1; + } + } + + function onMoveBottom() { + if (activeRow.value) { + conditions.value.push(activeRow.value.condition); + conditions.value.splice(activeRow.value.index, 1); + activeRow.value.index = conditions.value.length - 1; + } + } + + function onSelectRow({index}) { + activeRow.value = { index: index, condition: conditions.value[index] }; + } + + function validateCondition() { + const total = conditions.value.length; + if (total) { + // 清除最后条件的关系符 + conditions.value[total - 1].relation = FilterRelation.Empty; + + // 检查关系连接符 + const emptyRelations = conditions.value + .map((n: any, i) => { + if (n.relation === "" + FilterRelation.Empty) { + return { index: i, filter: n }; + } + return null; + }) + .filter((n, i) => { + return n && i !== total - 1; + }); + + let relationFlag = true; + if (emptyRelations.length) { + relationFlag = false; + } + + // 检查括号 + let bracketFlag = true; + let bracketStr = ''; + for (let i = 0; i < total; i++) { + const item = conditions.value[i]; + bracketStr += item.lbracket + item.rbracket; + } + + const l = bracketStr.length ; + if (l % 2 > 0) { + bracketFlag = false; + } else { + for(let i =0; i< l; i++){ + bracketStr = bracketStr.replace('()', ''); + } + bracketFlag = !bracketStr.length; + } + + // 检查字段是否设置 + const emptyFields = conditions.value.filter((n: any) => !n.filterField).length === 0; + + const result = [ + { + result: bracketFlag, + msg: '括号不匹配,请检查。' + }, + { + result: relationFlag, + msg: '关系设置不完整,请检查。' + }, + { + result: emptyFields, + msg: '字段不允许为空,请检查。' + } + ]; + + return result.find(n => !n.result); + } + + return true; + } + + + return { + activeRow, + canClear, + canMove, + onAddFilter, + onRemove: removeCondition, + onInsert: insertCondition, + onClear, + onMoveTop, + onMovePrev, + onMoveNext, + onMoveBottom, + onSelectRow, + validateCondition + }; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts new file mode 100644 index 00000000000..711c60591ef --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts @@ -0,0 +1,62 @@ +export function useConstantData() { + + const leftBracketItems = [ + { value: '', label: ' ' }, + { value: '(' , label: '(' }, + { value: '((' , label: '(('}, + { value: '(((', label: '(((' } + ]; + + const righttBracketItems = [ + { value: '' , label: ' ' }, + { value: ')' , label: ')' }, + { value: '))', label: '))' }, + { value: ')))', label: ')))' } + ]; + + const compareOperators = [ + { label: '=', value: 0}, + { label: '<>', value: 1}, + { label: '>', value: 2}, + { label: '>=', value: 3}, + { label: '<', value: 4}, + { label: '<=', value: 5}, + { label: 'like %...%', value: 6}, + { label: 'like ...%', value: 7}, + { label: 'like %...', value: 8}, + { label: 'not like %...%', value: 9}, + { label: 'not like ...%', value: 10}, + { label: 'not like %...', value: 11}, + { label: 'is', value: 12}, + { label: 'is not', value: 13}, + { label: 'in', value: 14}, + { label: 'not in', value: 15}, + ]; + + const relationItems = [ + { label: ' ', value: 0}, + { label: '并且', value: 1}, + { label: '或者', value: 2} + ]; + + const valueTypes = [ + { label: '值', value: 0}, + { label: '表达式', value: 1} + ]; + + const treeNodeStatus = (visualData: any) => { + if (visualData.raw.$type !== 'SimpleField' || visualData.raw.selectable === false) { + visualData.disabled = true; + } + return visualData; + }; + + return { + treeNodeStatus, + leftBracketItems, + righttBracketItems, + compareOperators, + relationItems, + valueTypes + }; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx new file mode 100644 index 00000000000..76ad7e6f254 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -0,0 +1,172 @@ +import { defineComponent, inject, ref } from "vue"; + +import FButtonEdit from '../../button-edit/src/button-edit.component'; +import { FilterConditionEditorProps, filterConditionEditorProps } from "./filter-condition-editor.props"; +import ConditionGrid from './components/filter-condition-grid.component'; +import ConditionActions from './components/filter-condition-actions.component'; +import { useConditionData } from "./composition/use-condition-data"; +import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; +import { FMessageBoxService } from "../../../components/message-box"; +import { FLoadingService } from "@farris/ui-vue/components/loading"; + + +export default defineComponent({ + name: 'filter-condition-editor', + props: filterConditionEditorProps, + emits: ['update:modelValue'], + setup(props: FilterConditionEditorProps, ctx) { + const displayText = ref(props.displayText); + const repository = inject(props.repositoryToken); + const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; + const loadingService: any | null = inject('FLoadingService'); + + if (notifyService) { + notifyService.globalConfig = { position: 'top-center' }; + } + + const fields = ref(props.fields || []); + const buttonIcon = ''; + const conditions = ref(props.modelValue || []); + const originalConditions = ref([]); + + const { onAddFilter, onClear, onMoveBottom, onMoveNext, onMovePrev, onMoveTop, + onInsert, onRemove, activeRow, onSelectRow, canClear, canMove, validateCondition + } = useConditionData(props, conditions); + + async function saveConditions() { + if (repository) { + try{ + loadingService?.show(); + const newConditions = await repository.getLookupConditions(props.editorParams) || []; + loadingService?.clearAll(); + if (JSON.stringify(newConditions) !== JSON.stringify(originalConditions.value)) { + FMessageBoxService.question('视图对象中的帮助过滤条件已更改,请点击确定同步过滤数据', '', () => { + conditions.value = newConditions; + originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); + }, () => { }); + } else { + if (JSON.stringify(conditions.value) === JSON.stringify(originalConditions.value)) { + return true; + } else { + // save + loadingService?.show(); + await repository.saveFilterConditionToVo(conditions.value, props.editorParams); + loadingService?.clearAll(); + return true; + } + } + } catch (error) { + FMessageBoxService?.error('保存失败', ''); + } finally { + loadingService?.clearAll(); + } + } + } + + + const modalOptions ={ + title: '过滤条件编辑器', + width: 800, + height: 600, + fitContent: false, + minWidth: 300, + minHeight: 200, + showMaxButton: true, + resizeable: true, + draggable: true, + buttons: [ + { + name: 'cancel', + text: '取消', + class: 'btn btn-secondary', + handle: ($event: MouseEvent) => { + return true; + } + }, + { + name: 'accept', + text: '确定', + class: 'btn btn-primary', + handle: async ($event: MouseEvent) => { + const failedResult = validateCondition(); + + if (typeof failedResult === "object" && failedResult !== null) { + if (failedResult && failedResult.msg) { + notifyService.warning(failedResult.msg); + return; + } + } + + await saveConditions(); + return true; + } + } + ] + }; + + async function onBeforeOpen() { + const helpId = props.editorParams?.propertyData?.helpId; + if (!helpId) { + notifyService?.warning({message: '请先配置数据源!'}); + return false; + } + + if (repository) { + try { + loadingService?.show(); + const data = await repository.getData(props.editorParams); + fields.value = data; + conditions.value = await repository.getLookupConditions(props.editorParams) || []; + loadingService?.clearAll(); + originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); + } catch (error) { + notifyService?.error({message: '获取数据失败!'}); + } finally { + loadingService?.clearAll(); + } + } + + return true; + } + + return () => { + return +
+
+ onInsert(payload)} + onRemove={(payload) => onRemove(payload)} + onRowClick={(payload) => onSelectRow(payload)}> + +
+
; + }; + } +}); diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts new file mode 100644 index 00000000000..8a3b777c96b --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -0,0 +1,53 @@ +import { ExtractPropTypes, readonly } from "vue"; +import { createPropsResolver } from "../../dynamic-resolver"; +import schema from './schema/filter-condition-editor.json'; +import { FilterCondition } from "./composition/types"; + + +export const filterConditionEditorProps = { + disabled: { + type: Boolean, + default: false + }, + readonly: { + type: Boolean, + default: false + }, + enableClear: { + type: Boolean, + default: true + }, + displayText: { + type: String, + default: '' + }, + enableExpress: { + type: Boolean, + default: false + }, + modelValue: { + type: Array, + default: [] + }, + insertType: { + type: String, + default: 'below' // 'above'|'below' + }, + fields: { + type: Array<{ label: string, value: string }>, + default: [] + }, + repositoryToken: { + type: Object, + default: null + }, + editorParams: { + type: Object, + default: null + } +} as Record; + + +export type FilterConditionEditorProps = ExtractPropTypes; + +export const propsResolver = createPropsResolver(filterConditionEditorProps, schema); diff --git a/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json new file mode 100644 index 00000000000..dbd04a06771 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://farris-design.gitee.io/field-selector.schema.json", + "title": "field-selector", + "description": "A Farris Input Component", + "type": "object", + "properties": { + "disabled": { + "description": "", + "type": "boolean", + "default": "false" + }, + "readonly": { + "description": "", + "type": "boolean", + "default": "false" + }, + "modelValue": { + "description": "", + "type": "object", + "default": null + }, + "repositoryToken": { + "description": "", + "type": "object", + "default": null + }, + "fields": { + "description": "", + "type": "array", + "default": null + }, + "editorParams": { + "type": "object", + "default": null + }, + "displayText": { + "description": "", + "type": "string", + "default": "" + }, + "enableClear": { + "description": "", + "type": "boolean", + "default": true + } + } +} \ No newline at end of file diff --git a/packages/ui-vue/components/index.ts b/packages/ui-vue/components/index.ts index 9f0d6dfcb43..b909c9d8bc7 100644 --- a/packages/ui-vue/components/index.ts +++ b/packages/ui-vue/components/index.ts @@ -94,6 +94,7 @@ import Drawer from './drawer'; import Common from './common'; import EventParemeter from './event-parameter'; import BindingSelector from './binding-selector'; +import FilterConditionEditor from './filter-condition-editor'; import '../public/assets/farris-all.css'; // 导出所有组件,可以按需加载 export * from './components'; @@ -182,7 +183,8 @@ export default { .use(Drawer) .use(Common) .use(BindingSelector) - .use(EventParemeter); + .use(EventParemeter) + .use(FilterConditionEditor); } }; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index a447d7f8ec7..f8ce8c95ea2 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -12,11 +12,11 @@ import { import { DesignerComponentInstance } from "../../../designer-canvas/src/types"; import { LookupEvents } from "./lookup-events"; import { cascadeItems } from "../composition/types"; +import { inject } from "vue"; export const LookupSchemaRepositoryToken = Symbol('schema_repository_token'); export class LookupPropertyConfig extends InputBaseProperty { - private comboListEditor = { type: 'combo-list', enableClear: false, @@ -180,6 +180,25 @@ export class LookupPropertyConfig extends InputBaseProperty { }, $converter: lookupDataSourceConverter }, + filterConditions: { + descriptions: "帮助过滤条件", + title: "过滤条件", + type: "string", + $converter: lookupDefaultConverter, + editor: { + type: "filter-condition-editor", + editable: false, + displayText:"点击配置", + enableClear: false, + editorParams: { + propertyData: editorOptions, + formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo(), + viewModelId: this.formSchemaUtils.getFormSchema().module.entity[0].id, + }, + repositoryToken: FieldSelectorRepositoryToken + }, + visible: !!editorOptions.helpId + }, displayType: { description: "类型: 树列表、列表、双列表、左树右列表", title: "展示类型", diff --git a/packages/ui-vue/demos/filter-condition-editor/basic.vue b/packages/ui-vue/demos/filter-condition-editor/basic.vue new file mode 100644 index 00000000000..460a8574e97 --- /dev/null +++ b/packages/ui-vue/demos/filter-condition-editor/basic.vue @@ -0,0 +1,13 @@ + + + diff --git a/packages/ui-vue/src/app.vue b/packages/ui-vue/src/app.vue index 8fcfb76a967..978afe7e9fa 100644 --- a/packages/ui-vue/src/app.vue +++ b/packages/ui-vue/src/app.vue @@ -308,6 +308,7 @@ import TolltipReference from '../demos/tooltip/reference.vue'; import FieldSelectorBasic from '../demos/field-selector/basic.vue'; import ExpressionEditorBasic from '../demos/expression-editor/basic.vue'; import TextareaBasic from '../demos/textarea/basic.vue'; +import FilterConditionEditor from '../demos/filter-condition-editor/basic.vue'; const routes: Record = { '/': DataGridBasic, @@ -614,7 +615,8 @@ const routes: Record = { '/tooltip/reference': TolltipReference, '/field-selector/basic': FieldSelectorBasic, '/expression-editor/basic': ExpressionEditorBasic, - '/textarea/basic': TextareaBasic + '/textarea/basic': TextareaBasic, + '/filter-condition-editor/basic': FilterConditionEditor }; const currentPath = ref(window.location.hash); -- Gitee From 2dca75cc15b3bb396ccb58693744e7a4da75a341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 8 Mar 2025 14:52:31 +0800 Subject: [PATCH 033/156] =?UTF-8?q?fix:=20combo-list=E6=98=93=E7=94=A8?= =?UTF-8?q?=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../button-edit/src/composition/use-text-box.ts | 1 + .../combo-list/src/combo-list.component.tsx | 10 +--------- .../filter-condition-grid.component.tsx | 6 +++--- .../src/filter-condition-editor.component.tsx | 14 +++++++------- .../search-bar/search-bar.component.tsx | 12 +----------- .../lookup/src/composition/use-treegrid.tsx | 15 +-------------- 6 files changed, 14 insertions(+), 44 deletions(-) diff --git a/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts b/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts index a395bdaf0c1..abc736c09e0 100644 --- a/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts +++ b/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts @@ -88,6 +88,7 @@ export function useTextBox( context.emit('click', $event); if (!props.disable && !props.readonly && props.popupOnClick) { usePopupComposition.togglePopup(); + document.body.click(); } } diff --git a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx index 6439d6e0a6a..ca45a0bed4e 100644 --- a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx +++ b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx @@ -60,14 +60,6 @@ export default defineComponent({ } tryHidePopupOnSelect(); } - /** - * 当点击输入框时触发 - */ - function onClickInput() { - if (!readonly.value) { - comboEditorRef.value.togglePopup(); - } - } function onClear($event: Event) { modelValue.value = ''; @@ -132,13 +124,13 @@ export default defineComponent({ focusOnCreated={props.focusOnCreated} selectOnCreated={props.selectOnCreated} onClear={onClear} - onClick={onClickInput} onChange={onDisplayTextChange} onInput={onInput} beforeOpen={props.beforeOpen} placement={props.placement} popupMinWidth={props.panelMinWidth} popupClass={'f-combo-list-wrapper'} + popupOnClick={true} > { conditions.value.map((item: FilterCondition, index: number) => { - return onRowClick(item, index)}> + return onRowClick(item, index)}> @@ -148,7 +147,8 @@ export default defineComponent({ > - ':''} + ':''} v-model={item.value}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index 76ad7e6f254..40539bfe2f7 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -142,13 +142,13 @@ export default defineComponent({ modalOptions={modalOptions} beforeOpen={onBeforeOpen}>
-
+
{ setDefaultSearchField(); if (isNavigation.value) { @@ -99,7 +90,6 @@ export default defineComponent({ idField={'value'} v-model={searchField.value} enableClear={false} - onClick={onInputClick} >
@@ -109,7 +99,7 @@ export default defineComponent({ enableClear={true} onClear={onClearSearchValue} onKeyup={onEnterHandler} - onClick={onInputClick} + popupOnClick={true} >
; diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index a1f0c54d3d8..ae23c450ce2 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -34,20 +34,7 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { const selectionTreeValues = ref([]); const { loadAndSelect } = useLoadData(props, lookupStates); - const { loadData, idValues, expandAllNodes } = useHttpComposition; - - function dataGridLoadData(items: any) { - - if (searchState.default?.value) { - items = expandAllNodes(items); - } - - treegridRef.value?.updateDataSource(items || []); - if (idValues.value) { - treegridRef.value?.selectItemByIds(idValues.value.split(props.separator)); - } - } - + const { loadData, expandAllNodes } = useHttpComposition; function treeGridLoadData(items: any) { -- Gitee From 1841f51727e81f86f9ad0f141dece360f4a64ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 20:20:21 +0800 Subject: [PATCH 034/156] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=20sort-ed?= =?UTF-8?q?itor=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/lookup-field-selector.service.ts | 19 ++- .../combo-list/src/combo-list.component.tsx | 2 +- .../combo-list/src/combo-list.props.ts | 2 +- .../src/schema/combo-list.schema.json | 2 +- .../combo-tree/src/combo-tree.component.tsx | 2 +- .../combo-tree/src/combo-tree.props.ts | 2 +- .../src/schema/combo-tree.schema.json | 2 +- .../visualization/use-visual-data-row.ts | 4 +- .../dynamic-view/src/components/maps.ts | 2 + .../filter-condition-editor/index.ts | 9 +- .../filter-condition-actions.component.tsx | 8 +- .../filter-condition-grid.component.tsx | 88 +++----------- .../sort-editor-grid.component.tsx | 69 +++++++++++ .../sort-editor/sort-editor.props.ts | 23 ++++ .../src/composition/types.ts | 10 ++ .../src/composition/use-condition-data.ts | 65 +++++----- .../src/composition/use-condition-editor.ts | 69 +++++++++++ .../src/composition/use-constant-data.ts | 23 ++-- .../src/composition/use-fields-tree.tsx | 23 ++++ .../src/filter-condition-editor.component.tsx | 115 ++++++++++-------- .../src/filter-condition-editor.props.ts | 15 ++- .../src/schema/filter-condition-editor.json | 15 +++ packages/ui-vue/components/index.ts | 4 +- .../cascade/tree-cascade.component.tsx | 2 +- .../lookup/src/composition/use-http.ts | 6 +- .../property-config/lookup.property-config.ts | 52 +++++++- .../components/sort-condition-editor/index.ts | 15 +++ .../src/schema/sort-editor.json | 58 +++++++++ .../src/sort-condition-editor.component.tsx | 18 +++ .../src/sort-condition-editor.props.ts | 62 ++++++++++ .../demos/filter-condition-editor/basic.vue | 4 + 31 files changed, 603 insertions(+), 187 deletions(-) create mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx create mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts create mode 100644 packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx create mode 100644 packages/ui-vue/components/sort-condition-editor/index.ts create mode 100644 packages/ui-vue/components/sort-condition-editor/src/schema/sort-editor.json create mode 100644 packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx create mode 100644 packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts diff --git a/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts b/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts index e6dc9c4f0fe..0da3f6a6d4d 100644 --- a/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts +++ b/packages/designer/src/components/composition/schema-repository/lookup/lookup-field-selector.service.ts @@ -63,7 +63,7 @@ export class LookupFieldSelectorService { async getLookupConditions(editorParams: any) { const { viewModelId, propertyData } = editorParams; - const {helpId, dataSource} = propertyData; + const {dataSourceId, dataSource} = propertyData; const helpUri = dataSource.uri; if (viewModelId) { const voMetadata = await this.getMetadata(viewModelId); @@ -71,7 +71,7 @@ export class LookupFieldSelectorService { const voMetadataContent = JSON.parse(voMetadata.content); // 提取帮助过滤条件 const valueHelpConfigs = voMetadataContent.ValueHelpConfigs || []; - const helpConfig = valueHelpConfigs.find(config => config.ElementID === helpUri.replace('.', '/') && config.HelperID === helpId); + const helpConfig = valueHelpConfigs.find(config => config.ElementID === helpUri.replace('.', '/') && config.HelperID === dataSourceId); if (helpConfig && helpConfig.HelpExtend.BeforeHelp && helpConfig.HelpExtend.BeforeHelp.length > 0) { const {ParameterCollection} = helpConfig.HelpExtend.BeforeHelp[0]; @@ -89,25 +89,25 @@ export class LookupFieldSelectorService { return null; } - async saveFilterConditionToVo(conditions, editorParams) { + async saveFilterCondition(conditions, editorParams) { conditions = conditions.filter(c => c.filterField); const conditionsStr = JSON.stringify(conditions); const { propertyData, formBasicInfo, viewModelId } = editorParams; - const {helpId, dataSource} = propertyData; - const helpUri = dataSource.uri; + const {dataSourceId, dataSource} = propertyData; + const getDataUri = dataSource.uri; const voMetadata = await this.getMetadata(viewModelId); const voMetadataContent = JSON.parse(voMetadata.content); const filterComponentEntityId = '07156c90-f6ee-4d1b-ad57-a40e4027c50c'; // 过滤筛选构件id const valueHelpConfigs = voMetadataContent.ValueHelpConfigs; - const helpConfig = valueHelpConfigs.find(config => config.ElementID === helpUri.replace('.', '/')); + const helpConfig = valueHelpConfigs.find(config => config.ElementID === getDataUri.replace('.', '/')); const requestHelpConfig: any = { filterCondition: conditionsStr, helpConfig: { - ElementID: helpUri.replace('.', '/'), - HelperID: helpId, + ElementID: getDataUri.replace('.', '/'), + HelperID: dataSourceId, FilterExpression: '', CustomizationInfo: null, EnableCustomHelpAuth: false, @@ -117,7 +117,6 @@ export class LookupFieldSelectorService { sortCondition: '' }; - // vo中已有帮助配置 if (helpConfig) { requestHelpConfig.helpConfig.FilterExpression = helpConfig.FilterExpression; requestHelpConfig.helpConfig.CustomizationInfo = helpConfig.CustomizationInfo; @@ -152,7 +151,7 @@ export class LookupFieldSelectorService { voMetadataContent.ValueHelpConfigs.push(data); } - // 保存vo元数据 + // 保存 voMetadata.content = JSON.stringify(voMetadataContent); return this.metadataService.saveMetadata(voMetadata); }); diff --git a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx index ca45a0bed4e..79874aa36ec 100644 --- a/packages/ui-vue/components/combo-list/src/combo-list.component.tsx +++ b/packages/ui-vue/components/combo-list/src/combo-list.component.tsx @@ -128,7 +128,7 @@ export default defineComponent({ onInput={onInput} beforeOpen={props.beforeOpen} placement={props.placement} - popupMinWidth={props.panelMinWidth} + popupMinWidth={props.minPanelWidth} popupClass={'f-combo-list-wrapper'} popupOnClick={true} > diff --git a/packages/ui-vue/components/combo-list/src/combo-list.props.ts b/packages/ui-vue/components/combo-list/src/combo-list.props.ts index 8755511407f..11c796bc56d 100644 --- a/packages/ui-vue/components/combo-list/src/combo-list.props.ts +++ b/packages/ui-vue/components/combo-list/src/combo-list.props.ts @@ -224,7 +224,7 @@ export const comboListProps = { }, // 搜索启用高亮 enableHighlightSearch: { type: Boolean, default: true }, - panelMinWidth: { type: Number, default: 160 } + minPanelWidth: { type: Number, default: 160 } } as Record; diff --git a/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json b/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json index 80b8025b9ae..fe10ef8be0e 100644 --- a/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json +++ b/packages/ui-vue/components/combo-list/src/schema/combo-list.schema.json @@ -135,7 +135,7 @@ "type": "number", "default": 350 }, - "panelMinWidth": { + "minPanelWidth": { "description": "", "type": "number", "default": 160 diff --git a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx index d2edd614329..4881cf5a634 100644 --- a/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/combo-tree.component.tsx @@ -98,7 +98,7 @@ export default defineComponent({ selectOnCreated={props.selectOnCreated} beforeOpen={onBeforeOpen} placement={props.placement} - popupMinWidth={props.panelMinWidth}> + popupMinWidth={props.minPanelWidth}> {showPopover.value && ; export type ComboTreeProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json index b5aa8ff0bf5..f2cf9285a54 100644 --- a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json +++ b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json @@ -123,7 +123,7 @@ "type": "object", "default": null }, - "panelMinWidth": { + "minPanelWidth": { "description": "", "type": "number", "default": 160 diff --git a/packages/ui-vue/components/data-view/composition/visualization/use-visual-data-row.ts b/packages/ui-vue/components/data-view/composition/visualization/use-visual-data-row.ts index ad176ebd761..14e3a5d8b53 100644 --- a/packages/ui-vue/components/data-view/composition/visualization/use-visual-data-row.ts +++ b/packages/ui-vue/components/data-view/composition/visualization/use-visual-data-row.ts @@ -54,7 +54,9 @@ export function useVisualDataRow( const isParentCollapse = parent && parent.collapse; // const isChildOfPreRow = pre && pre[idField.value] === dataItem.parent; const isSiblingOfPreRow = pre && pre.parent === dataItem.parent; - const shouldBeHidden = (isParentCollapse || !dataView.isVisibleInTree(dataItem) || (parent && !parent.visible)); + const isVisibleInTree = props.hierarchy && !dataView.isVisibleInTree(dataItem); + const shouldBeHidden = (isParentCollapse || isVisibleInTree + || (parent && !parent.visible)); // || (isSiblingOfPreRow && preRow && !preRow.visible); // const shouldBeHidden = (isChildOfPreRow && preRow && (preRow.collapse || !preRow.visible)) || // (isSiblingOfPreRow && preRow && !preRow.visible); diff --git a/packages/ui-vue/components/dynamic-view/src/components/maps.ts b/packages/ui-vue/components/dynamic-view/src/components/maps.ts index 0238d2450f8..d79fd1a5897 100644 --- a/packages/ui-vue/components/dynamic-view/src/components/maps.ts +++ b/packages/ui-vue/components/dynamic-view/src/components/maps.ts @@ -61,6 +61,7 @@ import FEventParameter from '@farris/ui-vue/components/event-parameter'; import FFilterConditionEditor from '@farris/ui-vue/components/filter-condition-editor'; // import FExternalContainer from '@farris/ui-vue/components/external-container'; import FFieldset from '@farris/ui-vue/components/fieldset'; +import FSortConditionEditor from '@farris/ui-vue/components/sort-condition-editor'; const componentMap: Record = {}; const componentPropsConverter: Record = {}; @@ -122,6 +123,7 @@ function loadRegister() { FSplitter.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FStep.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FSwitch.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); + FSortConditionEditor.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FTabs.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FTags.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FText.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); diff --git a/packages/ui-vue/components/filter-condition-editor/index.ts b/packages/ui-vue/components/filter-condition-editor/index.ts index 676a917a832..f81b7314696 100644 --- a/packages/ui-vue/components/filter-condition-editor/index.ts +++ b/packages/ui-vue/components/filter-condition-editor/index.ts @@ -1,10 +1,17 @@ import type { App } from 'vue'; import FilterConditionEditor from './src/filter-condition-editor.component'; import { propsResolver } from './src/filter-condition-editor.props'; +import ConditionActions from './src/components/filter-condition-actions.component'; + export * from './src/filter-condition-editor.props'; +export * from './src/composition/types'; +export * from './src/composition/use-fields-tree'; +export * from './src/composition/use-condition-data'; +export * from './src/composition/use-condition-editor'; +export * from './src/composition/use-constant-data'; -export { FilterConditionEditor }; +export { FilterConditionEditor, ConditionActions }; export default { install(app: App): void { diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx index 6a46da3c272..38bbb88e6b1 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx @@ -1,18 +1,20 @@ -import { defineComponent } from "vue"; +import { defineComponent, ref } from "vue"; import { FMessageBoxService } from "../../../../components/message-box"; export default defineComponent({ name: "filter-condition-actions", - props: ['canClear', 'canMove'], + props: ['canClear', 'canMove', 'questionMessage'], emits: ['add', 'clear', 'moveTop', 'movePrev', 'moveNext', 'moveBottom'], setup(props, ctx) { + const message = ref(props.questionMessage || '确定要清空所有数据吗?'); + function onAddFilter() { ctx.emit('add'); } function onClear() { - FMessageBoxService.question('确定要清空所有条件吗?', '', () => { + FMessageBoxService.question(message.value, '', () => { ctx.emit('clear'); }, () => { }); } diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 09402d7989a..fb6ec6352e0 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -1,74 +1,30 @@ -import { computed, defineComponent, onUpdated, ref, watch, watchEffect } from "vue"; +import { defineComponent, onUpdated, ref } from "vue"; import { filterConditionGridProps } from "./filter-condition-grid.props"; import { FComboList } from "../../../combo-list"; -import { FComboTree } from "../../../combo-tree"; import { FButtonEdit } from '../../../button-edit'; import { FilterCondition } from "../composition/types"; import { useConstantData } from "../composition/use-constant-data"; +import { useFieldsTree } from "../composition/use-fields-tree"; +import { useConditionEditor } from "../composition/use-condition-editor"; export default defineComponent({ name: 'filter-condition-grid', props: filterConditionGridProps, emits: ['insert', 'remove', 'rowClick'], setup(props, context) { - const activeIndex = ref(props.activeIndex); const { compareOperators, leftBracketItems, valueTypes, - treeNodeStatus,relationItems, righttBracketItems + relationItems, righttBracketItems } = useConstantData(); - + + const {renderFieldsComboTree} = useFieldsTree(props); + const tbodyRef = ref(); - const fields = ref(props.fields); - watch(() => props.fields, (newValue) => { - fields.value = newValue; - }); - - watch(() => props.activeIndex, (newValue) => { - activeIndex.value = newValue; - }); - - const selectedRowRef = computed(() => { - return tbodyRef.value.querySelector(`tr[index="${activeIndex.value}"]`); - }); - - function itemIntoView() { - const tr = selectedRowRef.value; - if (tr){ - if (tr.scrollIntoViewIfNeeded) { - tr.scrollIntoViewIfNeeded(false); - } else { - tr.scrollIntoView({block: 'nearest'}); - } - } - } - - const activeRowCls = computed(() => { - return (index) => { - return { - 'fv-grid-row-selected' : index === activeIndex.value - }; - }; - }); - - const conditions = ref>(props.conditions as Array); - - watch(() => props.conditions,(newValue) => { - conditions.value = newValue; - }); - - function onInsert(index: number, $event: MouseEvent) { - context.emit('insert', { index, $event }); - } - - function onRemove(index: number, $event: MouseEvent) { - context.emit('remove', { index, $event }); - } - - function onRowClick(item: FilterCondition, index: number) { - context.emit('rowClick', { item, index }); - } + const { + conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); @@ -92,7 +48,7 @@ export default defineComponent({ { conditions.value.map((item: FilterCondition, index: number) => { - return onRowClick(item, index)}> + return onRowClick(item, index)}> @@ -105,22 +61,12 @@ export default defineComponent({ idField={'value'} v-model={item.lbracket} enableClear={false} - panelMinWidth={130} + minPanelWidth={130} placement={'auto'} > - + { renderFieldsComboTree(item, fields.value, 'filterField') } @@ -142,7 +88,7 @@ export default defineComponent({ idField={'value'} v-model={item.expresstype} enableClear={false} - panelMinWidth={130} + minPanelWidth={130} placement={'auto'} > @@ -159,7 +105,7 @@ export default defineComponent({ idField={'value'} v-model={item.rbracket} enableClear={false} - panelMinWidth={130} + minPanelWidth={130} placement={'auto'} > @@ -171,7 +117,7 @@ export default defineComponent({ idField={'value'} v-model={item.relation} enableClear={false} - panelMinWidth={130} + minPanelWidth={130} placement={'auto'} > diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx new file mode 100644 index 00000000000..af9c6cc363a --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx @@ -0,0 +1,69 @@ +import { defineComponent, onUpdated, ref } from "vue"; +import { sortEditorProps } from "./sort-editor.props"; +import { FComboList } from "../../../../combo-list"; +import { useConstantData } from "../../composition/use-constant-data"; +import { useFieldsTree } from "../../composition/use-fields-tree"; +import { useConditionEditor } from "../../composition/use-condition-editor"; +import { SortCondition } from "../../composition/types"; + +export default defineComponent({ + name: 'sort-editor-grid', + props: sortEditorProps, + emits: ['insert','remove', 'rowClick'], + setup(props, context) { + const { sortTypes } = useConstantData(); + const {renderFieldsComboTree} = useFieldsTree(props); + const tbodyRef = ref(); + + const { + conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView + } = useConditionEditor(props, context, tbodyRef); + + onUpdated(() => { + itemIntoView(); + }); + + + return () => { + return
+ + + + + + + + + + { + conditions.value.map((item: SortCondition, index: number) => { + return onRowClick(item, index)}> + + + + + + }) + } + +
字段排序
+ + + + { renderFieldsComboTree(item, fields.value, 'sortField') } + + +
+
; + }; + } +}); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts new file mode 100644 index 00000000000..5919f61055d --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts @@ -0,0 +1,23 @@ +import { SortCondition } from "../../composition/types"; + + +export const sortEditorProps = { + conditions: { + type: Array, + default: [], + }, + fields: { + type: Array<{label: string, value: string}>, + default: [], + }, + activeIndex: { + type: Number, + default: -1, + }, + formatter: { + type: Function, + default: (cell, data) => { + return `${data.raw['name']} [${data.raw['path']}]`; + } + } +}; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts index eb97baffaa1..63fc7d1bfa8 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts @@ -39,3 +39,13 @@ export interface FilterCondition { relation?: FilterRelation; expresstype?: ExpressValueType; } + +export declare enum SortType { + Asc = 'asc', + Desc = 'desc' +} + +export interface SortCondition { + sortField: string; + sortType: SortType; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 21e973a3bb6..8460574701d 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -1,11 +1,15 @@ import { computed, ref } from "vue"; -import { Compare, ExpressValueType, FilterCondition, FilterRelation } from "./types"; +import { Compare, ExpressValueType, FilterRelation } from "./types"; export function useConditionData(props, conditions) { - const activeRow = ref({ index: -1, condition: null }); - const newCondition: FilterCondition = { + const displayText = computed(() => { + return props.displayText || `共 ${conditions.value.length} 项`; + }); + + + const newCondition = props.editorType !== 'sort' ? { filterField: '', value: '', lbracket: '', @@ -13,6 +17,9 @@ export function useConditionData(props, conditions) { relation: FilterRelation.Empty, compare: Compare.Equal, expresstype: ExpressValueType.Value + } : { + sortField: '', + sortType: 'asc' }; @@ -37,14 +44,14 @@ export function useConditionData(props, conditions) { function onAddFilter() { const newItem = Object.assign({}, newCondition); - conditions.value.forEach(n => { - if (n.relation === FilterRelation.Empty || !n.relation) { - n.relation = FilterRelation.And; + conditions.value.forEach(condition => { + if (condition.relation === FilterRelation.Empty || !condition.relation) { + condition.relation = FilterRelation.And; } }); conditions.value = [...conditions.value, newItem]; - const newIdx = conditions.value.length - 1; - activeRow.value = { index: newIdx, condition: newItem }; + const newIndex = conditions.value.length - 1; + activeRow.value = { index: newIndex, condition: newItem }; } function insertCondition({index}) { @@ -59,11 +66,12 @@ export function useConditionData(props, conditions) { } else { conditions.value.splice(index + 1, 0, _newCondition); } - + conditions.value = [...conditions.value]; } function removeCondition({index}) { conditions.value.splice(index, 1); + conditions.value = [...conditions.value]; if (activeRow.value) { if (index === activeRow.value.index) { @@ -141,37 +149,37 @@ export function useConditionData(props, conditions) { // 检查关系连接符 const emptyRelations = conditions.value - .map((n: any, i) => { - if (n.relation === "" + FilterRelation.Empty) { - return { index: i, filter: n }; + .map((condition: any, index) => { + if (condition.relation === "" + FilterRelation.Empty) { + return { index, filter: condition }; } return null; }) - .filter((n, i) => { - return n && i !== total - 1; + .filter((condition: any, index) => { + return condition && index !== total - index; }); - let relationFlag = true; + let relationChecked = true; if (emptyRelations.length) { - relationFlag = false; + relationChecked = false; } // 检查括号 - let bracketFlag = true; - let bracketStr = ''; + let bracketChecked = true; + let bracketResult = ''; for (let i = 0; i < total; i++) { const item = conditions.value[i]; - bracketStr += item.lbracket + item.rbracket; + bracketResult += item.lbracket + item.rbracket; } - const l = bracketStr.length ; + const l = bracketResult.length ; if (l % 2 > 0) { - bracketFlag = false; + bracketChecked = false; } else { for(let i =0; i< l; i++){ - bracketStr = bracketStr.replace('()', ''); + bracketResult = bracketResult.replace('()', ''); } - bracketFlag = !bracketStr.length; + bracketChecked = !bracketResult.length; } // 检查字段是否设置 @@ -179,16 +187,16 @@ export function useConditionData(props, conditions) { const result = [ { - result: bracketFlag, - msg: '括号不匹配,请检查。' + result: bracketChecked, + message: '括号不匹配,请检查。' }, { - result: relationFlag, - msg: '关系设置不完整,请检查。' + result: relationChecked, + message: '关系设置不完整,请检查。' }, { result: emptyFields, - msg: '字段不允许为空,请检查。' + message: '字段不允许为空,请检查。' } ]; @@ -200,6 +208,7 @@ export function useConditionData(props, conditions) { return { + displayText, activeRow, canClear, canMove, diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts new file mode 100644 index 00000000000..596d55c0032 --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -0,0 +1,69 @@ +import { computed, ref, watch } from "vue"; +import { FilterCondition, SortCondition } from "./types"; + +export function useConditionEditor(props, context, tbodyRef) { + const activeIndex = ref(props.activeIndex); + + const fields = ref(props.fields); + watch(() => props.fields, (newValue) => { + fields.value = newValue; + }); + + watch(() => props.activeIndex, (newValue) => { + activeIndex.value = newValue; + }); + + const selectedRowRef = computed(() => { + return tbodyRef.value.querySelector(`tr[index="${activeIndex.value}"]`); + }); + + function itemIntoView() { + const tr = selectedRowRef.value; + if (tr){ + if (tr.scrollIntoView) { + tr.scrollIntoView({block: 'center', behavior: 'smooth'}); + } else { + tr.scrollIntoViewIfNeeded && tr.scrollIntoViewIfNeeded(false); + } + } + } + + const activeRowCls = computed(() => { + return (index) => { + return { + 'fv-grid-row-selected' : index === activeIndex.value + }; + }; + }); + + const conditions = ref>(props.conditions as Array); + + watch(() => props.conditions,(newValue) => { + conditions.value = newValue; + }); + + function onInsert(index: number, $event: MouseEvent) { + context.emit('insert', { index, $event }); + } + + function onRemove(index: number, $event: MouseEvent) { + context.emit('remove', { index, $event }); + } + + function onRowClick(item: SortCondition, index: number) { + context.emit('rowClick', { item, index }); + } + + return { + itemIntoView, + activeRowCls, + fields, + activeIndex, + selectedRowRef, + conditions, + tbodyRef, + onInsert, + onRemove, + onRowClick + }; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts index 711c60591ef..12a2116c734 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts @@ -1,3 +1,10 @@ +export const treeNodeStatus = (visualData: any) => { + if (visualData.raw.$type !== 'SimpleField' || visualData.raw.selectable === false) { + visualData.disabled = true; + } + return visualData; +}; + export function useConstantData() { const leftBracketItems = [ @@ -43,20 +50,20 @@ export function useConstantData() { { label: '值', value: 0}, { label: '表达式', value: 1} ]; + + const sortTypes = [ + { label: '升序', value: 'asc'}, + { label: '降序', value: 'desc'} + ]; + - const treeNodeStatus = (visualData: any) => { - if (visualData.raw.$type !== 'SimpleField' || visualData.raw.selectable === false) { - visualData.disabled = true; - } - return visualData; - }; return { - treeNodeStatus, leftBracketItems, righttBracketItems, compareOperators, relationItems, - valueTypes + valueTypes, + sortTypes }; } diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx new file mode 100644 index 00000000000..798c6ae953b --- /dev/null +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx @@ -0,0 +1,23 @@ +import { FComboTree } from "../../../combo-tree"; +import { FilterCondition, SortCondition } from "./types"; +import { treeNodeStatus } from "./use-constant-data"; + + +export function useFieldsTree(props) { + function renderFieldsComboTree(model: any, fields: any[], bindFieldName = 'filterField') { + return ; + } + return { + renderFieldsComboTree + }; +} diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index 40539bfe2f7..c0bb97bda86 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -1,9 +1,11 @@ -import { defineComponent, inject, ref } from "vue"; +import { computed, defineComponent, inject, ref } from "vue"; import FButtonEdit from '../../button-edit/src/button-edit.component'; import { FilterConditionEditorProps, filterConditionEditorProps } from "./filter-condition-editor.props"; import ConditionGrid from './components/filter-condition-grid.component'; import ConditionActions from './components/filter-condition-actions.component'; +import SortConditionActions from './components/sort-editor/sort-editor-grid.component'; + import { useConditionData } from "./composition/use-condition-data"; import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; import { FMessageBoxService } from "../../../components/message-box"; @@ -14,8 +16,7 @@ export default defineComponent({ name: 'filter-condition-editor', props: filterConditionEditorProps, emits: ['update:modelValue'], - setup(props: FilterConditionEditorProps, ctx) { - const displayText = ref(props.displayText); + setup(props: FilterConditionEditorProps, context) { const repository = inject(props.repositoryToken); const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; const loadingService: any | null = inject('FLoadingService'); @@ -29,43 +30,55 @@ export default defineComponent({ const conditions = ref(props.modelValue || []); const originalConditions = ref([]); - const { onAddFilter, onClear, onMoveBottom, onMoveNext, onMovePrev, onMoveTop, + const {displayText, onAddFilter, onClear, onMoveBottom, onMoveNext, onMovePrev, onMoveTop, onInsert, onRemove, activeRow, onSelectRow, canClear, canMove, validateCondition } = useConditionData(props, conditions); + const dialogTitle = computed(() => { + return props.editorType === 'sort' ? '排序条件编辑器' : '过滤条件编辑器'; + }); + + function renderEditGrid() { + if (props.editorType === 'sort') { + return onInsert(payload)} + onRemove={(payload) => onRemove(payload)} + onRowClick={(payload) => onSelectRow(payload)}>; + } + + return onInsert(payload)} + onRemove={(payload) => onRemove(payload)} + onRowClick={(payload) => onSelectRow(payload)}>; + } + + async function saveConditions() { - if (repository) { - try{ - loadingService?.show(); - const newConditions = await repository.getLookupConditions(props.editorParams) || []; - loadingService?.clearAll(); - if (JSON.stringify(newConditions) !== JSON.stringify(originalConditions.value)) { - FMessageBoxService.question('视图对象中的帮助过滤条件已更改,请点击确定同步过滤数据', '', () => { - conditions.value = newConditions; - originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); - }, () => { }); - } else { - if (JSON.stringify(conditions.value) === JSON.stringify(originalConditions.value)) { - return true; - } else { - // save - loadingService?.show(); - await repository.saveFilterConditionToVo(conditions.value, props.editorParams); - loadingService?.clearAll(); - return true; - } - } - } catch (error) { - FMessageBoxService?.error('保存失败', ''); - } finally { - loadingService?.clearAll(); + + context.emit('update:modelValue', conditions.value); + + if (props.onSubmitModal) { + loadingService?.show(); + const canClose = await props.onSubmitModal({loadingService, repository, conditions, originalConditions, FMessageBoxService}); + loadingService?.clearAll(); + if (canClose) { + notifyService.success('过滤条件配置成功!'); } + return canClose; } + + return true; } const modalOptions ={ - title: '过滤条件编辑器', + title: dialogTitle.value, width: 800, height: 600, fitContent: false, @@ -80,6 +93,7 @@ export default defineComponent({ text: '取消', class: 'btn btn-secondary', handle: ($event: MouseEvent) => { + conditions.value = originalConditions.value; return true; } }, @@ -91,41 +105,43 @@ export default defineComponent({ const failedResult = validateCondition(); if (typeof failedResult === "object" && failedResult !== null) { - if (failedResult && failedResult.msg) { - notifyService.warning(failedResult.msg); - return; + if (failedResult && failedResult.message) { + notifyService.warning(failedResult.message); + return false; } } - await saveConditions(); - return true; + const canClose = await saveConditions(); + return canClose; } } ] }; async function onBeforeOpen() { - const helpId = props.editorParams?.propertyData?.helpId; - if (!helpId) { - notifyService?.warning({message: '请先配置数据源!'}); - return false; - } - if (repository) { + if (props.beforeOpen) { try { loadingService?.show(); - const data = await repository.getData(props.editorParams); - fields.value = data; - conditions.value = await repository.getLookupConditions(props.editorParams) || []; - loadingService?.clearAll(); - originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); + const result = await props.beforeOpen({repository, notifyService}); + if (result) { + const { fieldList, conditionList } = result; + fields.value = fieldList || []; + conditions.value = conditionList || []; + originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); + loadingService?.clearAll(); + return true; + } } catch (error) { notifyService?.error({message: '获取数据失败!'}); + return false; } finally { loadingService?.clearAll(); } + } + return true; } @@ -149,12 +165,7 @@ export default defineComponent({ width: 100%; z-index: 2; " class="shading-border-top">
- onInsert(payload)} - onRemove={(payload) => onRemove(payload)} - onRowClick={(payload) => onSelectRow(payload)}> + {renderEditGrid()} Promise<{fieldList: any, conditionList: any}>; export const filterConditionEditorProps = { disabled: { @@ -44,6 +45,18 @@ export const filterConditionEditorProps = { editorParams: { type: Object, default: null + }, + onSubmitModal: { + type: Function, + default: null + }, + beforeOpen: { + type: Function as PropType, + default: null + }, + editorType: { + type: String, + default: 'filter' } } as Record; diff --git a/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json index dbd04a06771..ed471c91a61 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json +++ b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json @@ -43,6 +43,21 @@ "description": "", "type": "boolean", "default": true + }, + "beforeOpen": { + "description": "", + "type": "function", + "default": null + }, + "onSubmitModal": { + "description": "", + "type": "function", + "default": null + }, + "editorType": { + "description": "", + "type": "string", + "default": "filter" } } } \ No newline at end of file diff --git a/packages/ui-vue/components/index.ts b/packages/ui-vue/components/index.ts index b909c9d8bc7..fe342ea6137 100644 --- a/packages/ui-vue/components/index.ts +++ b/packages/ui-vue/components/index.ts @@ -95,6 +95,7 @@ import Common from './common'; import EventParemeter from './event-parameter'; import BindingSelector from './binding-selector'; import FilterConditionEditor from './filter-condition-editor'; +import SortConditionEditor from './sort-condition-editor'; import '../public/assets/farris-all.css'; // 导出所有组件,可以按需加载 export * from './components'; @@ -184,7 +185,8 @@ export default { .use(Common) .use(BindingSelector) .use(EventParemeter) - .use(FilterConditionEditor); + .use(FilterConditionEditor) + .use(SortConditionEditor); } }; diff --git a/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx b/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx index df0d037b5d0..9c338ec2a8e 100644 --- a/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/cascade/tree-cascade.component.tsx @@ -22,7 +22,7 @@ export default defineComponent({ idField={'value'} v-model={modelValue.value} enableClear={false} - panelMinWidth={130} + minPanelWidth={130} placement={'top-left'} >
; diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 57825411188..a12a9cd96d5 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -54,11 +54,11 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return displayType === LookupDisplayType.Tree || displayType === LookupDisplayType.TreeList; }; - const setTreeInfo = (resData: TreeInfo, isNavigation = false) => { - if (resData) { + const setTreeInfo = (resposneData: TreeInfo, isNavigation = false) => { + if (resposneData) { const { layerType, dataField, parentField, pathField, layerField, isDetailField, loadDataType, - onlySelectLeaf } = resData; + onlySelectLeaf } = resposneData; const treeInfo: TreeInfo = { layerType, dataField, diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index f8ce8c95ea2..e90b1edceee 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -103,6 +103,13 @@ export class LookupPropertyConfig extends InputBaseProperty { } private getLookupConfig(editorOptions: any) { + + const getRemoteParams = () => { + const viewModelId = this.formSchemaUtils.getFormSchema().module.entity[0].id; + const formBasicInfo = this.formSchemaUtils.getFormMetadataBasicInfo(); + return {propertyData: editorOptions, formBasicInfo, viewModelId, dataSourceId: editorOptions.helpId}; + }; + return { description: "Basic Infomation", title: "编辑器", @@ -195,7 +202,50 @@ export class LookupPropertyConfig extends InputBaseProperty { formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo(), viewModelId: this.formSchemaUtils.getFormSchema().module.entity[0].id, }, - repositoryToken: FieldSelectorRepositoryToken + repositoryToken: FieldSelectorRepositoryToken, + beforeOpen: async ({ repository, notifyService }) => { + const hasDataSource = editorOptions?.helpId; + if (!hasDataSource) { + notifyService?.warning({message: '请先配置数据源!'}); + return false; + } + const repositoryParams = getRemoteParams(); + + if (repository) { + const data = await repository.getData(repositoryParams); + const conditions = await repository.getLookupConditions(repositoryParams); + return { fieldList: data, conditionList: conditions }; + } + }, + onSubmitModal: async ({loadingService, repository, conditions, originalConditions, FMessageBoxService}) => { + if (repository) { + try{ + const repositoryParams = getRemoteParams(); + + const newConditions = await repository.getLookupConditions(repositoryParams) || []; + if (JSON.stringify(newConditions) !== JSON.stringify(originalConditions.value)) { + loadingService?.clearAll(); + FMessageBoxService.question('视图对象中的帮助过滤条件已更改,请点击确定同步过滤数据', '', () => { + conditions.value = newConditions; + originalConditions.value = JSON.parse(JSON.stringify(conditions.value)); + }, () => { }); + return false; + } else { + if (JSON.stringify(conditions.value) === JSON.stringify(originalConditions.value)) { + return true; + } else { + await repository.saveFilterCondition(conditions.value, repositoryParams); + return true; + } + } + } catch (error) { + FMessageBoxService?.error('保存失败', ''); + return false; + } finally { + loadingService?.clearAll(); + } + } + } }, visible: !!editorOptions.helpId }, diff --git a/packages/ui-vue/components/sort-condition-editor/index.ts b/packages/ui-vue/components/sort-condition-editor/index.ts new file mode 100644 index 00000000000..c6e500737e8 --- /dev/null +++ b/packages/ui-vue/components/sort-condition-editor/index.ts @@ -0,0 +1,15 @@ +import type { App } from 'vue'; +import SortConditionEditor from './src/sort-condition-editor.component'; +import { propsResolver } from './src/sort-condition-editor.props'; + +export { SortConditionEditor }; + +export default { + install(app: App): void { + app.component(SortConditionEditor.name as string, SortConditionEditor); + }, + register(componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record): void { + componentMap['sort-condition-editor'] = SortConditionEditor; + propsResolverMap['sort-condition-editor'] = propsResolver; + }, +}; diff --git a/packages/ui-vue/components/sort-condition-editor/src/schema/sort-editor.json b/packages/ui-vue/components/sort-condition-editor/src/schema/sort-editor.json new file mode 100644 index 00000000000..2bcabf6f1eb --- /dev/null +++ b/packages/ui-vue/components/sort-condition-editor/src/schema/sort-editor.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://farris-design.gitee.io/field-selector.schema.json", + "title": "field-selector", + "description": "A Farris Input Component", + "type": "object", + "properties": { + "disabled": { + "description": "", + "type": "boolean", + "default": "false" + }, + "readonly": { + "description": "", + "type": "boolean", + "default": "false" + }, + "modelValue": { + "description": "", + "type": "object", + "default": null + }, + "repositoryToken": { + "description": "", + "type": "object", + "default": null + }, + "fields": { + "description": "", + "type": "array", + "default": null + }, + "editorParams": { + "type": "object", + "default": null + }, + "displayText": { + "description": "", + "type": "string", + "default": "" + }, + "enableClear": { + "description": "", + "type": "boolean", + "default": true + }, + "beforeOpen": { + "description": "", + "type": "function", + "default": null + }, + "onSubmitModal": { + "description": "", + "type": "function", + "default": null + } + } +} \ No newline at end of file diff --git a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx new file mode 100644 index 00000000000..f7156834fd5 --- /dev/null +++ b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx @@ -0,0 +1,18 @@ +import { defineComponent} from "vue"; + +import { SortConditionEditorProps, sortConditionEditorProps } from "./sort-condition-editor.props"; +import {FilterConditionEditor} from '../../filter-condition-editor'; + + +export default defineComponent({ + name: 'sort-condition-editor', + props: sortConditionEditorProps, + emits: ['update:modelValue'], + setup(props: SortConditionEditorProps, context) { + + return () => { + return + ; + }; + } +}); diff --git a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts new file mode 100644 index 00000000000..199940ebc49 --- /dev/null +++ b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts @@ -0,0 +1,62 @@ +import { ExtractPropTypes, PropType } from "vue"; +import { createPropsResolver } from "../../dynamic-resolver"; +import schema from './schema/sort-editor.json'; +import { SortCondition } from "../../filter-condition-editor"; + +export type BeforeOpenFunction = (...params: any) => Promise<{fields: any, conditions: any}>; + +export const sortConditionEditorProps = { + disabled: { + type: Boolean, + default: false + }, + readonly: { + type: Boolean, + default: false + }, + enableClear: { + type: Boolean, + default: true + }, + displayText: { + type: String, + default: '' + }, + enableExpress: { + type: Boolean, + default: false + }, + modelValue: { + type: Array, + default: [] + }, + insertType: { + type: String, + default: 'below' // 'above'|'below' + }, + fields: { + type: Array<{ label: string, value: string }>, + default: [] + }, + repositoryToken: { + type: Object, + default: null + }, + editorParams: { + type: Object, + default: null + }, + onSubmitModal: { + type: Function, + default: null + }, + beforeOpen: { + type: Function as PropType, + default: null + } +} as Record; + + +export type SortConditionEditorProps = ExtractPropTypes; + +export const propsResolver = createPropsResolver(sortConditionEditorProps, schema); diff --git a/packages/ui-vue/demos/filter-condition-editor/basic.vue b/packages/ui-vue/demos/filter-condition-editor/basic.vue index 460a8574e97..8aaf11ee3df 100644 --- a/packages/ui-vue/demos/filter-condition-editor/basic.vue +++ b/packages/ui-vue/demos/filter-condition-editor/basic.vue @@ -10,4 +10,8 @@ import { ref } from 'vue';
+ +
+ +
-- Gitee From 7c39a09a2198e092ee468db9af17e685daa85946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 20:22:12 +0800 Subject: [PATCH 035/156] =?UTF-8?q?feature:=20=E6=96=B0=E5=A2=9E=20sort-ed?= =?UTF-8?q?itor=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter-condition-editor/src/composition/use-constant-data.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts index 12a2116c734..01def9d85bc 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-constant-data.ts @@ -57,7 +57,6 @@ export function useConstantData() { ]; - return { leftBracketItems, righttBracketItems, -- Gitee From 914cc67df31739cbc252a45d87cea9071b268958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 20:27:42 +0800 Subject: [PATCH 036/156] fix: ctx rename to context --- .../filter-condition-actions.component.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx index 38bbb88e6b1..e259804ea18 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-actions.component.tsx @@ -5,34 +5,34 @@ export default defineComponent({ name: "filter-condition-actions", props: ['canClear', 'canMove', 'questionMessage'], emits: ['add', 'clear', 'moveTop', 'movePrev', 'moveNext', 'moveBottom'], - setup(props, ctx) { + setup(props, context) { const message = ref(props.questionMessage || '确定要清空所有数据吗?'); function onAddFilter() { - ctx.emit('add'); + context.emit('add'); } function onClear() { FMessageBoxService.question(message.value, '', () => { - ctx.emit('clear'); + context.emit('clear'); }, () => { }); } function onMoveTop() { - ctx.emit('moveTop'); + context.emit('moveTop'); } function onMovePrev() { - ctx.emit('movePrev'); + context.emit('movePrev'); } function onMoveNext() { - ctx.emit('moveNext'); + context.emit('moveNext'); } function onMoveBottom() { - ctx.emit('moveBottom'); + context.emit('moveBottom'); } -- Gitee From c2af55ad697f99350b7b575227f80f0975abf795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 21:31:30 +0800 Subject: [PATCH 037/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/expression-editor.component.tsx | 35 ++++++++----------- .../src/composition/use-condition-editor.ts | 2 +- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 34d774c8648..190890fc246 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -16,6 +16,7 @@ */ import { defineComponent, onMounted, ref, SetupContext, watch } from 'vue'; import { ExpressionEditorProps, expressionEditorProps } from './expression-editor.props'; +import { FLayout, FLayoutPane } from "../../../components/layout"; export default defineComponent({ name: 'FExpressionEditor', @@ -28,28 +29,20 @@ export default defineComponent({ return () => { return ( -
- - -
+
+ + + + + +
+
-

头部区域

- - - - -
-
-

左侧区域

-
- -
-
-

右侧区域

-
-
-
- +
+ + + +
); }; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 596d55c0032..2e085693743 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -50,7 +50,7 @@ export function useConditionEditor(pr context.emit('remove', { index, $event }); } - function onRowClick(item: SortCondition, index: number) { + function onRowClick(item: T, index: number) { context.emit('rowClick', { item, index }); } -- Gitee From 9dad68d1ecce10cc795892fbc2699f9b4af181ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 21:35:20 +0800 Subject: [PATCH 038/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/composition/use-condition-data.ts | 3 ++- .../src/composition/use-condition-editor.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 8460574701d..4a062426ec0 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -8,6 +8,7 @@ export function useConditionData(props, conditions) { return props.displayText || `共 ${conditions.value.length} 项`; }); + const fieldName = props.editorType !== 'sort' ? 'filterField' : 'sortField'; const newCondition = props.editorType !== 'sort' ? { filterField: '', @@ -183,7 +184,7 @@ export function useConditionData(props, conditions) { } // 检查字段是否设置 - const emptyFields = conditions.value.filter((n: any) => !n.filterField).length === 0; + const emptyFields = conditions.value.filter((n: any) => !n[fieldName]).length === 0; const result = [ { diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 596d55c0032..2e085693743 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -50,7 +50,7 @@ export function useConditionEditor(pr context.emit('remove', { index, $event }); } - function onRowClick(item: SortCondition, index: number) { + function onRowClick(item: T, index: number) { context.emit('rowClick', { item, index }); } -- Gitee From 71d7fd9e1eb768c3ad9f955526facc98ead6d7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 21:46:36 +0800 Subject: [PATCH 039/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/composition/use-condition-editor.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 2e085693743..8873ffff098 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -1,7 +1,9 @@ import { computed, ref, watch } from "vue"; import { FilterCondition, SortCondition } from "./types"; -export function useConditionEditor(props, context, tbodyRef) { +type ConditionType = SortCondition | FilterCondition; + +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const fields = ref(props.fields); -- Gitee From 7688eb3dbd793ffa225312c70e9af15d0e8d1db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 21:54:57 +0800 Subject: [PATCH 040/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 2 +- .../src/components/sort-editor/sort-editor-grid.component.tsx | 2 +- .../src/composition/use-condition-editor.ts | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index fb6ec6352e0..5108b9f7930 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -47,7 +47,7 @@ export default defineComponent({ { - conditions.value.map((item: FilterCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx index af9c6cc363a..6198d0825d8 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx @@ -36,7 +36,7 @@ export default defineComponent({ { - conditions.value.map((item: SortCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 8873ffff098..838e64ac218 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -1,9 +1,8 @@ import { computed, ref, watch } from "vue"; import { FilterCondition, SortCondition } from "./types"; -type ConditionType = SortCondition | FilterCondition; -export function useConditionEditor(props, context, tbodyRef) { +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const fields = ref(props.fields); -- Gitee From 0ddf580809a99f6487423535408ba9cfcbfc8cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 22:08:48 +0800 Subject: [PATCH 041/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 4 +--- .../components/sort-editor/sort-editor-grid.component.tsx | 3 +-- .../src/composition/use-condition-editor.ts | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 5108b9f7930..29d1f7341e8 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -3,8 +3,6 @@ import { filterConditionGridProps } from "./filter-condition-grid.props"; import { FComboList } from "../../../combo-list"; import { FButtonEdit } from '../../../button-edit'; - -import { FilterCondition } from "../composition/types"; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; @@ -24,7 +22,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx index 6198d0825d8..913f91e1e34 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx @@ -4,7 +4,6 @@ import { FComboList } from "../../../../combo-list"; import { useConstantData } from "../../composition/use-constant-data"; import { useFieldsTree } from "../../composition/use-fields-tree"; import { useConditionEditor } from "../../composition/use-condition-editor"; -import { SortCondition } from "../../composition/types"; export default defineComponent({ name: 'sort-editor-grid', @@ -17,7 +16,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 838e64ac218..671287a4ff6 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -2,7 +2,7 @@ import { computed, ref, watch } from "vue"; import { FilterCondition, SortCondition } from "./types"; -export function useConditionEditor(props, context, tbodyRef) { +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const fields = ref(props.fields); @@ -37,7 +37,7 @@ export function useConditionEditor(pr }; }); - const conditions = ref>(props.conditions as Array); + const conditions = ref(props.conditions); watch(() => props.conditions,(newValue) => { conditions.value = newValue; @@ -51,7 +51,7 @@ export function useConditionEditor(pr context.emit('remove', { index, $event }); } - function onRowClick(item: T, index: number) { + function onRowClick(item: Record, index: number) { context.emit('rowClick', { item, index }); } -- Gitee From d72519143a637883f353caa6d8641326c21974dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 22:11:12 +0800 Subject: [PATCH 042/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 5 +++-- .../components/sort-editor/sort-editor-grid.component.tsx | 5 +++-- .../src/composition/use-condition-editor.ts | 7 +++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 29d1f7341e8..ff9fd98525b 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -6,6 +6,7 @@ import { FButtonEdit } from '../../../button-edit'; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; +import { FilterCondition } from "../composition/types"; export default defineComponent({ name: 'filter-condition-grid', @@ -22,7 +23,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); @@ -45,7 +46,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + conditions.value.map((item: FilterCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx index 913f91e1e34..af9c6cc363a 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx @@ -4,6 +4,7 @@ import { FComboList } from "../../../../combo-list"; import { useConstantData } from "../../composition/use-constant-data"; import { useFieldsTree } from "../../composition/use-fields-tree"; import { useConditionEditor } from "../../composition/use-condition-editor"; +import { SortCondition } from "../../composition/types"; export default defineComponent({ name: 'sort-editor-grid', @@ -16,7 +17,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); @@ -35,7 +36,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + conditions.value.map((item: SortCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 671287a4ff6..838d3a68d25 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -1,8 +1,7 @@ import { computed, ref, watch } from "vue"; -import { FilterCondition, SortCondition } from "./types"; -export function useConditionEditor(props, context, tbodyRef) { +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const fields = ref(props.fields); @@ -37,7 +36,7 @@ export function useConditionEditor(props, context, tbodyRef) { }; }); - const conditions = ref(props.conditions); + const conditions = ref>(props.conditions as Array); watch(() => props.conditions,(newValue) => { conditions.value = newValue; @@ -51,7 +50,7 @@ export function useConditionEditor(props, context, tbodyRef) { context.emit('remove', { index, $event }); } - function onRowClick(item: Record, index: number) { + function onRowClick(item: T, index: number) { context.emit('rowClick', { item, index }); } -- Gitee From 122ff07f8ef01362dc83bda81c284f3eaf0e3edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 10 Mar 2025 22:18:01 +0800 Subject: [PATCH 043/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 5 ++--- .../components/sort-editor/sort-editor-grid.component.tsx | 4 ++-- .../src/composition/use-condition-editor.ts | 6 +++--- .../src/composition/use-fields-tree.tsx | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index ff9fd98525b..29d1f7341e8 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -6,7 +6,6 @@ import { FButtonEdit } from '../../../button-edit'; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; -import { FilterCondition } from "../composition/types"; export default defineComponent({ name: 'filter-condition-grid', @@ -23,7 +22,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); @@ -46,7 +45,7 @@ export default defineComponent({ { - conditions.value.map((item: FilterCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx index af9c6cc363a..98e98129b1c 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx @@ -17,7 +17,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); @@ -36,7 +36,7 @@ export default defineComponent({ { - conditions.value.map((item: SortCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 838d3a68d25..5d3e190fd0e 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -1,7 +1,7 @@ import { computed, ref, watch } from "vue"; -export function useConditionEditor(props, context, tbodyRef) { +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const fields = ref(props.fields); @@ -36,7 +36,7 @@ export function useConditionEditor(props, context, tbodyRef) { }; }); - const conditions = ref>(props.conditions as Array); + const conditions = ref(props.conditions); watch(() => props.conditions,(newValue) => { conditions.value = newValue; @@ -50,7 +50,7 @@ export function useConditionEditor(props, context, tbodyRef) { context.emit('remove', { index, $event }); } - function onRowClick(item: T, index: number) { + function onRowClick(item: any, index: number) { context.emit('rowClick', { item, index }); } diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx index 798c6ae953b..0f2d476efb4 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx @@ -1,5 +1,4 @@ import { FComboTree } from "../../../combo-tree"; -import { FilterCondition, SortCondition } from "./types"; import { treeNodeStatus } from "./use-constant-data"; -- Gitee From 0efac35c5c70a7aec1c8e97cb5c1e00657230aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 08:44:39 +0800 Subject: [PATCH 044/156] =?UTF-8?q?fix:=20=E5=8F=82=E6=95=B0=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-grid.props.ts => condition-grid.props.ts} | 5 +- .../filter-condition-grid.component.tsx | 6 +- .../sort-editor-grid.component.tsx | 13 ++- .../sort-editor/sort-editor.props.ts | 23 ----- .../src/composition/use-condition-data.ts | 92 +++++++++++-------- .../src/composition/use-condition-editor.ts | 11 +-- .../src/filter-condition-editor.component.tsx | 2 +- 7 files changed, 69 insertions(+), 83 deletions(-) rename packages/ui-vue/components/filter-condition-editor/src/components/{filter-condition-grid.props.ts => condition-grid.props.ts} (73%) rename packages/ui-vue/components/filter-condition-editor/src/components/{sort-editor => }/sort-editor-grid.component.tsx (88%) delete mode 100644 packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts similarity index 73% rename from packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts rename to packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts index eca3b5a3721..8bb25a81794 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts @@ -1,8 +1,7 @@ -import { FilterCondition } from "../composition/types"; -export const filterConditionGridProps = { +export const conditionGridProps = { conditions: { - type: Array, + type: Array, default: [], }, fields: { diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 29d1f7341e8..6a6c17e2e8d 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -1,5 +1,5 @@ import { defineComponent, onUpdated, ref } from "vue"; -import { filterConditionGridProps } from "./filter-condition-grid.props"; +import { conditionGridProps } from "./condition-grid.props"; import { FComboList } from "../../../combo-list"; import { FButtonEdit } from '../../../button-edit'; @@ -9,7 +9,7 @@ import { useConditionEditor } from "../composition/use-condition-editor"; export default defineComponent({ name: 'filter-condition-grid', - props: filterConditionGridProps, + props: conditionGridProps, emits: ['insert', 'remove', 'rowClick'], setup(props, context) { const { compareOperators, leftBracketItems, valueTypes, @@ -119,7 +119,7 @@ export default defineComponent({ placement={'auto'} > - + ; }) } diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx similarity index 88% rename from packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx rename to packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 98e98129b1c..4802e6d9093 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -1,14 +1,13 @@ import { defineComponent, onUpdated, ref } from "vue"; -import { sortEditorProps } from "./sort-editor.props"; -import { FComboList } from "../../../../combo-list"; -import { useConstantData } from "../../composition/use-constant-data"; -import { useFieldsTree } from "../../composition/use-fields-tree"; -import { useConditionEditor } from "../../composition/use-condition-editor"; -import { SortCondition } from "../../composition/types"; +import { FComboList } from "../../../combo-list"; +import { useConstantData } from "../composition/use-constant-data"; +import { useFieldsTree } from "../composition/use-fields-tree"; +import { useConditionEditor } from "../composition/use-condition-editor"; +import { conditionGridProps } from "./condition-grid.props"; export default defineComponent({ name: 'sort-editor-grid', - props: sortEditorProps, + props: conditionGridProps, emits: ['insert','remove', 'rowClick'], setup(props, context) { const { sortTypes } = useConstantData(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts deleted file mode 100644 index 5919f61055d..00000000000 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor/sort-editor.props.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SortCondition } from "../../composition/types"; - - -export const sortEditorProps = { - conditions: { - type: Array, - default: [], - }, - fields: { - type: Array<{label: string, value: string}>, - default: [], - }, - activeIndex: { - type: Number, - default: -1, - }, - formatter: { - type: Function, - default: (cell, data) => { - return `${data.raw['name']} [${data.raw['path']}]`; - } - } -}; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 4a062426ec0..5ee33bdb314 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -45,11 +45,14 @@ export function useConditionData(props, conditions) { function onAddFilter() { const newItem = Object.assign({}, newCondition); - conditions.value.forEach(condition => { - if (condition.relation === FilterRelation.Empty || !condition.relation) { - condition.relation = FilterRelation.And; - } - }); + if (props.editorType !== 'sort') { + conditions.value.forEach(condition => { + if (condition.relation === FilterRelation.Empty || !condition.relation) { + condition.relation = FilterRelation.And; + } + }); + } + conditions.value = [...conditions.value, newItem]; const newIndex = conditions.value.length - 1; activeRow.value = { index: newIndex, condition: newItem }; @@ -57,7 +60,11 @@ export function useConditionData(props, conditions) { function insertCondition({index}) { - const _newCondition = Object.assign({}, newCondition, { relation: FilterRelation.And }); + const _newCondition = Object.assign({}, newCondition); + if (props.editorType !== 'sort') { + Object.assign({}, _newCondition, { relation: FilterRelation.And }); + } + if (props.insertType === 'above') { if (index === 0) { conditions.value.unshift(_newCondition); @@ -145,42 +152,47 @@ export function useConditionData(props, conditions) { function validateCondition() { const total = conditions.value.length; if (total) { - // 清除最后条件的关系符 - conditions.value[total - 1].relation = FilterRelation.Empty; - - // 检查关系连接符 - const emptyRelations = conditions.value - .map((condition: any, index) => { - if (condition.relation === "" + FilterRelation.Empty) { - return { index, filter: condition }; - } - return null; - }) - .filter((condition: any, index) => { - return condition && index !== total - index; - }); - - let relationChecked = true; - if (emptyRelations.length) { - relationChecked = false; - } + + let bracketChecked = true; // 括号是否匹配 + let relationChecked = true; // 关系连接符是否完整 + + if (props.editorType !== 'sort') { + // 清除最后条件的关系符 + conditions.value[total - 1].relation = FilterRelation.Empty; + + // 检查关系连接符 + const emptyRelations = conditions.value + .map((condition: any, index) => { + if (condition.relation === "" + FilterRelation.Empty) { + return { index, filter: condition }; + } + return null; + }) + .filter((condition: any, index) => { + return condition && index !== total - index; + }); + + + if (emptyRelations.length) { + relationChecked = false; + } - // 检查括号 - let bracketChecked = true; - let bracketResult = ''; - for (let i = 0; i < total; i++) { - const item = conditions.value[i]; - bracketResult += item.lbracket + item.rbracket; - } - - const l = bracketResult.length ; - if (l % 2 > 0) { - bracketChecked = false; - } else { - for(let i =0; i< l; i++){ - bracketResult = bracketResult.replace('()', ''); + + let bracketResult = ''; + for (let i = 0; i < total; i++) { + const item = conditions.value[i]; + bracketResult += item.lbracket + item.rbracket; + } + + const l = bracketResult.length ; + if (l % 2 > 0) { + bracketChecked = false; + } else { + for(let i =0; i< l; i++){ + bracketResult = bracketResult.replace('()', ''); + } + bracketChecked = !bracketResult.length; } - bracketChecked = !bracketResult.length; } // 检查字段是否设置 diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index 5d3e190fd0e..f5618326b8a 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -3,12 +3,16 @@ import { computed, ref, watch } from "vue"; export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); - + const conditions = ref(props.conditions); const fields = ref(props.fields); watch(() => props.fields, (newValue) => { fields.value = newValue; }); + watch(() => props.conditions,(newValue) => { + conditions.value = newValue; + }); + watch(() => props.activeIndex, (newValue) => { activeIndex.value = newValue; }); @@ -36,11 +40,6 @@ export function useConditionEditor(props, context, tbodyRef) { }; }); - const conditions = ref(props.conditions); - - watch(() => props.conditions,(newValue) => { - conditions.value = newValue; - }); function onInsert(index: number, $event: MouseEvent) { context.emit('insert', { index, $event }); diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index c0bb97bda86..bf89e405490 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -4,7 +4,7 @@ import FButtonEdit from '../../button-edit/src/button-edit.component'; import { FilterConditionEditorProps, filterConditionEditorProps } from "./filter-condition-editor.props"; import ConditionGrid from './components/filter-condition-grid.component'; import ConditionActions from './components/filter-condition-actions.component'; -import SortConditionActions from './components/sort-editor/sort-editor-grid.component'; +import SortConditionActions from './components/sort-editor-grid.component'; import { useConditionData } from "./composition/use-condition-data"; import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; -- Gitee From 2ae70b4c5c0c0d8cc1be928bd0de3535afd454ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 09:05:41 +0800 Subject: [PATCH 045/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 3 ++- .../src/components/sort-editor-grid.component.tsx | 3 ++- .../src/filter-condition-editor.props.ts | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 6a6c17e2e8d..8cf4e04e12f 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -6,6 +6,7 @@ import { FButtonEdit } from '../../../button-edit'; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; +import { FilterCondition } from "../composition/types"; export default defineComponent({ name: 'filter-condition-grid', @@ -45,7 +46,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + conditions.value.map((item: FilterCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 4802e6d9093..51b9dbb3e7b 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -4,6 +4,7 @@ import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; import { conditionGridProps } from "./condition-grid.props"; +import { SortCondition } from "../composition/types"; export default defineComponent({ name: 'sort-editor-grid', @@ -35,7 +36,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + conditions.value.map((item: SortCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts index 6fe3a7beeff..a45b531e345 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType, readonly } from "vue"; import { createPropsResolver } from "../../dynamic-resolver"; import schema from './schema/filter-condition-editor.json'; -import { FilterCondition } from "./composition/types"; +import { FilterCondition, SortCondition } from "./composition/types"; export type BeforeOpenFunction = (...params: any) => Promise<{fieldList: any, conditionList: any}>; @@ -27,7 +27,7 @@ export const filterConditionEditorProps = { default: false }, modelValue: { - type: Array, + type: Array, default: [] }, insertType: { -- Gitee From 453de568b57e35ac7c6ed97ef72a4aeff12347e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 09:22:53 +0800 Subject: [PATCH 046/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/composition/types.ts | 41 +++++++++++++------ .../src/filter-condition-editor.props.ts | 4 +- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts index 63fc7d1bfa8..dd81ebd5f81 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts @@ -30,22 +30,39 @@ export enum ExpressValueType { } -export interface FilterCondition { - lbracket?: string; - filterField: string; - compare?: Compare; - value: string; - rbracket?: string; - relation?: FilterRelation; - expresstype?: ExpressValueType; -} +// export interface FilterCondition { +// lbracket?: string; +// filterField: string; +// compare?: Compare; +// value: string; +// rbracket?: string; +// relation?: FilterRelation; +// expresstype?: ExpressValueType; +// } + +// export interface SortCondition { +// sortField: string; +// sortType: SortType; +// } + export declare enum SortType { Asc = 'asc', Desc = 'desc' } -export interface SortCondition { - sortField: string; - sortType: SortType; + +export interface FilterSortCondition { + lbracket?: string; + filterField?: string; + compare?: Compare; + value?: string; + rbracket?: string; + relation?: FilterRelation; + expresstype?: ExpressValueType; + sortField?: string; + sortType?: SortType; } + +export type FilterCondition = Pick; +export type SortCondition = Pick; diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts index a45b531e345..f50b0f90d33 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType, readonly } from "vue"; import { createPropsResolver } from "../../dynamic-resolver"; import schema from './schema/filter-condition-editor.json'; -import { FilterCondition, SortCondition } from "./composition/types"; +import { FilterCondition, FilterSortCondition, SortCondition } from "./composition/types"; export type BeforeOpenFunction = (...params: any) => Promise<{fieldList: any, conditionList: any}>; @@ -27,7 +27,7 @@ export const filterConditionEditorProps = { default: false }, modelValue: { - type: Array, + type: Array>, default: [] }, insertType: { -- Gitee From ca442794d98052a813fa43e497cfaf41ce1a5b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 09:27:52 +0800 Subject: [PATCH 047/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/filter-condition-editor.props.ts | 2 +- .../sort-condition-editor/src/sort-condition-editor.props.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts index f50b0f90d33..684430c4f5f 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -1,7 +1,7 @@ import { ExtractPropTypes, PropType, readonly } from "vue"; import { createPropsResolver } from "../../dynamic-resolver"; import schema from './schema/filter-condition-editor.json'; -import { FilterCondition, FilterSortCondition, SortCondition } from "./composition/types"; +import { FilterSortCondition } from "./composition/types"; export type BeforeOpenFunction = (...params: any) => Promise<{fieldList: any, conditionList: any}>; diff --git a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts index 199940ebc49..7f95fd0a2cd 100644 --- a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts +++ b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts @@ -1,7 +1,6 @@ import { ExtractPropTypes, PropType } from "vue"; import { createPropsResolver } from "../../dynamic-resolver"; import schema from './schema/sort-editor.json'; -import { SortCondition } from "../../filter-condition-editor"; export type BeforeOpenFunction = (...params: any) => Promise<{fields: any, conditions: any}>; @@ -27,7 +26,7 @@ export const sortConditionEditorProps = { default: false }, modelValue: { - type: Array, + type: Array, default: [] }, insertType: { -- Gitee From 5bd5139f5db084577bc3cdaaaa68f9d5ec5126be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 09:35:53 +0800 Subject: [PATCH 048/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/filter-condition-grid.component.tsx | 2 +- .../src/components/sort-editor-grid.component.tsx | 2 +- .../src/filter-condition-editor.props.ts | 2 +- .../src/sort-condition-editor.component.tsx | 2 +- .../sort-condition-editor/src/sort-condition-editor.props.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 8cf4e04e12f..c8df88a5a89 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -46,7 +46,7 @@ export default defineComponent({ { - conditions.value.map((item: FilterCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 51b9dbb3e7b..b09ee79bdc3 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -36,7 +36,7 @@ export default defineComponent({ { - conditions.value.map((item: SortCondition, index: number) => { + conditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts index 684430c4f5f..90bb2a4e493 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -27,7 +27,7 @@ export const filterConditionEditorProps = { default: false }, modelValue: { - type: Array>, + type: Array, default: [] }, insertType: { diff --git a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx index f7156834fd5..4a471dfc2be 100644 --- a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx +++ b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.component.tsx @@ -8,7 +8,7 @@ export default defineComponent({ name: 'sort-condition-editor', props: sortConditionEditorProps, emits: ['update:modelValue'], - setup(props: SortConditionEditorProps, context) { + setup(props, context) { return () => { return diff --git a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts index 7f95fd0a2cd..c786585a85c 100644 --- a/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts +++ b/packages/ui-vue/components/sort-condition-editor/src/sort-condition-editor.props.ts @@ -26,7 +26,7 @@ export const sortConditionEditorProps = { default: false }, modelValue: { - type: Array, + type: Array, default: [] }, insertType: { -- Gitee From a5d824584f17f643647023f46eeea8d01ea54b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 10:02:04 +0800 Subject: [PATCH 049/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/condition-grid.props.ts | 4 +++ .../filter-condition-grid.component.tsx | 1 - .../components/sort-editor-grid.component.tsx | 5 ++-- .../src/composition/types.ts | 28 +++++++++---------- .../src/composition/use-condition-editor.ts | 7 +++++ .../src/filter-condition-editor.component.tsx | 8 +++--- .../src/filter-condition-editor.props.ts | 1 - 7 files changed, 31 insertions(+), 23 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts index 8bb25a81794..16fb16d8eee 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts @@ -1,5 +1,9 @@ export const conditionGridProps = { + sortConditions: { + type: Array, + default: [], + }, conditions: { type: Array, default: [], diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index c8df88a5a89..6a6c17e2e8d 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -6,7 +6,6 @@ import { FButtonEdit } from '../../../button-edit'; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; -import { FilterCondition } from "../composition/types"; export default defineComponent({ name: 'filter-condition-grid', diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index b09ee79bdc3..62d17a63dff 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -4,7 +4,6 @@ import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; import { conditionGridProps } from "./condition-grid.props"; -import { SortCondition } from "../composition/types"; export default defineComponent({ name: 'sort-editor-grid', @@ -16,7 +15,7 @@ export default defineComponent({ const tbodyRef = ref(); const { - conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView + sortConditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { @@ -36,7 +35,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + sortConditions.value.map((item: any, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts index dd81ebd5f81..e2d716b76ac 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts @@ -46,23 +46,23 @@ export enum ExpressValueType { // } -export declare enum SortType { +export enum SortType { Asc = 'asc', Desc = 'desc' } -export interface FilterSortCondition { - lbracket?: string; - filterField?: string; - compare?: Compare; - value?: string; - rbracket?: string; - relation?: FilterRelation; - expresstype?: ExpressValueType; - sortField?: string; - sortType?: SortType; -} +// export interface FilterSortCondition { +// lbracket?: string; +// filterField?: string; +// compare?: Compare; +// value?: string; +// rbracket?: string; +// relation?: FilterRelation; +// expresstype?: ExpressValueType; +// sortField?: string; +// sortType?: SortType; +// } -export type FilterCondition = Pick; -export type SortCondition = Pick; +// export type FilterCondition = Pick; +// export type SortCondition = Pick; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index f5618326b8a..eb22108b550 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -4,6 +4,8 @@ import { computed, ref, watch } from "vue"; export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); const conditions = ref(props.conditions); + const sortConditions = ref(props.sortConditions); + const fields = ref(props.fields); watch(() => props.fields, (newValue) => { fields.value = newValue; @@ -13,6 +15,10 @@ export function useConditionEditor(props, context, tbodyRef) { conditions.value = newValue; }); + watch(() => props.sortConditions,(newValue) => { + sortConditions.value = newValue; + }); + watch(() => props.activeIndex, (newValue) => { activeIndex.value = newValue; }); @@ -60,6 +66,7 @@ export function useConditionEditor(props, context, tbodyRef) { activeIndex, selectedRowRef, conditions, + sortConditions, tbodyRef, onInsert, onRemove, diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index bf89e405490..4c5a9ba4f47 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -4,7 +4,7 @@ import FButtonEdit from '../../button-edit/src/button-edit.component'; import { FilterConditionEditorProps, filterConditionEditorProps } from "./filter-condition-editor.props"; import ConditionGrid from './components/filter-condition-grid.component'; import ConditionActions from './components/filter-condition-actions.component'; -import SortConditionActions from './components/sort-editor-grid.component'; +import SortConditionGrod from './components/sort-editor-grid.component'; import { useConditionData } from "./composition/use-condition-data"; import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; @@ -40,13 +40,13 @@ export default defineComponent({ function renderEditGrid() { if (props.editorType === 'sort') { - return onInsert(payload)} onRemove={(payload) => onRemove(payload)} - onRowClick={(payload) => onSelectRow(payload)}>; + onRowClick={(payload) => onSelectRow(payload)}>; } return Promise<{fieldList: any, conditionList: any}>; -- Gitee From 2e194cb70aa89ff84daa7820d780fd4510c7a23f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 10:40:51 +0800 Subject: [PATCH 050/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/condition-grid.props.ts | 4 --- .../filter-condition-grid.component.tsx | 3 ++- .../components/sort-editor-grid.component.tsx | 5 ++-- .../src/composition/types.ts | 26 +++++++++---------- .../src/filter-condition-editor.component.tsx | 9 ++++--- .../src/sort-condition-editor.component.tsx | 5 ++-- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts index 16fb16d8eee..8bb25a81794 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts @@ -1,9 +1,5 @@ export const conditionGridProps = { - sortConditions: { - type: Array, - default: [], - }, conditions: { type: Array, default: [], diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 6a6c17e2e8d..8cf4e04e12f 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -6,6 +6,7 @@ import { FButtonEdit } from '../../../button-edit'; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; +import { FilterCondition } from "../composition/types"; export default defineComponent({ name: 'filter-condition-grid', @@ -45,7 +46,7 @@ export default defineComponent({ { - conditions.value.map((item: any, index: number) => { + conditions.value.map((item: FilterCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 62d17a63dff..51b9dbb3e7b 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -4,6 +4,7 @@ import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; import { conditionGridProps } from "./condition-grid.props"; +import { SortCondition } from "../composition/types"; export default defineComponent({ name: 'sort-editor-grid', @@ -15,7 +16,7 @@ export default defineComponent({ const tbodyRef = ref(); const { - sortConditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView + conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { @@ -35,7 +36,7 @@ export default defineComponent({ { - sortConditions.value.map((item: any, index: number) => { + conditions.value.map((item: SortCondition, index: number) => { return onRowClick(item, index)}> diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts index e2d716b76ac..f38fa103457 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/types.ts @@ -52,17 +52,17 @@ export enum SortType { } -// export interface FilterSortCondition { -// lbracket?: string; -// filterField?: string; -// compare?: Compare; -// value?: string; -// rbracket?: string; -// relation?: FilterRelation; -// expresstype?: ExpressValueType; -// sortField?: string; -// sortType?: SortType; -// } +export interface FilterSortCondition { + lbracket?: string; + filterField?: string; + compare?: Compare; + value?: string; + rbracket?: string; + relation?: FilterRelation; + expresstype?: ExpressValueType; + sortField?: string; + sortType?: SortType; +} -// export type FilterCondition = Pick; -// export type SortCondition = Pick; +export type FilterCondition = Pick; +export type SortCondition = Pick; diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index 4c5a9ba4f47..247cb2c0135 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -4,9 +4,10 @@ import FButtonEdit from '../../button-edit/src/button-edit.component'; import { FilterConditionEditorProps, filterConditionEditorProps } from "./filter-condition-editor.props"; import ConditionGrid from './components/filter-condition-grid.component'; import ConditionActions from './components/filter-condition-actions.component'; -import SortConditionGrod from './components/sort-editor-grid.component'; +import SortConditionGrid from './components/sort-editor-grid.component'; import { useConditionData } from "./composition/use-condition-data"; + import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; import { FMessageBoxService } from "../../../components/message-box"; import { FLoadingService } from "@farris/ui-vue/components/loading"; @@ -40,13 +41,13 @@ export default defineComponent({ function renderEditGrid() { if (props.editorType === 'sort') { - return onInsert(payload)} onRemove={(payload) => onRemove(payload)} - onRowClick={(payload) => onSelectRow(payload)}>; + onRowClick={(payload) => onSelectRow(payload)}>; } return { - return - ; + return ; }; } }); -- Gitee From c2e2069e000ae15804341666d40371f0ae52309b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 10:51:57 +0800 Subject: [PATCH 051/156] =?UTF-8?q?fix:=20=E7=B1=BB=E5=9E=8B=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/filter-condition-grid.component.tsx | 2 +- .../src/components/sort-editor-grid.component.tsx | 2 +- .../src/composition/use-condition-editor.ts | 12 +++--------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index 8cf4e04e12f..f774f554ad6 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -23,7 +23,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 51b9dbb3e7b..e13f4ddfa7d 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -17,7 +17,7 @@ export default defineComponent({ const { conditions, fields, onInsert, onRemove, onRowClick, activeRowCls, itemIntoView - } = useConditionEditor(props, context, tbodyRef); + } = useConditionEditor(props, context, tbodyRef); onUpdated(() => { itemIntoView(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts index eb22108b550..d1f6d1b1014 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-editor.ts @@ -1,10 +1,9 @@ -import { computed, ref, watch } from "vue"; +import { computed, Ref, ref, watch } from "vue"; -export function useConditionEditor(props, context, tbodyRef) { +export function useConditionEditor(props, context, tbodyRef) { const activeIndex = ref(props.activeIndex); - const conditions = ref(props.conditions); - const sortConditions = ref(props.sortConditions); + const conditions = ref(props.conditions) as Ref>; const fields = ref(props.fields); watch(() => props.fields, (newValue) => { @@ -15,10 +14,6 @@ export function useConditionEditor(props, context, tbodyRef) { conditions.value = newValue; }); - watch(() => props.sortConditions,(newValue) => { - sortConditions.value = newValue; - }); - watch(() => props.activeIndex, (newValue) => { activeIndex.value = newValue; }); @@ -66,7 +61,6 @@ export function useConditionEditor(props, context, tbodyRef) { activeIndex, selectedRowRef, conditions, - sortConditions, tbodyRef, onInsert, onRemove, -- Gitee From 49404881d4d038c827ef2c349b1756e307af2dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 11:29:18 +0800 Subject: [PATCH 052/156] =?UTF-8?q?fix:=20=E7=AA=97=E5=8F=A3=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E5=90=8E=EF=BC=8C=E9=87=8D=E7=BD=AE=E7=84=A6=E7=82=B9?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/sort-editor-grid.component.tsx | 3 +-- .../src/filter-condition-editor.component.tsx | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index e13f4ddfa7d..4fcc4e9fac0 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -23,7 +23,6 @@ export default defineComponent({ itemIntoView(); }); - return () => { return
@@ -58,7 +57,7 @@ export default defineComponent({ placement={'auto'} > - + ; }) } diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index 247cb2c0135..c8190863500 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -69,6 +69,7 @@ export default defineComponent({ const canClose = await props.onSubmitModal({loadingService, repository, conditions, originalConditions, FMessageBoxService}); loadingService?.clearAll(); if (canClose) { + activeRow.value.index = -1; notifyService.success('过滤条件配置成功!'); } return canClose; @@ -95,6 +96,7 @@ export default defineComponent({ class: 'btn btn-secondary', handle: ($event: MouseEvent) => { conditions.value = originalConditions.value; + activeRow.value.index = -1; return true; } }, -- Gitee From 6d0e7d5911fe8d161dacc47ed84aae0578c70465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 11 Mar 2025 21:49:01 +0800 Subject: [PATCH 053/156] feature: expression-editor --- .../components/expression-editor/index.ts | 17 +- .../components/expression-code.component.tsx | 81 +++ .../functions/common-functions.component.tsx | 136 +++++ .../functions/common-functions.props.ts | 14 + .../composition/functions-data/advanced.ts | 59 ++ .../composition/functions-data/analytical.ts | 482 ++++++++++++++++ .../composition/functions-data/date-time.ts | 531 ++++++++++++++++++ .../src/composition/functions-data/index.ts | 16 + .../composition/functions-data/math-number.ts | 121 ++++ .../src/composition/functions-data/string.ts | 300 ++++++++++ .../composition/functions-data/translate.ts | 146 +++++ .../src/composition/types.ts | 4 + .../expression-editor.design.component.tsx | 32 -- .../src/expression-editor.component.tsx | 12 +- .../src/expression-editor.props.ts | 5 +- .../src/expression-textbox.component.tsx | 65 +++ .../src/expression-textbox.props.ts | 27 + .../expression-editor.property-config.json | 25 - .../components/expression-editor/style.scss | 54 ++ .../ui-vue/demos/expression-editor/basic.vue | 6 +- packages/ui-vue/package.json | 7 +- pnpm-lock.yaml | 505 ++++++++--------- 22 files changed, 2281 insertions(+), 364 deletions(-) create mode 100644 packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/date-time.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/types.ts delete mode 100644 packages/ui-vue/components/expression-editor/src/designer/expression-editor.design.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts delete mode 100644 packages/ui-vue/components/expression-editor/src/property-config/expression-editor.property-config.json create mode 100644 packages/ui-vue/components/expression-editor/style.scss diff --git a/packages/ui-vue/components/expression-editor/index.ts b/packages/ui-vue/components/expression-editor/index.ts index 5c45ea91881..d5641751bce 100644 --- a/packages/ui-vue/components/expression-editor/index.ts +++ b/packages/ui-vue/components/expression-editor/index.ts @@ -16,23 +16,20 @@ */ import type { App } from 'vue'; import ExpressionEditor from './src/expression-editor.component'; -import ExpressionEditorDesign from './src/designer/expression-editor.design.component'; -import { propsResolver } from './src/expression-editor.props'; +import FExpressionTextbox from './src/expression-textbox.component'; +import { expressionTextboxProps } from './src/expression-textbox.props'; +import './style.scss'; export * from './src/expression-editor.props'; -export { ExpressionEditor }; +export { ExpressionEditor, FExpressionTextbox }; export default { install(app: App): void { - app.component(ExpressionEditor.name as string, ExpressionEditor); + app.component(FExpressionTextbox.name as string, FExpressionTextbox); }, register(componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record): void { - componentMap['expression-editor'] = ExpressionEditor; - propsResolverMap['expression-editor'] = propsResolver; - }, - registerDesigner(componentMap: Record, propsResolverMap: Record, configResolverMap: Record): void { - componentMap['expression-editor'] = ExpressionEditorDesign; - propsResolverMap['expression-editor'] = propsResolver; + componentMap['expression-editor'] = FExpressionTextbox; + propsResolverMap['expression-editor'] = expressionTextboxProps; } }; diff --git a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx new file mode 100644 index 00000000000..53cdb05d512 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx @@ -0,0 +1,81 @@ +import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from "vue"; +import loader from "@monaco-editor/loader"; + + +export default defineComponent({ + name: 'expression-code', + props: { + modelValue: { type: String, default: '' }, + language: { type: String, default: 'typescript' }, + theme: { type: String, default: 'vs-dark' }, + readOnly: { type: Boolean, default: false }, + configPath: { type: String, default: 'assets/monaco-editor.config.json' } + }, + emits: [], + setup(props, context) { + const editorContainer = ref(); + let editorInstance: any = null; + const codeValues = ref(props.modelValue); + + async function getMonacoEditorConfig() { + return fetch(props.configPath).then((config: Record) => { + return config.json(); + }); + } + + async function initMonacoEditor() { + if (editorContainer.value && !editorInstance) { + const config = await getMonacoEditorConfig(); + const { vsPath } = config; + loader.config({ paths: { vs: window.location.origin + vsPath } }); + loader.config({ "vs/nls": { availableLanguages: { "*": "zh-cn" } } }); + + loader.init().then((monaco) => { + editorInstance = monaco.editor.create(editorContainer.value, { + value: codeValues.value, + language: props.language, + theme: props.theme, + folding: true, + readOnly: props.readOnly + }); + }); + } + } + + watch(() => props.modelValue, (newValue) => { + codeValues.value = newValue; + editorInstance?.setValue(newValue); + }); + const resizeObserver = new ResizeObserver(entries => { + editorInstance?.layout(); + }); + + function getContent() { + return editorInstance?.getValue(); + } + + onMounted(() => { + initMonacoEditor(); + editorContainer.value && resizeObserver.observe(editorContainer.value); + }); + + onBeforeUnmount(() => { + if (editorInstance) { + editorInstance.dispose(); + } + + if (resizeObserver && editorContainer.value) { + resizeObserver.unobserve(editorContainer.value); + resizeObserver.disconnect(); + } + }); + + context.expose({ + getContent + }); + + return () => { + return
; + }; + } +}); diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx new file mode 100644 index 00000000000..1c4cb25cbe0 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx @@ -0,0 +1,136 @@ +import { computed, defineComponent, nextTick, onMounted, onUpdated, Ref, ref, watch } from "vue"; + +import { FLayout, FLayoutPane } from "../../../../../components/layout"; + +import { commonFunctions } from "../../composition/functions-data"; +import { commonFunctionsProps } from "./common-functions.props"; +import { DisabledFunction } from "../../composition/types"; + +export default defineComponent({ + name: 'FExpressionEditor', + props: commonFunctionsProps, + emits: [] as (string[] & ThisType) | undefined, + setup(props, context) { + const commonFunctionRef = ref(); + const currentFunctionType = ref(''); + const currentFunctionItem = ref(); + + const functionTypeExtendClass = computed(() => { + return (functionTypeName: string) => { + return { + "functions-type d-flex flex-column": true, + open: currentFunctionType.value === functionTypeName, + closed: currentFunctionType.value !== functionTypeName + }; + }; + }); + + const functionTypeIconClass = computed(() => { + return (functionTypeName: string) => { + return { + "f-icon f-icon-arrow-chevron-down": currentFunctionType.value === functionTypeName, + "f-icon f-icon-arrow-chevron-right": currentFunctionType.value!== functionTypeName + }; + }; + }); + + const selectedFunctionClass = computed(() => { + return (functionItem: any) => { + return { + "functions-item pl-2": true, + "selected": currentFunctionItem.value?.key === functionItem.key + }; + }; + }); + + const disabled = ref(props.disabled || {}) as Ref; + // 常用函数类型 + const functionsTypes = ref(Object.keys(commonFunctions)); + + if (disabled.value) { + const { types: disabledTypes, functions: disabledFunctions } = disabled.value; + if (disabledTypes && disabledTypes.length) { + functionsTypes.value = functionsTypes.value.filter((functionType) => { + return disabledTypes.includes(functionType); + }); + } + + if (disabledFunctions && disabledFunctions.length) { + Object.values(commonFunctions).forEach((functions) => { + functions.items.forEach((functionItem) => { + if (disabledFunctions.includes(functionItem.name)) { + functionItem['visible'] = false; + } + }); + }); + } + } + + function functionTypeIntoView() { + const functionTypeDom = commonFunctionRef.value.querySelector('li[function-type="'+ currentFunctionType.value +'"] > div.functions-type-name'); + if (functionTypeDom) { + functionTypeDom.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + } + + function onFunctionTypeClick(functionTypeName: string) { + if (currentFunctionType.value === functionTypeName) { + currentFunctionType.value = ''; + return; + } + currentFunctionType.value = ''; + setTimeout(() => { + currentFunctionType.value = currentFunctionType.value = functionTypeName; + functionTypeIntoView(); + }, 200); + } + + function onFunctionItemClick($event: MouseEvent, functionItem: any) { + $event.stopPropagation(); + currentFunctionItem.value = functionItem; + } + + + onMounted(() => { + currentFunctionType.value = functionsTypes.value[0]; + }); + + + return () => { + return
+ + + +
+
    + { functionsTypes.value.map((type) => { + return
  • {onFunctionTypeClick(type)}}> +
    + + {commonFunctions[type].name} +
    +
      + {commonFunctions[type].items.map((item) => { + if (item.visible !== false) { + return
    • onFunctionItemClick(payload, item)}>{item.name}
    • ; + } + })} +
    +
  • ; + }) } +
+
+
+ + + +
+ + +
; + }; + } +}); diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts new file mode 100644 index 00000000000..dc32f668200 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts @@ -0,0 +1,14 @@ +import { PropType } from "vue"; +import { DisabledFunction } from "../../composition/types"; + + +export const commonFunctionsProps = { + data: { + type: Array, + default: [] + }, + disabled: { + type: Object as PropType, + default: null + } +}; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts new file mode 100644 index 00000000000..20e9e9b58df --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts @@ -0,0 +1,59 @@ +export const advancedFunctions = [ + { + key: "if", + name: "if()\n{\n\n}", + params: [], + description: "if条件成立,执行括号中内容", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "if else", + name: "if()\n{\n\n}\nelse\n{\n\n}", + params: [], + description: "if条件成立,执行括号中内容;否则执行else中内容", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "for", + name: "for(;;)\n{\n\n}", + params: [], + description: "for循环:示例:for(var i=0;i<5;i++){}", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "return", + name: "return ;", + params: [], + description: "返回值", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "var", + name: "var ", + params: [], + description: "变量定义", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "true", + name: "true ", + params: [], + description: "正确", + type: "Advanced", + keyFront: "", + className: "" + }, { + key: "false", + name: "false ", + params: [], + description: "错误", + type: "Advanced", + keyFront: "", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts new file mode 100644 index 00000000000..369d4788aa3 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts @@ -0,0 +1,482 @@ +export const analyticalFunctions = [ + { + key: "IsNull", + name: "是空值", + params: [{ + key: "obj", + name: "检测对象", + type: "object" + }], + description: "【功能】判断检测对象是否为空值(null)。检测对象为null返回true,否则返回false\n 【参数】\n 【obj】检测对象\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含编号code字段\n 【需求】判断提交单据的编号是否为null\n 【举例】是空值(Order.code)", + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IsNullOrWhiteSpace", + name: "是空串", + params: [{ + key: "obj", + name: "检测对象", + type: "object" + }], + description: '【功能】判断检测对象是否为null值或空串""。检测对象为null或""返回true,否则返回false\n 【参数】\n 【obj】检测对象\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含编号code字段\n 【需求】判断提交单据的编号是否为null或空串""\n 【举例】是空值(Order.code)', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IsNaN", + name: "非数字", + params: [{ + key: "obj", + name: "检测对象", + type: "object" + }], + description: "【功能】判断检测对象是否可以转换成数字(Double)。检测对象不能转为数字返回true,否则返回false\n 【参数】\n 【obj】检测对象\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含单据总额sum字段\n 【需求】判断提交单据的单据总额是否为非数字\n 【举例】非数字(Order.sum)", + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IsNumber", + name: "是数字", + params: [{ + key: "obj", + name: "检测对象", + type: "object" + }], + description: "【功能】判断检测对象是否可以转换成数字(Double)。检测对象能转为数字返回true,否则返回false\n 【参数】\n 【obj】检测对象\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含单据总额sum字段\n 【需求】判断提交单据的单据总额是否是数字\n 【举例】是数字(Order.sum)", + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ExistData", + name: "子表有无数据", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }], + description: '【功能】判断子表中有没有数据。有数据返回true,无数据返回false(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips\n 【需求】判断差旅明细子表是否有数据\n 【举例】子表有无数据("Order.trips")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "CountOfChild", + name: "子表数据数量", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }], + description: '【功能】返回子表数据的数量(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【返回值】数量(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips\n 【需求】获取差旅明细子表的数量\n 【举例】子表数据数量("Order.trips")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "SortChildData", + name: "子表数据排序", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表排序字段", + type: "string" + }, { + key: "order", + name: "排序方式", + type: "string" + }], + description: '【功能】对子表数据进行排序(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(字段类型应为数字类型)\n 【order】排序方式("ESC"表示正序从小到大,"DESC"表示倒序从大到小)\n 【返回值】无\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段\n 【需求】按照出差费用money字段对差旅明细从小到大排序\n 【举例】子表数据排序("Order.trips","money","ESC")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IncludedInList", + name: "是否在列表中", + params: [{ + key: "property", + name: "字段", + type: "object" + }, { + key: "list", + name: "数据列表", + type: "list" + }], + description: '【功能】:判断字段是否在数据列表中存在。字段在列表中存在返回true,不存在返回false。支持判断字符和数字类型\n 【参数】\n 【property】字段\n 【list】数据列表\n 【返回值】true或false\n 【示例】是否在列表中(Order.name,["Zs","Ls"])\n 【示例】是否在列表中(Order.quantity,[100,200])', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "CountByProp", + name: "子表列非空数", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】:统计子表某字段不为null的数据数量(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【返回值】子表字段不为null的数量(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差方式way字段\n 【需求】统计差旅明细子表trips中出差方式way不为空的数据数量\n 【举例】子表列非空数("Order.trips","way")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "SumByProp", + name: "子表字段求和", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】求和子表某字段(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【返回值】子表某字段的和(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段\n 【需求】对差旅明细子表trips的出差费用money字段求和\n 【举例】子表字段求和("Order.trips","money")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "AvgByProp", + name: "子表列平均值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】求子表某字段的平均值(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【返回值】子表某字段的平均值(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段\n 【需求】获取差旅明细子表trips的出差费用money的平均值\n 【举例】子表列平均值("Order.trips","money")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "MaxByProp", + name: "子表列最大值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】求子表某字段的最大值(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【返回值】子表某字段的最大值(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段\n 【需求】获取差旅明细子表trips的出差费用money的最大值\n 【举例】子表列最大值("Order.trips","money")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "MinByProp", + name: "子表列最小值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】求子表某字段的最小值(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【返回值】子表某字段的最小值(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段\n 【需求】获取差旅明细子表trips的出差费用money的最小值\n 【举例】子表列最小值("Order.trips","money")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IsExistRecord", + name: "子表有无等于匹配值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "string" + }], + description: '【功能】判断子表某字段是否存在等于匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差方式way\n 【需求】判断差旅明细子表trips是否存在出差方式way等于\'火车\'的数据\n 【举例】子表有无等于匹配值("Order.trips","way","火车")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "IsContainMatch", + name: "子表有无包含匹配值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "string" + }], + description: '【功能】判断子表某字段是否存在包含匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差方式way\n 【需求】判断差旅明细子表trips是否存在出差方式way包含匹配值\'飞机\'的数据\n 【举例】子表有无包含匹配值("Order.trips","way","飞机")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ListGreaterThan", + name: "子表有无大于匹配值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "double" + }], + description: '【功能】判断子表某字段是否存在大于匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差距离distance\n 【需求】判断差旅明细子表trips是否存在出差距离distance大于1000的数据\n 【举例】子表有无大于匹配值("Order.trips","distance",1000)', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ListLessThan", + name: "子表有无小于匹配值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "double" + }], + description: '【功能】判断子表某字段是否存在小于匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段(数值类型)\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差距离distance\n 【需求】判断差旅明细子表trips是否存在出差距离distance小于10的数据\n 【举例】子表有无小于匹配值("Order.trips","distance",10)', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ListStartWith", + name: "子表有无以匹配值开头", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "string" + }], + description: '【功能】判断子表某字段有无开头是匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含编号code字段\n 【需求】判断差旅明细子表trips是否存在编号code字段以\'0001\'开头的数据\n 【举例】子表有无以匹配值开头("Order.trips","code","0001")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ListEndWith", + name: "子表有无以匹配值结尾", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }, { + key: "match", + name: "匹配值", + type: "string" + }], + description: '【功能】判断子表某字段有无结尾是匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【match】匹配值\n 【返回值】true或false\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含编号code字段\n 【需求】判断差旅明细子表trips是否存在编号code字段以\'0002\'结尾的数据\n 【举例】子表有无以匹配值结尾("Order.trips","code","0002")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetComputeJsonData", + name: "子表字段取JSON串", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "property", + name: "子表字段", + type: "string" + }], + description: '【功能】判断子表某字段有无结尾是匹配值的数据(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【property】子表字段\n 【返回值】子表某字段的JSON格式\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含编号code字段\n 【需求】将差旅明细子表trips编号code字段用一个列表统计数据,并返回序列化后的值\n 【举例】子表字段取JSON串("Order.trips","code")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "MultiplyChildNumber", + name: "子表属性乘积求和", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "prop1", + name: "属性一", + type: "string" + }, { + key: "prop2", + name: "属性二", + type: "string" + }], + description: '【功能】对子表的两个数字类型属性,先做乘积,然后求和(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【prop1】属性一(数值类型)\n 【prop2】属性二(数值类型)\n 【返回值】求和值(数值类型)\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差天数days、出差费用money\n 【需求】获取差旅明细的总费用,即子表出差天数*出差费用的总和\n 【举例】子表属性乘积求和("Order.trips","days","money")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "MinValueOfPeriod", + name: "时间范围内取最小值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "timeProp", + name: "比较时间字段", + type: "string" + }, { + key: "valueProp", + name: "取值字段", + type: "string" + }, { + key: "startTime", + name: "起始时间", + type: "string" + }, { + key: "endTime", + name: "结束时间", + type: "string" + }], + description: '【功能】在指定时间范围内,取子表某字段的最小值(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【timeProp】比较时间字段(字段类型应为时间类型)\n 【valueProp】取值字段(字段类型应为数字类型)\n 【startTime】起始时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【endTime】结束时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【返回值】时间范围内,子表某字段的最小值\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段,出差日期date字段\n 【需求】获取2022-10-01到2022-10-07时间段内,哪一天的出差费用money最小\n 【举例】时间范围内取最小值("Order.trips","date","money","2022-10-01","2022-10-07")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "MaxValueOfPeriod", + name: "时间范围内取最大值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "timeProp", + name: "比较时间字段", + type: "string" + }, { + key: "valueProp", + name: "取值字段", + type: "string" + }, { + key: "startTime", + name: "起始时间", + type: "string" + }, { + key: "endTime", + name: "结束时间", + type: "string" + }], + description: '【功能】在指定时间范围内,取子表某字段的最大值(参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【timeProp】比较时间字段(字段类型应为时间类型)\n 【valueProp】取值字段(字段类型应为数字类型)\n 【startTime】起始时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【endTime】结束时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【返回值】时间范围内,子表某字段的最大值\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段,出差日期date字段\n 【需求】获取2022-10-01到2022-10-07时间段内,哪一天的出差费用money最大\n 【举例】时间范围内取最大值("Order.trips","date","money","2022-10-01","2022-10-07")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "AvgValueOfPeriod", + name: "时间范围内取平均值", + params: [{ + key: "table", + name: "主表.子表", + type: "string" + }, { + key: "timeProp", + name: "比较时间字段", + type: "string" + }, { + key: "valueProp", + name: "取值字段", + type: "string" + }, { + key: "startTime", + name: "起始时间", + type: "string" + }, { + key: "endTime", + name: "结束时间", + type: "string" + }], + description: '【功能】在指定时间范围内,取子表某字段的平均值(所有参数用""包起来)\n 【参数】\n 【table】主表.子表(链式结构)\n 【timeProp】比较时间字段(字段类型应为时间类型)\n 【valueProp】取值字段(字段类型应为数字类型)\n 【startTime】起始时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【endTime】结束时间(支持\'yyyy-MM-dd\' 或 \'yyyy-MM-dd hh:mm:ss\')\n 【返回值】时间范围内,子表某字段的平均值\n 【示例】\n 【场景】提交单据Order,单据包含差旅明细子表trips,子表包含出差费用money字段,出差日期date字段\n 【需求】获取2022-10-01到2022-10-07时间段内,平均的出差费用money是多少\n 【举例】时间范围内取平均值("Order.trips","date","money","2022-10-01","2022-10-07")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetSessionValue", + name: "获取会话变量", + params: [{ + key: "name", + name: "名称", + type: "string" + }], + description: '【功能】获取用户会话变量的值\n 【参数】\n 【name】会话变量名\n 【返回值】对象(object)\n 【示例】\n 【举例】获取会话变量("会话变量一")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetContextParameter", + name: "获取上下文变量", + params: [{ + key: "name", + name: "名称", + type: "string" + }], + description: '【功能】获取上下文变量的值\n 【参数】\n 【name】上下文变量名\n 【返回值】对象(object)\n 【示例】\n 【举例】获取上下文变量("上下文变量一")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "getComputeJsonData", + name: "根据属性名获取JSON串" + }, { + key: "GetInjectedEntity", + name: "根据注入名获取注入对象", + params: [{ + key: "name", + name: "注入名", + type: "string" + }], + description: '【功能】获取运行时注入对象的实际对象(参数用""包起来),不支持获取属性 \n 【参数】\n 【name】注入名\n 【返回值】对象(object)\n 【示例】\n 【举例】根据注入名获取注入对象("注入名")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetChainedPropertyValue", + name: "根据属性名获取属性值", + params: [{ + key: "property", + name: "属性名", + type: "string" + }], + description: '【功能】:获取运行时注入属性的实际值(参数用""包起来)\n 【参数】\n 【property】属性名\n 【返回值】对象(object)\n 【示例】\n 【举例】根据属性名获取属性值("属性名")', + type: "Analytical", + keyFront: "DefaultFunction", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/date-time.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/date-time.ts new file mode 100644 index 00000000000..f5268febdd4 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/date-time.ts @@ -0,0 +1,531 @@ +export const dateTimeFunctions = [ + { + key: "DayDifference", + name: "天数差", + params: [{ + key: "date1", + name: "时间一", + type: "obj" + }, { + key: "date2", + name: "时间二", + type: "obj" + }], + description: '【功能】计算两个时间的天数差,计算时以年月日为准,自动忽略时分秒。时间一若早于时间二,返回正数;若晚于时间二,返回负数\n 【参数】\n 【date1】时间一\n 【date2】时间二\n 【返回值】两个日期的天数差\n 【示例】\n 【示例一】天数差("2024-01-01","2024-01-11")\n 【返回值】10\n 【示例一】天数差("2024-01-11","2024-01-01")\n 【返回值】-10', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "DateTimeAddDays", + name: "增加天数", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }, { + key: "value", + name: "增加天数", + type: "int" + }], + description: '【功能】:在指定日期时间上增加指定天数\n【返回值类型】:日期时间(DateTime)\n【示例】:增加天数("2019-01-30T10:00:00+08:00",2)【返回值】:2019-02-01T10:00+08:00', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "DateTimeAddYears", + name: "增加年数", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }, { + key: "value", + name: "增加年数", + type: "int" + }], + description: '【功能】:在指定日期时间上增加指定年数\n【返回值类型】:日期时间(DateTime)\n【示例】:增加年数("2019-01-30T10:00:00+08:00",2)【返回值】:2021-01-30T10:00+08:00', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "DateTimeAddMonths", + name: "增加月数", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }, { + key: "value", + name: "增加月数", + type: "int" + }], + description: '【功能】:在指定日期时间上增加指定的月数\n【返回值类型】:日期时间(DateTime)\n【示例】:增加月数("2019-01-30T10:00:00+08:00",1)【返回值】:2019-02-28T10:00+08:00', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetFirstDayOfMonth", + name: "日期所在月第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:获取指定日期时间所在月的第一天的日期\n【返回值类型】:日期时间(DateTime)\n【示例】:日期所在月第一天("2019-01-30T10:00:00+08:00")【返回值】:2019-01-01', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetLastDayOfMonth", + name: "日期所在月最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:获取指定日期时间所在月的最后一天的日期\n【返回值类型】:日期时间(DateTime)\n【示例】:日期所在月最后一天("2019-01-30T10:00:00+08:00")【返回值】:2019-01-31', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetDateTimeNow", + name: "当前日期时间", + params: [], + description: "【功能】:获取当前的日期时间\n【返回值类型】:日期时间(DateTime)\n【示例】:当前日期时间()【返回值】:2019-01-30T12:00:00.000+08:00", + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "CompareDate", + name: "比较两个时间", + params: [{ + key: "date1", + name: "日期时间一", + type: "string" + }, { + key: "date2", + name: "日期时间二", + type: "string" + }], + description: '【功能】:比较两个时间值,并返回一个整数\n【返回值类型】:数值(int32)日期1早于日期2,返回-1;日期1等于日期2,返回0;日期1晚于日期2,返回1\n【示例】:比较两个时间("2019-01-30T10:00:00+08:00","2019-02-01T10:00:00+08:00")【返回值】:-1', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FormatDate", + name: "格式化当前日期", + params: [{ + key: "format", + name: "格式", + type: "string" + }], + description: '【功能】:使用指定的格式将当前日期时间值转换为其等效的字符串表示形式\n【返回值类型】:字符串(String)\n【示例】:格式化当前日期("yyyy-MM-dd HH:mm:ss")【返回值】:"2019-01-30 01:00:00"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FormatDefineDate", + name: "格式化指定日期", + params: [{ + key: "format", + name: "格式", + type: "string" + }, { + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:使用指定的格式将指定的日期时间值转换为其等效的字符串表示形式\n【返回值类型】:字符串(String)\n【示例】:格式化指定日期("yyyy-MM-dd HH:mm:ss","2019-01-30 01:00:00")【返回值】:"2019-01-30 01:00:00"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "Today", + name: "今天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的今天,格式为"yyyy-MM-dd"形式,无参数则默认返回当前日期的今天\n【返回值类型】:字符串(String)\n【示例】:今天("2019-01-30T10:00:00+08:00")【返回值】:"2019-01-30"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "Yesterday", + name: "昨天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的昨天,格式为"yyyy-MM-dd"形式,无参数则默认返回当前日期的昨天\n【返回值类型】:字符串(String)\n【示例】:昨天("2019-01-30T10:00:00+08:00")【返回值】:"2019-01-29"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "Tomorrow", + name: "明天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的明天,格式为"yyyy-MM-dd"形式,无参数则默认返回当前日期的明天\n【返回值类型】:字符串(String)\n【示例】:明天("2019-01-30T10:00:00+08:00")【返回值】:"2019-01-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ThisYear", + name: "本年", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本年,格式为"yyyy"形式,无参数则默认返回当前日期的本年\n【返回值类型】:字符串(String)\n【示例】:本年("2019-01-30T10:00:00+08:00")【返回值】:"2019"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastYear", + name: "去年", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的去年,格式为"yyyy"形式,无参数则默认返回当前日期的去年\n【返回值类型】:字符串(String)\n【示例】:去年("2019-01-30T10:00:00+08:00")【返回值】:"2018"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NextYear", + name: "明年", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的明年,格式为"yyyy"形式,无参数则默认返回当前日期的明年\n【返回值类型】:字符串(String)\n【示例】:明年("2019-01-30T01:00:00+08:00")【返回值】:"2020"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ThisMonth", + name: "本月", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本月,格式为"MM"形式,无参数则默认返回当前日期的本月\n【返回值类型】:字符串(String)\n【示例】:本月("2019-01-30T01:00:00+08:00")【返回值】:"1"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastMonth", + name: "上月", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上月,格式为"MM"形式,无参数则默认返回当前日期的上月\n【返回值类型】:字符串(String)\n【示例】:上月("2019-02-30 01:00:00")【返回值】:"1"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NextMonth", + name: "下月", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下月,格式为"MM"形式,无参数则默认返回当前日期的下月\n【返回值类型】:字符串(String)\n【示例】:下月("2019-01-30T01:00:00+08:00")【返回值】:"2"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ThisWeek", + name: "本周", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期在本年的第几周,格式为"ww"形式,无参数则默认返回当前日期在本年的第几周\n【返回值类型】:字符串(String)\n【示例】:本周("2019-01-30T01:00:00+08:00")【返回值】:"5"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastWeek", + name: "上周", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上周,格式为"ww"形式,无参数则默认返回当前日期的上周\n【返回值类型】:字符串(String)\n【示例】:上周("2019-01-30T01:00:00+08:00")【返回值】:"4"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NextWeek", + name: "下周", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下周,格式为"ww"形式,无参数则默认返回当前日期的下周\n【返回值类型】:字符串(String)\n【示例】:下周("2019-01-30T01:00:00+08:00")【返回值】:"6"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "DayOfWeek", + name: "星期几", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期是本周的星期几,格式为"n",无参数则默认返回当前日期是本周的星期几\n【返回值类型】:字符串(String)\n【示例】:星期几("2019-01-30T01:00:00+08:00")【返回值】:"3"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfWeek", + name: "本周第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本周第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本周第一天\n【返回值类型】:字符串(String)\n【示例】:本周第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-28"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfWeek", + name: "本周最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本周最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本周第一天\n【返回值类型】:字符串(String)\n【示例】:本周最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-02-03"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfLastWeek", + name: "上周第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上周第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上周第一天\n【返回值类型】:字符串(String)\n【示例】:上周第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-21"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfLastWeek", + name: "上周最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上周最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上周最后一天\n【返回值类型】:字符串(System.String)\n【示例】:上周最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-27"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfNextWeek", + name: "下周第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下周第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下周第一天\n【返回值类型】:字符串(String)\n【示例】:下周第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-02-04"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfNextWeek", + name: "下周最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下周最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下周最后一天\n【返回值类型】:字符串(String)\n【示例】:下周最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-02-10"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfMonth", + name: "本月第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本月第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本月第一天\n【返回值类型】:字符串(String)\n【示例】:本月第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfMonth", + name: "本月最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本月最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本月最后一天\n【返回值类型】:字符串(String)\n【示例】:本月最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfLastMonth", + name: "上月第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上月第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上月第一天\n【返回值类型】:字符串(String)\n【示例】:上月第一天("2019-01-30T01:00:00+08:00")【返回值】:"2018-12-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfLastMonth", + name: "上月最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上月最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上月最后一天\n【返回值类型】:字符串(String)\n【示例】:上月最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2018-12-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfNextMonth", + name: "下月第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下月第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下月第一天\n【返回值类型】:字符串(String)\n【示例】:下月第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-02-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfNextMonth", + name: "下月最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下月最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下月最后一天\n【返回值类型】:字符串(String)\n【示例】:下月最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-02-28"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfYear", + name: "本年第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本年第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本年第一天\n【返回值类型】:字符串(String)\n【示例】:本年第一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-01-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfYear", + name: "本年最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的本年最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的本年最后一天\n【返回值类型】:字符串(String)\n【示例】:本年最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2019-12-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfLastYear", + name: "上年第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上年第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上年第一天\n【返回值类型】:字符串(String)\n【示例】:上年第一天("2019-01-30T01:00:00+08:00")【返回值】:"2018-01-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfLastYear", + name: "上年最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的上年最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的上年最后一天\n【返回值类型】:字符串(String)\n【示例】:上年最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2018-12-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "FirstDayOfNextYear", + name: "下年第一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下年第一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下年第一天\n【返回值类型】:字符串(String)\n【示例】:下年第一天("2019-01-30T01:00:00+08:00")【返回值】:"2020-01-01"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "LastDayOfNextYear", + name: "下年最后一天", + params: [{ + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定日期的下年最后一天,格式为"yyyy-MM-dd",无参数则默认返回当前日期的下年最后一天\n【返回值类型】:字符串(String)\n【示例】:下年最后一天("2019-01-30T01:00:00+08:00")【返回值】:"2020-12-31"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + }, { + key: "GetDate", + name: "返回指定格式的日期", + params: [{ + key: "format", + name: "格式", + type: "string" + }, { + key: "date", + name: "日期时间", + type: "string" + }], + description: '【功能】:返回指定形式的日期,无参数则默认返回当前日期的指定格式日期\n【返回值类型】:字符串(String)\n DD:今天 LD:昨天 ND:明天 YY:本年 LY:上年 NY:下年 MM:本月 LM:上月 NM:下月 \n WD:星期几 WW:本周 LW:上周 NW:下周 FDW:本周首日 LDW:本周尾日 \n FDLW:上周首日 LDLW:上周尾日 FDNW:下周首日 LDNW:下周尾日 \n FDM:本月首日 LDM:本月尾日 FDLM:上月首日 LDLM:上月尾日 FDNM:下月首日 LDNM:下月尾日 \n FDY:本年首日 LDY:本年尾日 FDLY:上年首日 LDLY:上年尾日 FDNY:下年首日 LDNY:下年尾日 \n 【示例】:返回指定格式的日期("LD","2019-01-30T01:00:00+08:00")【返回值】:"2019-01-29"', + type: "DateTime", + keyFront: "DefaultFunction", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts new file mode 100644 index 00000000000..355e6658a9d --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts @@ -0,0 +1,16 @@ +import { advancedFunctions } from "./advanced"; +import { analyticalFunctions } from "./analytical"; +import { dateTimeFunctions } from "./date-time"; +import { mathFunctions } from "./math-number"; +import { stringFunctions } from "./string"; +import { translateFunctions } from "./translate"; + + +export const commonFunctions = { + advanced: { name: '高级' ,items: advancedFunctions}, + analytical: { name: '数据', items: analyticalFunctions}, + datetime: {name: '时间',items: dateTimeFunctions}, + string: {name: '字符', items: stringFunctions}, + math: {name: '数字', items: mathFunctions}, + translate: {name: '转换', items: translateFunctions} +}; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts new file mode 100644 index 00000000000..457b580407f --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts @@ -0,0 +1,121 @@ +export const mathFunctions = [ + { + key: "NumberThousandSeparator", + name: "数字千位分隔", + params: [{ + key: "property", + name: "数字类型字段", + type: "int32" + }], + description: "【功能】对数字添加千位分割符,以逗号作为千位分隔符\n【参数】\n 【property】字段(链式结构)\n【返回值】字符型\n【示例】\n 【场景】提交单据Order,单据包含总费用totalCost\n 【需求】优化总费用展示,对总费用添加千位分隔符\n 【举例】数字千位分隔(Order.totalCost)\n 【返回值】1,234,567.89", + type: "Math", + keyFront: "DefaultFunction", + className: "" + }, { + key: "abs", + name: "绝对值", + params: [{ + key: "value", + name: "数值", + type: "double" + }], + description: "【功能】:返回一个数值的绝对值\n【返回值类型】:数值(Double)\n【示例】:绝对值(-1.5)【返回值】:1.5", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "Round", + name: "四舍五入" + }, { + key: "round", + name: "四舍五入", + params: [{ + key: "value1", + name: "数值", + type: "double" + }, { + key: "value2", + name: "小数位数", + type: "int32" + }], + description: "【功能】:根据小数位数精度,对数值四舍五入\n【value1】:数值\n【value2】:四舍五入小数位数\n【返回值类型】:数值(Double)\n【示例】:四舍五入(1.52,1)【返回值】:1.5", + type: "Math", + keyFront: "DefaultFunction", + className: "" + }, { + key: "random", + name: "随机数", + params: [], + description: "【功能】:随机生成大于等于 0.0 且小于 1.0 的伪随机值\n【返回值类型】:数值(Double)\n【示例】:随机数()【返回值】:0.624508349393", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "sin", + name: "正弦", + params: [{ + key: "value", + name: "数值", + type: "double" + }], + description: "【功能】:返回一个数字的正弦值\n【返回值类型】:数值(Double)一个以弧度表示的角\n【示例】:正弦(1)【返回值】:0.84187098", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "cos", + name: "余弦", + params: [{ + key: "value", + name: "数值", + type: "double" + }], + description: "【功能】:返回一个数字的余弦值\n【返回值类型】:数值(Double)一个以弧度表示的角\n【示例】:余弦(3)【返回值】:-0.9899924", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "ceil", + name: "向上舍入", + params: [{ + key: "value", + name: "数值", + type: "double" + }], + description: "【功能】:返回大于或等于函数参数,并且与之最接近的整数\n【返回值类型】:数值(Int32)\n【示例】:向上舍入(3.2)【返回值】:4", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "floor", + name: "向下舍入", + params: [{ + key: "value", + name: "数值", + type: "double" + }], + description: "【功能】:返回小于或等于函数参数,并且与之最接近的整数\n【返回值类型】:数值(Int32)\n【示例】:向下舍入(3.2)【返回值】:3", + type: "Math", + keyFront: "Math", + className: "" + }, { + key: "BankerRound", + name: "银行家舍入" + }, { + key: "bankerRound", + name: "银行家舍入", + params: [{ + key: "value1", + name: "数值", + type: "double" + }, { + key: "value2", + name: "小数位数", + type: "int32" + }], + description: "【功能】:使用银行家舍入标准,把指定数字舍入为最接近的数字\n【value1】:舍入数值\n【value2】:舍入小数位数\n【返回值类型】:数值(Double)\n【示例】:银行家舍入(36.124,2)【返回值】:36.12", + type: "Math", + keyFront: "DefaultFunction", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts new file mode 100644 index 00000000000..6bee70659b4 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts @@ -0,0 +1,300 @@ +export const stringFunctions = [ + { + key: "StringSubstring", + name: "取子字符串" + }, { + key: "SubString", + name: "取子字符串", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "start", + name: "起始位置", + type: "int" + }, { + key: "length", + name: "长度", + type: "int" + }], + description: '【功能】:从字符串中指定位置开始,截取指定长度的字符串并返回\n【返回值类型】:字符串(String)\n【示例】:取子字符串("ABCDEFG",2,3)【返回值】:"CDE"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringLength", + name: "取字符串长度" + }, { + key: "Length", + name: "取字符串长度", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:获取字符串的长度\n【返回值类型】:数值(Int32)\n【示例】:取字符串长度("ABCDEF")【返回值】:6', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "Contains", + name: "是否包含", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串中是否包含目标字符串\n【返回值类型】:布尔(Boolean)\n【示例】:是否包含(salesorder.code,"表达式")【返回值】:false', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NotContains", + name: "是否不包含", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串中是否不包含目标字符串\n【返回值类型】:布尔(Boolean)\n【示例】:是否不包含(salesorder.code,"表达式")【返回值】:true', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StartsWith", + name: "开头是", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串是否以目标字符串开头\n【返回值类型】:布尔(Boolean)\n【示例】:开头是(salesorder.code,"表达式")【返回值】:false', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NotStartsWith", + name: "开头不是", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串是否不以目标字符串开头\n【返回值类型】:布尔(Boolean)\n【示例】:开头不是(salesorder.code,"表达式")【返回值】:true', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "EndsWith", + name: "结尾是", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串是否以目标字符串结尾\n【返回值类型】:布尔(Boolean)\n【示例】:结尾是(salesorder.code,"表达式")【返回值】:false', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "NotEndsWith", + name: "结尾不是", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:判断字符串是否不以目标字符串结尾\n【返回值类型】:布尔(Boolean)\n【示例】:结尾不是(salesorder.code,"表达式")【返回值】:false', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringReplace", + name: "字符串替换" + }, { + key: "Replace", + name: "字符串替换", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "oldVal", + name: "被替换值", + type: "str" + }, { + key: "newVal", + name: "替换值", + type: "str" + }], + description: '【功能】:将字符串中的"被替换值"替换为"替换值"\n【返回值类型】:字符串(String)\n【示例】:字符串替换("123412","12","00")【返回值】:"003400"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringToUpper", + name: "转大写" + }, { + key: "ToUpper", + name: "转大写", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:将字符串转换为大写\n【返回值类型】:字符串(String)\n【示例】:转大写("abc")【返回值】:"ABC"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringToLower", + name: "转小写" + }, { + key: "ToLower", + name: "转小写", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:将字符串转换为小写\n【返回值类型】:字符串(String)\n【示例】:转小写("ABC")【返回值】:"abc"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringIndexOf", + name: "首个匹配字符索引" + }, { + key: "IndexOf", + name: "首个匹配字符索引", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:在字符串中检索目标字符串,找到首个匹配的字符串并返回索引位置(从0开始)。如果未找到则返回-1,如果目标字符串为空则返回0,如果原字符串为null则返回-1\n【返回值类型】:数值(Int32)\n【示例】:首个匹配字符索引("12001234012","01")【返回值】:3\n【示例】:首个匹配字符索引("12002323","34")【返回值】:-1\n【示例】:首个匹配字符索引("120011","")【返回值】:0', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringLastIndexOf", + name: "最后匹配字符索引" + }, { + key: "LastIndexOf", + name: "最后匹配字符索引", + params: [{ + key: "data", + name: "字符串", + type: "str" + }, { + key: "target", + name: "目标字符串", + type: "str" + }], + description: '【功能】:在字符串中检索目标字符串,找到最后一个匹配的字符串后返回索引位置(从0开始)。如果未找到则返回-1,如果目标字符串为空串则返回原字符串长度,如果原字符串为null则返回-1\n【返回值类型】:数值(Int32)\n【示例】:最后匹配字符索引("12001234012","01")【返回值】:8\n【示例】:最后匹配字符索引("12002323","34")【返回值】:-1\n【示例】:最后匹配字符索引("120011","")【返回值】:6', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringTrimStart", + name: "删除头部空格" + }, { + key: "TrimStart", + name: "删除头部空格", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:删除字符串的头部空格并返回\n【返回值类型】:字符串(String)\n【示例】:删除头部空格(" ABC")【返回值】:"ABC"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringTrimEnd", + name: "删除尾部空格" + }, { + key: "TrimEnd", + name: "删除尾部空格", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:删除字符串的尾部空格并返回\n【返回值类型】:字符串(String)\n【示例】:删除尾部空格("ABC ")【返回值】:"ABC"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringTrim", + name: "删除头尾部空格" + }, { + key: "Trim", + name: "删除头尾部空格", + params: [{ + key: "data", + name: "字符串", + type: "str" + }], + description: '【功能】:删除字符串的头尾部空格并返回\n【返回值类型】:字符串(String)\n【示例】:删除头尾部空格(" ABC ")【返回值】:"ABC"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "CreateGuid", + name: "唯一标识符", + params: [], + description: '【功能】:获取唯一标识符Guid\n【返回值类型】:字符串(String)\n【示例】:唯一标识符()【返回值】:"7722A793-14DF-49CD-B7E7-DF4987YYD2"', + type: "String", + keyFront: "DefaultFunction", + className: "" + }, { + key: "StringAdd", + name: "字符串相加" + }, { + key: "Add", + name: "字符串相加", + params: [{ + key: "str1", + name: "第一个字符串", + type: "str" + }, { + key: "str2", + name: "第二个字符串", + type: "str" + }], + description: '【功能】:将若干字符串拼接成一个新字符串,最多支持10个字符串拼接,最少2个;编辑器中默认插入两个,多个字符串可手动添加\n【返回值类型】:字符串(String)\n【示例】:字符串相加("Hello","World")【返回值】:"HelloWord"', + type: "String", + keyFront: "DefaultFunction", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts new file mode 100644 index 00000000000..808a90aee83 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts @@ -0,0 +1,146 @@ + +export const translateFunctions = [ + { + key: "ToStringX", + name: "转字符串", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换为字符串\n【返回值类型】:字符串(String)\n【示例】:转字符串(123)【返回值】:"123"', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToDateTime", + name: "转日期时间", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成日期时间\n【返回值类型】:日期时间(OffsetDateTime)\n【示例】:转日期时间("2019-01-30T10:00:00+08:00")【返回值】: 2019-01-30T10:00+08:00', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToBoolean", + name: "转布尔值", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成等效的布尔值\n【返回值类型】:布尔值(Boolean)\n【示例】:转布尔值("True")【返回值】:true', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToDecimal", + name: "转数值" + }, { + key: "ToBigDecimal", + name: "转数值", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成十进制数值\n【返回值类型】:十进制数值(BigDecimal)\n【示例】:转数值("40.23")【返回值】:40.23', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToCustomBigDecimal", + name: "转自定义精度数值", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }, { + key: "number", + name: "小数位数", + type: "int" + }], + description: '【功能】:将转换值转换成指定精度的十进制数值\n【返回值类型】:十进制数值(BigDecimal)\n【示例】:转自定义精度数值("40.2,2")【返回值】:40.20', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToDouble", + name: "转双精度浮点数", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成双精度浮点数\n【返回值类型】:双精度浮点数(Double)\n【示例】:转双精度浮点数("40.23")【返回值】:40.23', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToSingle", + name: "转单精度浮点数" + }, { + key: "ToFloat", + name: "转单精度浮点数", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成单精度浮点数\n【返回值类型】:单精度浮点数(Float)\n【示例】:转单精度浮点数("40.23")【返回值】:40.23', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToByte", + name: "转8位无符号整数", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成8位无符号整数\n【返回值类型】:8位无符号整数(Byte)\n【示例】:转8位无符号整数("10")【返回值】:10', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToInt16", + name: "转16位有符号整数", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成16位有符号整数\n【返回值类型】:16位有符号整数(Int16)\n【示例】:转16位有符号整数("10")【返回值】:10', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToInt32", + name: "转32位有符号整数", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成32位有符号整数\n【返回值类型】:32位有符号整数(Int32)\n【示例】:转32位有符号整数("10")【返回值】:10', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + }, { + key: "ToChineseMoney", + name: "转中文大写金额", + params: [{ + key: "obj", + name: "转换值", + type: "object" + }], + description: '【功能】:将转换值转换成中文大写金额\n【返回值类型】:字符串(String)\n【示例】:转中文大写金额(40.23)【返回值】:"肆拾元零贰角叁分"', + type: "Translate", + keyFront: "DefaultFunction", + className: "" + } +]; diff --git a/packages/ui-vue/components/expression-editor/src/composition/types.ts b/packages/ui-vue/components/expression-editor/src/composition/types.ts new file mode 100644 index 00000000000..6a1c5ba728b --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/types.ts @@ -0,0 +1,4 @@ +export interface DisabledFunction { + types?: string[]; + functions?: string[]; +} diff --git a/packages/ui-vue/components/expression-editor/src/designer/expression-editor.design.component.tsx b/packages/ui-vue/components/expression-editor/src/designer/expression-editor.design.component.tsx deleted file mode 100644 index 61b378e5bba..00000000000 --- a/packages/ui-vue/components/expression-editor/src/designer/expression-editor.design.component.tsx +++ /dev/null @@ -1,32 +0,0 @@ - -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * defination - */ -import { defineComponent, SetupContext } from 'vue'; -import { expressionEditorProps, ExpressionEditorProps } from '../expression-editor.props'; - -export default defineComponent({ - name: 'FExpressionEditorDesign', - props: expressionEditorProps, - emits: [] as (string[] & ThisType) | undefined, - setup(props: ExpressionEditorProps, context: SetupContext) { - return () => { - return ( - <>expression editor design - ); - }; - } -}); diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 190890fc246..33e3d75ef37 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -18,26 +18,28 @@ import { defineComponent, onMounted, ref, SetupContext, watch } from 'vue'; import { ExpressionEditorProps, expressionEditorProps } from './expression-editor.props'; import { FLayout, FLayoutPane } from "../../../components/layout"; +import ExpressionCode from './components/expression-code.component'; +import FExpressionEditor from './components/functions/common-functions.component'; + export default defineComponent({ name: 'FExpressionEditor', props: expressionEditorProps, emits: [] as (string[] & ThisType) | undefined, setup(props: ExpressionEditorProps, context: SetupContext) { const elementRef = ref(); + onMounted(() => { }); return () => { return ( -
+
- + -
- -
+
diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts index bbb67265626..ba04c8a80f4 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts @@ -19,12 +19,11 @@ import { createPropsResolver } from '../../dynamic-resolver'; import { schemaMapper } from './schema/schema-mapper'; import { schemaResolver } from './schema/schema-resolver'; import expressionEditorSchema from './schema/expression-editor.schema.json'; -import propertyConfig from './property-config/expression-editor.property-config.json'; export const expressionEditorProps = { - + } as Record; export type ExpressionEditorProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(expressionEditorProps, expressionEditorSchema, schemaMapper, schemaResolver, propertyConfig); +export const propsResolver = createPropsResolver(expressionEditorProps, expressionEditorSchema, schemaMapper, schemaResolver); diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx new file mode 100644 index 00000000000..8477344e4e8 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx @@ -0,0 +1,65 @@ +import { defineComponent } from "vue"; +import FButtonEdit from '../../button-edit/src/button-edit.component'; +import { expressionTextboxProps } from "./expression-textbox.props"; + +import FExpressionEditor from './expression-editor.component'; + + +export default defineComponent({ + name: 'f-expression-textbox', + props: expressionTextboxProps, + setup(props, context) { + const buttonIcon = ''; + + + const modalOptions = { + title: '表达式编辑器', + width: 800, + height: 600, + fitContent: false, + minWidth: 300, + minHeight: 200, + showMaxButton: true, + resizeable: true, + draggable: true, + buttons: [ + { + name: 'cancel', + text: '取消', + class: 'btn btn-secondary', + handle: ($event: MouseEvent) => { + return true; + } + }, + { + name: 'accept', + text: '确定', + class: 'btn btn-primary', + handle: async ($event: MouseEvent) => { + return true; + } + } + ] + }; + + function onBeforeOpen () {} + + + return () => { + return +
+ +
+
; + } + } +}); diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts new file mode 100644 index 00000000000..bcee56be586 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts @@ -0,0 +1,27 @@ +export const expressionTextboxProps = { + disabled: { + type: Boolean, + default: false + }, + readonly: { + type: Boolean, + default: false + }, + enableClear: { + type: Boolean, + default: false + }, + modelValue: { + type: String, + default: '' + }, + displayText: { + type: String, + default: '' + }, + repositoryToken: { + type: Object, + default: null + }, + editorParams: {} +} diff --git a/packages/ui-vue/components/expression-editor/src/property-config/expression-editor.property-config.json b/packages/ui-vue/components/expression-editor/src/property-config/expression-editor.property-config.json deleted file mode 100644 index 8db562d766d..00000000000 --- a/packages/ui-vue/components/expression-editor/src/property-config/expression-editor.property-config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "title": "expression-editor", - "description": "A Farris Component", - "type": "object", - "categories": { - "basic": { - "description": "Basic Infomation", - "title": "基本信息", - "properties": { - "id": { - "description": "组件标识", - "title": "标识", - "type": "string", - "readonly": true - }, - "type": { - "description": "类型", - "title": "类型", - "type": "string", - "readonly": true - } - } - } - } -} \ No newline at end of file diff --git a/packages/ui-vue/components/expression-editor/style.scss b/packages/ui-vue/components/expression-editor/style.scss new file mode 100644 index 00000000000..9343f86d8e1 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/style.scss @@ -0,0 +1,54 @@ +.expression-editor { + border: 1px solid #cccccc; + + .functions-list { + + .functions-type { + cursor: pointer; + overflow: hidden; + transition: max-height 0.2s ease-in-out; + + &.open { + max-height: 1000px; + } + + &.closed { + max-height: 28px; + } + + + .functions-type-name { + height: 28px; + line-height: 28px; + font-weight: bold; + } + + li { + height: 28px; + line-height: 28px; + list-style: none; + } + + .functions-item { + &.selected { + background: #e4e4e4; + border-radius: 6px; + } + + &:hover:not(.selected) { + background: #f4f4f4; + border-radius: 6px; + } + } + } + } + + .function-remark { + resize: none; + outline: none; + background: #f4f4f4; + border: 1px solid #cbcbcb; + border-left: 0; + border-bottom: 0; + } +} diff --git a/packages/ui-vue/demos/expression-editor/basic.vue b/packages/ui-vue/demos/expression-editor/basic.vue index 95004be7cf4..6924dc262ae 100644 --- a/packages/ui-vue/demos/expression-editor/basic.vue +++ b/packages/ui-vue/demos/expression-editor/basic.vue @@ -1,3 +1,7 @@ diff --git a/packages/ui-vue/package.json b/packages/ui-vue/package.json index 0b5e9a78c9d..58836d0520b 100644 --- a/packages/ui-vue/package.json +++ b/packages/ui-vue/package.json @@ -35,28 +35,29 @@ }, "dependencies": { "@docsearch/js": "3.6.0", + "@monaco-editor/loader": "^1.4.0", "@types/lodash-es": "^4.17.4", "@vue/shared": "^3.2.0", "@vueuse/core": "^9.2.0", "async-validator": "^4.2.0", "bignumber.js": "^9.1.2", + "date-fns": "^3.6.0", "echarts": "^5.5.0", "jsonp": "^0.2.1", "lodash": "^4.17.21", "lodash-es": "^4.17.20", "rxjs": "^7.4.0", "vite-plugin-dts": "^2.1.0", - "vue": "^3.2.37", - "date-fns":"^3.6.0" + "vue": "^3.2.37" }, "devDependencies": { - "@farris/cli": "workspace:*", "@babel/parser": "^7.19.0", "@babel/preset-env": "^7.19.0", "@babel/preset-typescript": "^7.18.0", "@babel/traverse": "^7.19.0", "@commitlint/cli": "^17.1.0", "@commitlint/config-conventional": "^17.1.0", + "@farris/cli": "workspace:*", "@farris/designer-dragula": "0.0.5", "@testing-library/vue": "^7.0.0", "@types/jest": "^26.0.24", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c0bd1486c2..29902570459 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -293,7 +293,7 @@ importers: version: 5.1.0(vue@3.5.12(typescript@5.6.3)) vitepress: specifier: ^1.0.0-alpha.8 - version: 1.0.0-alpha.10(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(terser@5.36.0)(typescript@5.6.3) + version: 1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3) vitepress-theme-demoblock: specifier: 1.4.2 version: 1.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(typescript@5.6.3) @@ -408,7 +408,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -450,7 +450,7 @@ importers: version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 @@ -638,7 +638,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) ora: specifier: ^6.1.2 version: 6.3.1 @@ -668,13 +668,13 @@ importers: version: 3.9.1(@types/node@20.5.1)(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.21.5 - version: 0.21.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) + version: 0.21.5(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) vite-svg-loader: specifier: ^5.1.0 version: 5.1.0(vue@3.5.12(typescript@5.6.3)) vitepress: specifier: ^1.0.0-alpha.8 - version: 1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3) + version: 1.0.0-alpha.10(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(terser@5.36.0)(typescript@5.6.3) vitepress-theme-demoblock: specifier: 1.4.2 version: 1.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(typescript@5.6.3) @@ -874,7 +874,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) ora: specifier: ^6.1.2 version: 6.3.1 @@ -898,7 +898,7 @@ importers: version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 @@ -1064,7 +1064,7 @@ importers: version: 2.3.0(@types/node@18.19.57)(rollup@4.24.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 @@ -1150,9 +1150,6 @@ importers: vue: specifier: ^3.2.37 version: 3.5.12(typescript@4.9.5) - vue-router: - specifier: '4' - version: 4.4.5(vue@3.5.12(typescript@4.9.5)) devDependencies: '@babel/parser': specifier: ^7.19.0 @@ -1168,7 +1165,7 @@ importers: version: 7.25.7 '@commitlint/cli': specifier: ^19.3.0 - version: 19.5.0(@types/node@18.19.57)(typescript@4.9.5) + version: 19.5.0(@types/node@20.5.1)(typescript@4.9.5) '@commitlint/config-conventional': specifier: ^19.2.0 version: 19.5.0 @@ -1192,16 +1189,16 @@ importers: version: 4.0.9 '@typescript-eslint/eslint-plugin': specifier: ^7.15.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@4.9.5))(eslint@8.57.1)(typescript@4.9.5) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.19.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.19.0(jiti@1.21.6))(typescript@4.9.5) '@typescript-eslint/parser': specifier: ^7.15.0 - version: 7.18.0(eslint@8.57.1)(typescript@4.9.5) + version: 7.18.0(eslint@9.19.0(jiti@1.21.6))(typescript@4.9.5) '@vitejs/plugin-vue': specifier: ^4.2.3 - version: 4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) + version: 4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) '@vitejs/plugin-vue-jsx': specifier: ^3.0.1 - version: 3.1.0(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) + version: 3.1.0(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) '@vue/babel-plugin-jsx': specifier: ^1.1.1 version: 1.2.5(@babel/core@7.25.8) @@ -1237,7 +1234,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@4.9.5)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) ora: specifier: ^6.1.2 version: 6.3.1 @@ -1255,19 +1252,19 @@ importers: version: 4.9.5 vite: specifier: ^4.4.1 - version: 4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0) + version: 4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) vite-plugin-dts: specifier: ^2.1.0 - version: 2.3.0(@types/node@18.19.57)(rollup@4.24.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) + version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 vitepress: specifier: 1.0.0-alpha.8 - version: 1.0.0-alpha.8(@algolia/client-search@4.24.0)(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@4.9.5) + version: 1.0.0-alpha.8(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@4.9.5) vitepress-theme-demoblock: specifier: 1.4.2 version: 1.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(typescript@4.9.5) @@ -1372,6 +1369,21 @@ importers: '@farris/mobile-ui-vue': specifier: latest version: 0.0.1-beta.3(typescript@4.9.5) + '@rollup/plugin-babel': + specifier: ^6.0.4 + version: 6.0.4(@babel/core@7.25.8)(@types/babel__core@7.20.5)(rollup@4.24.0) + '@rollup/plugin-commonjs': + specifier: ^28.0.1 + version: 28.0.1(rollup@4.24.0) + '@rollup/plugin-json': + specifier: ^6.1.0 + version: 6.1.0(rollup@4.24.0) + '@rollup/plugin-node-resolve': + specifier: ^15.2.3 + version: 15.3.0(rollup@4.24.0) + '@rollup/plugin-terser': + specifier: ^0.4.4 + version: 0.4.4(rollup@4.24.0) '@testing-library/vue': specifier: ^7.0.0 version: 7.0.0(@vue/compiler-sfc@3.5.12)(vue@3.5.12(typescript@4.9.5)) @@ -1428,7 +1440,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -1438,6 +1450,15 @@ importers: patch-vue-directive-ssr: specifier: ^0.0.1 version: 0.0.1 + rollup-plugin-typescript2: + specifier: ^0.36.0 + version: 0.36.0(rollup@4.24.0)(typescript@4.9.5) + rollup-plugin-visualizer: + specifier: ^5.12.0 + version: 5.12.0(rollup@4.24.0) + rollup-plugin-vue: + specifier: ^6.0.0 + version: 6.0.0(@vue/compiler-sfc@3.5.12) sass: specifier: ^1.32.2 version: 1.80.3 @@ -1458,7 +1479,7 @@ importers: version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 @@ -1477,6 +1498,9 @@ importers: packages/mobile-ui-vue: dependencies: + bignumber.js: + specifier: ^9.1.2 + version: 9.1.2 vue: specifier: ^3.2.37 version: 3.5.12(typescript@4.9.5) @@ -1531,7 +1555,7 @@ importers: version: 2.2.2 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) patch-vue-directive-ssr: specifier: ^0.0.1 version: 0.0.1 @@ -1679,7 +1703,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) ora: specifier: ^6.1.2 version: 6.3.1 @@ -1706,7 +1730,7 @@ importers: version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) vite-plugin-md: specifier: ^0.20.0 - version: 0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) + version: 0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vite-svg-loader: specifier: ^4.0.0 version: 4.0.0 @@ -1810,6 +1834,9 @@ importers: '@docsearch/js': specifier: 3.6.0 version: 3.6.0(@algolia/client-search@4.24.0)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(search-insights@2.17.2) + '@monaco-editor/loader': + specifier: ^1.4.0 + version: 1.4.0(monaco-editor@0.52.2) '@types/lodash-es': specifier: ^4.17.4 version: 4.17.12 @@ -1845,7 +1872,7 @@ importers: version: 7.8.1 vite-plugin-dts: specifier: ^2.1.0 - version: 2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) + version: 2.3.0(@types/node@18.19.57)(rollup@4.24.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) vue: specifier: ^3.2.37 version: 3.5.12(typescript@5.6.3) @@ -1894,10 +1921,10 @@ importers: version: 7.18.0(eslint@9.19.0(jiti@1.21.6))(typescript@5.6.3) '@vitejs/plugin-vue': specifier: ^4.2.3 - version: 4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) + version: 4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) '@vitejs/plugin-vue-jsx': specifier: ^3.0.1 - version: 3.1.0(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) + version: 3.1.0(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) '@vue/babel-plugin-jsx': specifier: ^1.1.1 version: 1.2.5(@babel/core@7.25.8) @@ -1933,7 +1960,7 @@ importers: version: 9.3.7 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + version: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) ora: specifier: ^6.1.2 version: 6.3.1 @@ -1951,25 +1978,25 @@ importers: version: 5.6.3 vite: specifier: ^5.3.3 - version: 5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + version: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) vite-plugin-banner: specifier: ^0.8.0 version: 0.8.0 vite-plugin-md: specifier: ^0.21.5 - version: 0.21.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) + version: 0.21.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) vite-svg-loader: specifier: ^5.1.0 version: 5.1.0(vue@3.5.12(typescript@5.6.3)) vitepress: specifier: ^1.0.0-alpha.8 - version: 1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3) + version: 1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3) vitepress-theme-demoblock: specifier: 1.4.2 version: 1.4.2(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(typescript@5.6.3) vitest: specifier: ^1.4.0 - version: 1.6.0(@types/node@20.5.1)(happy-dom@8.9.0)(jsdom@20.0.3)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + version: 1.6.0(@types/node@18.19.57)(happy-dom@8.9.0)(jsdom@20.0.3)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) vue-tsc: specifier: ^2.0.0 version: 2.1.6(typescript@5.6.3) @@ -12375,19 +12402,6 @@ snapshots: - '@swc/core' - '@swc/wasm' - '@commitlint/cli@19.5.0(@types/node@18.19.57)(typescript@4.9.5)': - dependencies: - '@commitlint/format': 19.5.0 - '@commitlint/lint': 19.5.0 - '@commitlint/load': 19.5.0(@types/node@18.19.57)(typescript@4.9.5) - '@commitlint/read': 19.5.0 - '@commitlint/types': 19.5.0 - tinyexec: 0.3.1 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - typescript - '@commitlint/cli@19.5.0(@types/node@18.19.57)(typescript@5.6.3)': dependencies: '@commitlint/format': 19.5.0 @@ -12509,22 +12523,6 @@ snapshots: - '@swc/core' - '@swc/wasm' - '@commitlint/load@19.5.0(@types/node@18.19.57)(typescript@4.9.5)': - dependencies: - '@commitlint/config-validator': 19.5.0 - '@commitlint/execute-rule': 19.5.0 - '@commitlint/resolve-extends': 19.5.0 - '@commitlint/types': 19.5.0 - chalk: 5.3.0 - cosmiconfig: 9.0.0(typescript@4.9.5) - cosmiconfig-typescript-loader: 5.1.0(@types/node@18.19.57)(cosmiconfig@9.0.0(typescript@4.9.5))(typescript@4.9.5) - lodash.isplainobject: 4.0.6 - lodash.merge: 4.6.2 - lodash.uniq: 4.5.0 - transitivePeerDependencies: - - '@types/node' - - typescript - '@commitlint/load@19.5.0(@types/node@18.19.57)(typescript@5.6.3)': dependencies: '@commitlint/config-validator': 19.5.0 @@ -12549,7 +12547,7 @@ snapshots: '@commitlint/types': 19.5.0 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@4.9.5) - cosmiconfig-typescript-loader: 5.1.0(@types/node@20.5.1)(cosmiconfig@9.0.0(typescript@4.9.5))(typescript@4.9.5) + cosmiconfig-typescript-loader: 5.1.0(@types/node@20.5.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@4.9.5) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -13102,42 +13100,6 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.57 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - -<<<<<<< HEAD '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5))': dependencies: '@jest/console': 29.7.0 @@ -13187,7 +13149,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) + jest-config: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -13208,8 +13170,6 @@ snapshots: - supports-color - ts-node -======= ->>>>>>> main '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 @@ -14400,6 +14360,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-vue-jsx@3.1.0(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': + dependencies: + '@babel/core': 7.25.8 + '@babel/plugin-transform-typescript': 7.25.7(@babel/core@7.25.8) + '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.25.8) + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + vue: 3.5.12(typescript@5.6.3) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-vue-jsx@3.1.0(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': dependencies: '@babel/core': 7.25.8 @@ -14454,6 +14424,11 @@ snapshots: vite: 4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) vue: 3.5.12(typescript@4.9.5) + '@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': + dependencies: + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + vue: 3.5.12(typescript@5.6.3) + '@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': dependencies: vite: 5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) @@ -14847,64 +14822,14 @@ snapshots: - '@vue/composition-api' - vue - '@yankeeinlondon/builder-api@1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))': - dependencies: - '@types/markdown-it': 12.2.3 - '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - fp-ts: 2.16.9 - inferred-types: 0.37.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - markdown-it: 13.0.2 - vite-plugin-md: 0.22.5(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) - transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitejs/plugin-vue' - - '@vitest/browser' - - '@vitest/ui' - - encoding - - happy-dom - - jsdom - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite - - '@yankeeinlondon/builder-api@1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))': - dependencies: - '@types/markdown-it': 12.2.3 - '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - fp-ts: 2.16.9 - inferred-types: 0.37.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - markdown-it: 13.0.2 - vite-plugin-md: 0.22.5(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) - transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitejs/plugin-vue' - - '@vitest/browser' - - '@vitest/ui' - - encoding - - happy-dom - - jsdom - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite - - '@yankeeinlondon/builder-api@1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))': + '@yankeeinlondon/builder-api@1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))': dependencies: '@types/markdown-it': 12.2.3 '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) fp-ts: 2.16.9 inferred-types: 0.37.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) markdown-it: 13.0.2 - vite-plugin-md: 0.22.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) + vite-plugin-md: 0.22.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) transitivePeerDependencies: - '@edge-runtime/vm' - '@vitejs/plugin-vue' @@ -15024,20 +14949,16 @@ snapshots: acorn-globals@7.0.1: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 acorn-walk: 8.3.4 - acorn-jsx@5.3.2(acorn@8.13.0): - dependencies: - acorn: 8.13.0 - acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 acorn-walk@8.3.4: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 acorn@8.13.0: {} @@ -15693,7 +15614,7 @@ snapshots: dependencies: bumpp: 8.2.1 callsites: 4.2.0 - inferred-types: 0.37.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) + inferred-types: 0.37.6(happy-dom@14.12.3)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) vitest: 0.25.8(happy-dom@14.12.3)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) transitivePeerDependencies: - '@edge-runtime/vm' @@ -16454,13 +16375,6 @@ snapshots: ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.6.3) typescript: 5.6.3 - cosmiconfig-typescript-loader@5.1.0(@types/node@18.19.57)(cosmiconfig@9.0.0(typescript@4.9.5))(typescript@4.9.5): - dependencies: - '@types/node': 18.19.57 - cosmiconfig: 9.0.0(typescript@4.9.5) - jiti: 1.21.6 - typescript: 4.9.5 - cosmiconfig-typescript-loader@5.1.0(@types/node@18.19.57)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): dependencies: '@types/node': 18.19.57 @@ -16468,10 +16382,10 @@ snapshots: jiti: 1.21.6 typescript: 5.6.3 - cosmiconfig-typescript-loader@5.1.0(@types/node@20.5.1)(cosmiconfig@9.0.0(typescript@4.9.5))(typescript@4.9.5): + cosmiconfig-typescript-loader@5.1.0(@types/node@20.5.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@4.9.5): dependencies: '@types/node': 20.5.1 - cosmiconfig: 9.0.0(typescript@4.9.5) + cosmiconfig: 9.0.0(typescript@5.6.3) jiti: 1.21.6 typescript: 4.9.5 @@ -16554,13 +16468,28 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): + create-jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + create-jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -17534,8 +17463,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.13.0 - acorn-jsx: 5.3.2(acorn@8.13.0) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -19009,7 +18938,7 @@ snapshots: jest-cli@29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 @@ -19026,16 +18955,15 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): + jest-cli@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + create-jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) exit: 0.1.2 import-local: 3.2.0 -<<<<<<< HEAD jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) jest-util: 29.7.0 jest-validate: 29.7.0 @@ -19056,9 +18984,6 @@ snapshots: exit: 0.1.2 import-local: 3.2.0 jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) -======= - jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) ->>>>>>> main jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -19125,12 +19050,11 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 18.19.57 - ts-node: 10.9.2(@types/node@18.19.57)(typescript@5.6.3) + ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.6.3) transitivePeerDependencies: - babel-plugin-macros - supports-color -<<<<<<< HEAD jest-config@29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): dependencies: '@babel/core': 7.25.8 @@ -19162,7 +19086,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)): + jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): dependencies: '@babel/core': 7.25.8 '@jest/test-sequencer': 29.7.0 @@ -19187,16 +19111,13 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 18.19.57 - ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.6.3) + '@types/node': 20.5.1 + ts-node: 10.9.2(@types/node@20.5.1)(typescript@4.9.5) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): -======= - jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): ->>>>>>> main + jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)): dependencies: '@babel/core': 7.25.8 '@jest/test-sequencer': 29.7.0 @@ -19222,7 +19143,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.5.1 - ts-node: 10.9.2(@types/node@18.19.57)(typescript@5.6.3) + ts-node: 10.9.2(@types/node@20.5.1)(typescript@5.6.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -19480,7 +19401,7 @@ snapshots: jest@29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) '@jest/types': 29.6.3 import-local: 3.2.0 jest-cli: 29.7.0(@types/node@18.19.57)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) @@ -19490,12 +19411,11 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)): + jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) '@jest/types': 29.6.3 import-local: 3.2.0 -<<<<<<< HEAD jest-cli: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5)) transitivePeerDependencies: - '@types/node' @@ -19509,9 +19429,6 @@ snapshots: '@jest/types': 29.6.3 import-local: 3.2.0 jest-cli: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3)) -======= - jest-cli: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@types/node@18.19.57)(typescript@5.6.3)) ->>>>>>> main transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -20200,7 +20117,7 @@ snapshots: mlly@1.7.2: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 pathe: 1.1.2 pkg-types: 1.2.1 ufo: 1.5.4 @@ -21909,7 +21826,7 @@ snapshots: strip-literal@1.3.0: dependencies: - acorn: 8.13.0 + acorn: 8.14.0 strip-literal@2.1.0: dependencies: @@ -22082,7 +21999,7 @@ snapshots: terser@5.36.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.13.0 + acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -22277,6 +22194,25 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.5.1 + acorn: 8.13.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + ts-node@10.9.2(@types/node@20.5.1)(typescript@5.6.3): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -22660,6 +22596,24 @@ snapshots: - rollup - supports-color + vite-plugin-dts@2.3.0(@types/node@18.19.57)(rollup@4.24.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): + dependencies: + '@babel/parser': 7.25.8 + '@microsoft/api-extractor': 7.47.11(@types/node@18.19.57) + '@rollup/pluginutils': 5.1.2(rollup@4.24.0) + '@rushstack/node-core-library': 3.66.1(@types/node@18.19.57) + debug: 4.3.7 + fast-glob: 3.3.2 + fs-extra: 10.1.0 + kolorist: 1.8.0 + magic-string: 0.29.0 + ts-morph: 18.0.0 + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + vite-plugin-dts@2.3.0(@types/node@20.5.1)(rollup@4.24.0)(vite@3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)): dependencies: '@babel/parser': 7.25.8 @@ -22765,40 +22719,15 @@ snapshots: - rollup - supports-color - vite-plugin-md@0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)): - dependencies: - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) - '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - gray-matter: 4.0.3 - markdown-it: 13.0.2 - source-map-js: 1.2.1 - transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitejs/plugin-vue' - - '@vitest/browser' - - '@vitest/ui' - - encoding - - happy-dom - - jsdom - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite - - vite-plugin-md@0.20.6(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)): + vite-plugin-md@0.20.6(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0): dependencies: - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) + '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) gray-matter: 4.0.3 markdown-it: 13.0.2 source-map-js: 1.2.1 transitivePeerDependencies: - '@edge-runtime/vm' - - '@vitejs/plugin-vue' - '@vitest/browser' - '@vitest/ui' - encoding @@ -22811,16 +22740,15 @@ snapshots: - sugarss - supports-color - terser - - vite - vite-plugin-md@0.21.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): + vite-plugin-md@0.21.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): dependencies: - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) + '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) '@yankeeinlondon/gray-matter': 6.2.1(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) markdown-it: 13.0.2 source-map-js: 1.2.1 - vite: 5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) transitivePeerDependencies: - '@edge-runtime/vm' - '@vitejs/plugin-vue' @@ -22861,39 +22789,14 @@ snapshots: - supports-color - terser - vite-plugin-md@0.22.5(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)): - dependencies: - '@vitejs/plugin-vue': 4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) - '@yankeeinlondon/gray-matter': 6.2.1(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) - markdown-it: 13.0.2 - source-map-js: 1.2.1 - vite: 4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0) - transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitest/browser' - - '@vitest/ui' - - encoding - - happy-dom - - jsdom - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vite-plugin-md@0.22.5(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)): + vite-plugin-md@0.21.5(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): dependencies: - '@vitejs/plugin-vue': 4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) + '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) '@yankeeinlondon/gray-matter': 6.2.1(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) markdown-it: 13.0.2 source-map-js: 1.2.1 - vite: 4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) + vite: 5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) transitivePeerDependencies: - '@edge-runtime/vm' - '@vitest/browser' @@ -22909,19 +22812,15 @@ snapshots: - supports-color - terser - vite-plugin-md@0.22.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): + vite-plugin-md@0.22.5(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)): dependencies: - '@vitejs/plugin-vue': 4.6.2(vite@5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) -<<<<<<< HEAD - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0)) -======= - '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@4.5.5(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0)) ->>>>>>> main + '@vitejs/plugin-vue': 4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) + '@yankeeinlondon/builder-api': 1.4.1(@vitejs/plugin-vue@4.6.2(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)))(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0)(vite@5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0)) '@yankeeinlondon/gray-matter': 6.2.1(happy-dom@8.9.0)(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) '@yankeeinlondon/happy-wrapper': 2.10.1(jsdom@20.0.3)(sass@1.80.3)(terser@5.36.0) markdown-it: 13.0.2 source-map-js: 1.2.1 - vite: 5.4.9(@types/node@20.5.1)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) transitivePeerDependencies: - '@edge-runtime/vm' - '@vitest/browser' @@ -23165,17 +23064,17 @@ snapshots: - supports-color - typescript - vitepress@1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@4.9.5): + vitepress@1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3): dependencies: '@docsearch/css': 3.6.2 '@docsearch/js': 3.6.0(@algolia/client-search@4.24.0)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(search-insights@2.17.2) - '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) + '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) '@vue/devtools-api': 6.6.4 - '@vueuse/core': 9.2.0(vue@3.5.12(typescript@4.9.5)) + '@vueuse/core': 9.2.0(vue@3.5.12(typescript@5.6.3)) body-scroll-lock: 4.0.0-beta.0 shiki: 0.11.1 - vite: 3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) - vue: 3.5.12(typescript@4.9.5) + vite: 3.2.11(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0) + vue: 3.5.12(typescript@5.6.3) transitivePeerDependencies: - '@algolia/client-search' - '@types/node' @@ -23191,17 +23090,17 @@ snapshots: - terser - typescript - vitepress@1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@5.6.3): + vitepress@1.0.0-alpha.10(@algolia/client-search@4.24.0)(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(search-insights@2.17.2)(terser@5.36.0)(typescript@4.9.5): dependencies: '@docsearch/css': 3.6.2 '@docsearch/js': 3.6.0(@algolia/client-search@4.24.0)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(search-insights@2.17.2) - '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) + '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@4.9.5)) '@vue/devtools-api': 6.6.4 - '@vueuse/core': 9.2.0(vue@3.5.12(typescript@5.6.3)) + '@vueuse/core': 9.2.0(vue@3.5.12(typescript@4.9.5)) body-scroll-lock: 4.0.0-beta.0 shiki: 0.11.1 vite: 3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) - vue: 3.5.12(typescript@5.6.3) + vue: 3.5.12(typescript@4.9.5) transitivePeerDependencies: - '@algolia/client-search' - '@types/node' @@ -23217,16 +23116,16 @@ snapshots: - terser - typescript - vitepress@1.0.0-alpha.10(@types/node@18.19.57)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(terser@5.36.0)(typescript@5.6.3): + vitepress@1.0.0-alpha.10(@types/node@20.5.1)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(sass@1.80.3)(terser@5.36.0)(typescript@5.6.3): dependencies: '@docsearch/css': 3.6.2 '@docsearch/js': 3.6.0(@algolia/client-search@4.24.0)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)(search-insights@2.17.2) - '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) + '@vitejs/plugin-vue': 3.2.0(vite@3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) '@vue/devtools-api': 6.6.4 '@vueuse/core': 9.2.0(vue@3.5.12(typescript@5.6.3)) body-scroll-lock: 4.0.0-beta.0 shiki: 0.11.1 - vite: 3.2.11(@types/node@18.19.57)(sass@1.80.3)(terser@5.36.0) + vite: 3.2.11(@types/node@20.5.1)(sass@1.80.3)(terser@5.36.0) vue: 3.5.12(typescript@5.6.3) transitivePeerDependencies: - '@algolia/client-search' @@ -23300,7 +23199,7 @@ snapshots: '@types/chai': 4.3.20 '@types/chai-subset': 1.3.5 '@types/node': 18.19.57 - acorn: 8.13.0 + acorn: 8.14.0 acorn-walk: 8.3.4 chai: 4.5.0 debug: 4.3.7 @@ -23328,7 +23227,7 @@ snapshots: '@types/chai': 4.3.20 '@types/chai-subset': 1.3.5 '@types/node': 18.19.57 - acorn: 8.13.0 + acorn: 8.14.0 acorn-walk: 8.3.4 chai: 4.5.0 debug: 4.3.7 @@ -23463,6 +23362,42 @@ snapshots: - supports-color - terser + vitest@1.6.0(@types/node@18.19.57)(happy-dom@8.9.0)(jsdom@20.0.3)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0): + dependencies: + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.4 + chai: 4.5.0 + debug: 4.3.7 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.12 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.9(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + vite-node: 1.6.0(@types/node@18.19.57)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 18.19.57 + happy-dom: 8.9.0 + jsdom: 20.0.3 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vitest@1.6.0(@types/node@20.5.1)(happy-dom@8.9.0)(jsdom@20.0.3)(sass-embedded@1.80.3)(sass@1.80.3)(terser@5.36.0): dependencies: '@vitest/expect': 1.6.0 -- Gitee From ad00676d0370e180658ae5f1e41ec536718b9f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 18 Mar 2025 16:04:19 +0800 Subject: [PATCH 054/156] =?UTF-8?q?feature:=20=E6=8F=90=E4=BE=9B=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E7=BC=96=E8=BE=91=E5=99=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form-designer/form-designer.component.tsx | 3 +- .../monaco-editor/monaco-editor.component.tsx | 1 + .../composition/component-schema.service.ts | 41 ++- .../components/composition/use-form-schema.ts | 4 +- .../designer/src/components/types/metadata.ts | 4 +- .../row/hierarchy-row.component.tsx | 7 +- .../src/composition/use-type-resolver.ts | 2 + .../components/dynamic-form/src/types.ts | 2 +- .../components/dynamic-resolver/src/types.ts | 4 + .../dynamic-view/src/components/maps.ts | 2 + .../components/expression-editor/index.ts | 4 +- .../entities-variable/entity-model.ts | 23 ++ .../entity-variable.component.tsx | 161 ++++++++++ .../entity-variable.props.ts | 9 + .../entity-tree/entity-treeview.component.tsx | 53 ++++ .../entity-tree/entity-treeview.props.ts | 16 + .../components/expression-code.component.tsx | 59 +++- .../functions/common-functions.component.tsx | 224 +++++++++----- .../functions/common-functions.props.ts | 8 +- .../composition/functions-data/advanced.ts | 4 +- .../src/composition/functions-data/index.ts | 4 +- .../composition/functions-data/math-number.ts | 3 - .../src/composition/functions-data/string.ts | 35 +-- .../src/composition/types.ts | 2 + .../src/composition/use-esprima.ts | 120 ++++++++ .../src/composition/use-expression.ts | 214 ++++++++++++++ .../src/composition/use-search-function.tsx | 48 +++ .../src/expression-editor.component.tsx | 95 +++++- .../src/expression-editor.props.ts | 45 ++- .../src/expression-textbox.component.tsx | 80 ++++- .../src/expression-textbox.props.ts | 53 +++- .../src/schema/expression-editor.schema.json | 44 +++ .../src/schema/schema-mapper.ts | 5 - .../src/schema/schema-resolver.ts | 5 - .../components/expression-editor/style.scss | 79 ++++- .../src/filter-condition-editor.component.tsx | 2 +- .../src/components/layout-pane.component.tsx | 2 +- .../property-config/lookup.property-config.ts | 5 +- .../composition/entity/expression-property.ts | 276 ++++++++++++++++++ .../composition/entity/input-base-property.ts | 8 + .../tree-view/src/tree-view.component.tsx | 2 +- .../tree-view/src/tree-view.props.ts | 3 +- .../ui-vue/demos/expression-editor/basic.vue | 2 +- 43 files changed, 1577 insertions(+), 186 deletions(-) create mode 100644 packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts create mode 100644 packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.props.ts create mode 100644 packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx create mode 100644 packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.props.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/use-esprima.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/use-expression.ts create mode 100644 packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx delete mode 100644 packages/ui-vue/components/expression-editor/src/schema/schema-mapper.ts delete mode 100644 packages/ui-vue/components/expression-editor/src/schema/schema-resolver.ts create mode 100644 packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts diff --git a/packages/designer/src/components/components/form-designer/form-designer.component.tsx b/packages/designer/src/components/components/form-designer/form-designer.component.tsx index ec7b00f5826..96bd49bda4f 100644 --- a/packages/designer/src/components/components/form-designer/form-designer.component.tsx +++ b/packages/designer/src/components/components/form-designer/form-designer.component.tsx @@ -25,6 +25,7 @@ export default defineComponent({ const monacoEditorRef = ref(); const customClassEditorRef = ref(); + function onCanvasInitialized(dragula: any) { dragulaCompostion.value = dragula; } @@ -32,7 +33,7 @@ export default defineComponent({ const propertyConfig = ref(); const propertyName = ref(); const focusingSchema = ref(); - const schemaService = useComponentSchemaService(); + const schemaService = useComponentSchemaService(schema); schemaService.load(componentSchema.value); provide('SchemaService', schemaService); const designViewModelUtils = inject('designViewModelUtils') as UseDesignViewModel; diff --git a/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx b/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx index c8e67576452..66bc4859504 100644 --- a/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx +++ b/packages/designer/src/components/components/monaco-editor/monaco-editor.component.tsx @@ -41,6 +41,7 @@ export default defineComponent({ }); const resizeObserver = new ResizeObserver(entries => { editorInstance?.layout(); + editorInstance?.updateOptions({ theme: 'vs-dark' }); }); function getContent() { diff --git a/packages/designer/src/components/composition/component-schema.service.ts b/packages/designer/src/components/composition/component-schema.service.ts index a8060396de5..6e0f7dec477 100644 --- a/packages/designer/src/components/composition/component-schema.service.ts +++ b/packages/designer/src/components/composition/component-schema.service.ts @@ -1,7 +1,8 @@ import { SchemaService } from '@farris/ui-vue/components'; import { FormMetadataConverter } from './form-metadata-converter'; +import { Ref } from 'vue'; -export function useComponentSchemaService(): SchemaService { +export function useComponentSchemaService(formSchema: Ref): SchemaService { const componentSchemaMap = new Map>(); const componentParentMap = new Map(); @@ -52,6 +53,42 @@ export function useComponentSchemaService(): SchemaService { return formMetaDataConverter.getRealEditorType(editorType); } - return { closest, getSchemaById, load, select, getRealEditorType }; + function updateExpression(expressionItem: any) { + let {expressions } = formSchema.value.module; + if (!expressions) { + expressions = [expressionItem]; + } else { + let item = expressions.find(item => item.target === expressionItem.target); + if (!item) { + expressions.push(expressionItem); + } else { + item = expressionItem; + } + } + + formSchema.value.module.expressions = JSON.parse(JSON.stringify(expressions)); + } + + function getExpressionRuleValue(expressionId: any, rultType: string) { + const { expressions } = formSchema.value.module; + if (!expressions) { + return ''; + } + const expressionItem = expressions.find(item => item.target === expressionId); + if (!expressionItem) { + return ''; + } + + const ruleItem = expressionItem.rules.find(item => item.type === rultType); + if (!ruleItem) { + return ''; + } + + return ruleItem; + } + + return { closest, getSchemaById, load, select, getRealEditorType, updateExpression, + getExpressionRuleValue + }; } diff --git a/packages/designer/src/components/composition/use-form-schema.ts b/packages/designer/src/components/composition/use-form-schema.ts index 0986e1b165e..308e8582525 100644 --- a/packages/designer/src/components/composition/use-form-schema.ts +++ b/packages/designer/src/components/composition/use-form-schema.ts @@ -1302,6 +1302,8 @@ export function useFormSchema(): UseFormSchema { deleteComponent, getControlsInCmpWidthBinding, getVariableById, - updateRemoteVariables + updateRemoteVariables, + getRootViewModelId, + getSchemaEntities }; } diff --git a/packages/designer/src/components/types/metadata.ts b/packages/designer/src/components/types/metadata.ts index 6715f37ae3d..f5e617b33a2 100644 --- a/packages/designer/src/components/types/metadata.ts +++ b/packages/designer/src/components/types/metadata.ts @@ -1,6 +1,6 @@ import { FormComponent, FormExpression, FormStateMachine, FormWebCmd } from "./basic"; import { DesignViewModel } from "./design-viewmodel"; -import { FormSchema, FormSchemaEntityField } from "./entity-schema"; +import { FormSchema, FormSchemaEntity, FormSchemaEntityField } from "./entity-schema"; import { FormVariable, FormViewModel, FormViewModelField } from "./view-model"; export interface FormOptions { @@ -226,6 +226,8 @@ export interface UseFormSchema { getControlsInCmpWidthBinding: (viewModelId: string, fieldId: string) => any; getVariableById: (variableId: string) => FormVariable | undefined; updateRemoteVariables: (variables: FormSchemaEntityField[]) => void; + getRootViewModelId: () => string; + getSchemaEntities: () => FormSchemaEntity[]; } export interface UseSchemaService { diff --git a/packages/ui-vue/components/data-view/components/row/hierarchy-row.component.tsx b/packages/ui-vue/components/data-view/components/row/hierarchy-row.component.tsx index 50157e8e317..009b041718b 100644 --- a/packages/ui-vue/components/data-view/components/row/hierarchy-row.component.tsx +++ b/packages/ui-vue/components/data-view/components/row/hierarchy-row.component.tsx @@ -175,6 +175,10 @@ export default function ( (area === 'primary' && columnContext.value.primaryColumns.length > 0 && columnContext.value.primaryColumns[0].field === cell.field); } + function onDblclickRow(payload: MouseEvent, visualData: VisualData) { + context.emit('dblclickNode', {$event: payload, node: visualData.raw }); + } + /** 渲染树节点 */ function renderDataRow( visualData: VisualData, @@ -190,7 +194,8 @@ export default function ( style={rowPosition(visualData)} onMouseover={(payload: MouseEvent) => onMouseoverRow(payload, visualData)} onMouseout={(payload: MouseEvent) => onMouseoutRow(payload, visualData)} - onClick={(payload: MouseEvent) => onClickRow(payload, visualData)}> + onClick={(payload: MouseEvent) => onClickRow(payload, visualData)} + onDblclick={(payload: MouseEvent) => onDblclickRow(payload, visualData)}> {Object.values(visualData.data) .filter((cell: VisualDataCell) => cellPositionMap[cell.field] && cell.rowSpan === 1) .map((cell: VisualDataCell) => { diff --git a/packages/ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts b/packages/ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts index bb1c62b5c72..8b2fe2a50b8 100644 --- a/packages/ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts +++ b/packages/ui-vue/components/dynamic-form/src/composition/use-type-resolver.ts @@ -94,6 +94,8 @@ export function useTypeResolver(): UseTypeResolver { case 'query-solution-config': case 'solution-preset': return 'onFieldsChanged'; + case 'expression-editor': + return 'onExpressionChanged'; } } diff --git a/packages/ui-vue/components/dynamic-form/src/types.ts b/packages/ui-vue/components/dynamic-form/src/types.ts index 878bffe474d..4bce11deea4 100644 --- a/packages/ui-vue/components/dynamic-form/src/types.ts +++ b/packages/ui-vue/components/dynamic-form/src/types.ts @@ -3,7 +3,7 @@ export type EditorType = 'button-edit' | 'check-box' | 'check-group' | 'combo-li 'year-picker' | 'year-range' | 'input-group' | 'lookup' | 'number-range' | 'number-spinner' | 'radio-group' | 'text' | 'response-layout-editor-setting' | 'switch' | 'grid-field-editor' | 'field-selector' | 'schema-selector' | 'mapping-editor' | 'textarea' | 'response-form-layout-setting' | 'binding-selector' | 'query-solution-config' | 'solution-preset' | 'item-collection-editor' | - 'menu-lookup'| 'response-layout-splitter'; + 'menu-lookup'| 'response-layout-splitter' | 'expression-editor'; export interface EditorConfig { /** 编辑器类型 */ diff --git a/packages/ui-vue/components/dynamic-resolver/src/types.ts b/packages/ui-vue/components/dynamic-resolver/src/types.ts index c82d887f402..5c096dff439 100644 --- a/packages/ui-vue/components/dynamic-resolver/src/types.ts +++ b/packages/ui-vue/components/dynamic-resolver/src/types.ts @@ -14,6 +14,10 @@ export interface SchemaService { select: (root: Record, predicate: (child: Record) => boolean) => Record; getRealEditorType: (editorType: string) => string; + + updateExpression: (expressionItem: any) => void; + + getExpressionRuleValue: (expressionId: string, ruleType: string) => string; } export interface PropertyConverter { diff --git a/packages/ui-vue/components/dynamic-view/src/components/maps.ts b/packages/ui-vue/components/dynamic-view/src/components/maps.ts index dbafd395b28..71f25b1e234 100644 --- a/packages/ui-vue/components/dynamic-view/src/components/maps.ts +++ b/packages/ui-vue/components/dynamic-view/src/components/maps.ts @@ -64,6 +64,7 @@ import FFieldset from '@farris/ui-vue/components/fieldset'; import FSortConditionEditor from '@farris/ui-vue/components/sort-condition-editor'; import FMenuLookup from '@farris/ui-vue/components/menu-lookup'; import FDrawer from '@farris/ui-vue/components/drawer'; +import FExpressionEditor from '@farris/ui-vue/components/expression-editor'; const componentMap: Record = {}; const componentPropsConverter: Record = {}; @@ -93,6 +94,7 @@ function loadRegister() { FDropdown.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FDynamicForm.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FEventsEditor.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); + FExpressionEditor.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FFilterBar.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FFieldSelector.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); FFilterConditionEditor.register(componentMap, componentPropsConverter, componentPropertyConfigConverter, resolverMap); diff --git a/packages/ui-vue/components/expression-editor/index.ts b/packages/ui-vue/components/expression-editor/index.ts index d5641751bce..de920d98517 100644 --- a/packages/ui-vue/components/expression-editor/index.ts +++ b/packages/ui-vue/components/expression-editor/index.ts @@ -17,7 +17,7 @@ import type { App } from 'vue'; import ExpressionEditor from './src/expression-editor.component'; import FExpressionTextbox from './src/expression-textbox.component'; -import { expressionTextboxProps } from './src/expression-textbox.props'; +import { propsResolver } from './src/expression-textbox.props'; import './style.scss'; export * from './src/expression-editor.props'; @@ -30,6 +30,6 @@ export default { }, register(componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record): void { componentMap['expression-editor'] = FExpressionTextbox; - propsResolverMap['expression-editor'] = expressionTextboxProps; + propsResolverMap['expression-editor'] = propsResolver; } }; diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts new file mode 100644 index 00000000000..a9ccec6b087 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts @@ -0,0 +1,23 @@ + + +export interface VariableModel { + /** 标识,不可重复 */ + key: string; + /** 名称 */ + name: string; + /** 描述 */ + description: string; +} + +export interface VariableModels { + [key: string]: { + name: string, + items: VariableModel[] + } +} + + +export interface EntityVariableDataSource { + entities?: { entityCode: string, fields: any[] }, + variables?: VariableModels +}; diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx new file mode 100644 index 00000000000..1e67a2c14de --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx @@ -0,0 +1,161 @@ +import { computed, defineComponent, onMounted, ref } from "vue"; +import { entityVariableProps } from "./entity-variable.props"; +import FEntitiesTree from "../entity-tree/entity-treeview.component"; + +export default defineComponent({ + name: 'entity-variable', + props: entityVariableProps, + emits: ['variableItemDblClick', 'entityItemDblClick'], + setup(props, context) { + + const currentExpandName = ref('dataEntity'); + const dataSource = ref(props.dataSource); + const { entities, variables } = dataSource.value; + + const entityTreeDisplayFormat = (cell, data) => { + return `${data.raw['name']} [${data.raw['bindingPath']}]`; + }; + + const variableExpandStatus = ref({}); + const currentVariableItem = ref(); + + const expandClass = computed(() => { + return (groupName: string) => { + return { + "list-group d-flex flex-column": true, + "f-utils-fill": currentExpandName.value === groupName, + "expand": currentExpandName.value === groupName, + "collapse": currentExpandName.value !== groupName + }; + }; + }); + + const expandIconClass = computed(() => { + return (groupName: string) => { + return { + "f-icon f-icon-arrow-chevron-up": currentExpandName.value !== groupName, + "f-icon f-icon-arrow-chevron-down": currentExpandName.value === groupName + }; + }; + }); + + + const variableTypeExtendClass = computed(() => { + return (variableTypeName: string) => { + return { + "functions-type d-flex flex-column": true, + open: variableExpandStatus.value[variableTypeName], + closed: !variableExpandStatus.value[variableTypeName] + }; + }; + }); + + const variableTypeIconClass = computed(() => { + return (variableTypeName: string) => { + return { + "f-icon f-icon-arrow-chevron-down": variableExpandStatus.value[variableTypeName], + "f-icon f-icon-arrow-chevron-right":!variableExpandStatus.value[variableTypeName] + }; + }; + }); + + const selectedVariableClass = computed(() => { + return (variableItem: any) => { + return { + "functions-item pl-2": true, + "selected": currentVariableItem.value?.key === variableItem.key + }; + }; + }); + + function onVariableTypeClick($event:MouseEvent, type: string) { + $event.stopPropagation(); + variableExpandStatus.value = variableExpandStatus.value || {}; + variableExpandStatus.value[type] = !variableExpandStatus.value[type]; + } + + function onVariableItemClick($event: MouseEvent, variableItem: any) { + $event.stopPropagation(); + currentVariableItem.value = variableItem; + } + + function onVariableItemDblClick($event: MouseEvent, variableItem: any) { + context.emit('variableItemDblClick', {$event, item: variableItem}); + } + + function onFieldDblclick({$event, node}) { + context.emit('entityItemDblClick', {$event, item: node.data, entityCode: entities?.entityCode}); + } + + function renderEntities() { + return ; + } + + function renderVariables() { + if (variables) { + return
    + {Object.keys(variables).map((key) => { + return
  • +
    { onVariableTypeClick($event, key); }}> + + {variables[key].name} +
    +
      + {variables[key].items.map((item) => { + return
    • onVariableItemClick(payload, item)} + onDblclick={(payload) => onVariableItemDblClick(payload, item)}> + {item.name}
    • ; + })} +
    +
  • ; + + })} +
; + } + } + + function onGroupClick($event, groupName: string) { + $event.stopPropagation(); + if (currentExpandName.value === groupName) { + currentExpandName.value = ''; + return; + } + currentExpandName.value = groupName; + } + + onMounted(() => { + if (variables) { + const variableType = Object.keys(variables)[0]; + variableExpandStatus.value[variableType] = true; + } + }); + + + return () => { + return
+
    +
  • +
    onGroupClick($event, 'dataEntity')}> + 数据实体 + +
    +
    + {renderEntities()} +
    +
  • +
  • +
    onGroupClick($event, 'variables')}> + 变量 + +
    +
    + {renderVariables()} +
    +
  • +
+
; + }; + } +}); diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.props.ts b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.props.ts new file mode 100644 index 00000000000..739afe42fa8 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.props.ts @@ -0,0 +1,9 @@ +import { PropType } from "vue"; +import { EntityVariableDataSource } from "./entity-model"; + +export const entityVariableProps = { + dataSource: { + type: Object as PropType, + default: {} + } +}; diff --git a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx new file mode 100644 index 00000000000..d478934171d --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx @@ -0,0 +1,53 @@ +import { computed, defineComponent, inject, onMounted, ref } from "vue"; +import FTreeView from '@farris/ui-vue/components/tree-view'; + +import { entityTreeviewProps, EntityTreeviewProps } from "./entity-treeview.props"; + +export default defineComponent({ + name: 'FEntitiesTree', + props: entityTreeviewProps, + emits: ['dblclickNode'], + setup(props: EntityTreeviewProps, context) { + const dataSource = ref(props.data); + + const rowOption = { + customRowStatus: props.customRowStatus + }; + + + const treeColumn = computed(() => { + return [{ + field: props.textField, title: '', + dataType: 'string', + formatter: props.formatter + }]; + }); + + function onDblclickNode({$event, node}) { + context.emit('dblclickNode', {$event, node}); + } + + + onMounted(() => { + + }); + + return () => { + return ( +
+ +
+ ); + }; + } +}); diff --git a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.props.ts b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.props.ts new file mode 100644 index 00000000000..e75c00ac36f --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.props.ts @@ -0,0 +1,16 @@ +import { ExtractPropTypes } from "vue"; + +export const entityTreeviewProps = { + + data: { type: Array, default: [] }, + + + idField: { type: String, default: 'id' }, + + textField: { type: String, default: 'name' }, + + formatter: { type: Function }, + + customRowStatus: { type: Object, default: null } +}; +export type EntityTreeviewProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx index 53cdb05d512..afd9b83534e 100644 --- a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx @@ -1,19 +1,21 @@ -import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from "vue"; +import { defineComponent, onBeforeUnmount, onMounted, PropType, ref, watch } from "vue"; import loader from "@monaco-editor/loader"; +import { MonacoEditorTheme } from "../composition/types"; export default defineComponent({ name: 'expression-code', props: { modelValue: { type: String, default: '' }, - language: { type: String, default: 'typescript' }, - theme: { type: String, default: 'vs-dark' }, + language: { type: String, default: 'javascript' }, + theme: { type: String as PropType, default: 'vs' }, readOnly: { type: Boolean, default: false }, configPath: { type: String, default: 'assets/monaco-editor.config.json' } }, emits: [], - setup(props, context) { + setup(props, context) { const editorContainer = ref(); + const monacoRef = ref(); let editorInstance: any = null; const codeValues = ref(props.modelValue); @@ -31,12 +33,22 @@ export default defineComponent({ loader.config({ "vs/nls": { availableLanguages: { "*": "zh-cn" } } }); loader.init().then((monaco) => { + monacoRef.value = monaco; editorInstance = monaco.editor.create(editorContainer.value, { value: codeValues.value, + automaticLayout: true, // 自动调整布局 language: props.language, theme: props.theme, folding: true, - readOnly: props.readOnly + readOnly: props.readOnly, + minimap: { enabled: false }, + lineNumbers: 'on', + lineNumbersMinChars: 3, + overviewRulerLanes: 0, + scrollbar: { + verticalScrollbarSize: 8, + horizontalScrollbarSize: 8, + } }); }); } @@ -54,6 +66,24 @@ export default defineComponent({ return editorInstance?.getValue(); } + function insertText(text: string) { + // 获取当前选择范围(光标位置或选中区域) + const selection = editorInstance.getSelection(); + // 创建插入的 Range 对象 + const range = new monacoRef.value.Range( + selection.startLineNumber, + selection.startColumn, + selection.endLineNumber, + selection.endColumn + ); + // 执行编辑操作 + editorInstance.executeEdits('insert-text', [{ + range: range, + text, + forceMoveMarkers: true // 移动光标到插入后的位置 + }]); + } + onMounted(() => { initMonacoEditor(); editorContainer.value && resizeObserver.observe(editorContainer.value); @@ -70,12 +100,25 @@ export default defineComponent({ } }); - context.expose({ - getContent + function setContent(content: string) { + editorInstance.setValue(content); + } + + + function clearText() { + setContent(''); + } + + + context.expose({ + getContent, + insertText, + clearText, + setContent }); return () => { - return
; + return
; }; } }); diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx index 1c4cb25cbe0..2d1df929ab8 100644 --- a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx @@ -1,36 +1,53 @@ -import { computed, defineComponent, nextTick, onMounted, onUpdated, Ref, ref, watch } from "vue"; - +import { computed, defineComponent, onMounted, ref, watch } from "vue"; +import { FButtonEdit } from "@farris/ui-vue/components/button-edit"; import { FLayout, FLayoutPane } from "../../../../../components/layout"; -import { commonFunctions } from "../../composition/functions-data"; import { commonFunctionsProps } from "./common-functions.props"; -import { DisabledFunction } from "../../composition/types"; export default defineComponent({ name: 'FExpressionEditor', props: commonFunctionsProps, - emits: [] as (string[] & ThisType) | undefined, + emits: ['insertFunction', 'search'], setup(props, context) { const commonFunctionRef = ref(); const currentFunctionType = ref(''); const currentFunctionItem = ref(); + const expandStatus = ref({}); + const searchFunctionValue = ref(''); + + const dataSource = ref(props.functionItems); const functionTypeExtendClass = computed(() => { return (functionTypeName: string) => { - return { - "functions-type d-flex flex-column": true, - open: currentFunctionType.value === functionTypeName, - closed: currentFunctionType.value !== functionTypeName - }; + if (props.singleExpand) { + return { + "functions-type d-flex flex-column": true, + open: currentFunctionType.value === functionTypeName, + closed: currentFunctionType.value !== functionTypeName + }; + } else { + return { + "functions-type d-flex flex-column": true, + open: expandStatus.value[functionTypeName], + closed: !expandStatus.value[functionTypeName] + }; + } }; }); const functionTypeIconClass = computed(() => { return (functionTypeName: string) => { - return { - "f-icon f-icon-arrow-chevron-down": currentFunctionType.value === functionTypeName, - "f-icon f-icon-arrow-chevron-right": currentFunctionType.value!== functionTypeName - }; + if (props.singleExpand) { + return { + "f-icon f-icon-arrow-chevron-down": currentFunctionType.value === functionTypeName, + "f-icon f-icon-arrow-chevron-right": currentFunctionType.value!== functionTypeName + }; + } else { + return { + "f-icon f-icon-arrow-chevron-down": expandStatus.value[functionTypeName], + "f-icon f-icon-arrow-chevron-right":!expandStatus.value[functionTypeName] + }; + } }; }); @@ -43,46 +60,48 @@ export default defineComponent({ }; }); - const disabled = ref(props.disabled || {}) as Ref; // 常用函数类型 - const functionsTypes = ref(Object.keys(commonFunctions)); - - if (disabled.value) { - const { types: disabledTypes, functions: disabledFunctions } = disabled.value; - if (disabledTypes && disabledTypes.length) { - functionsTypes.value = functionsTypes.value.filter((functionType) => { - return disabledTypes.includes(functionType); - }); - } - - if (disabledFunctions && disabledFunctions.length) { - Object.values(commonFunctions).forEach((functions) => { - functions.items.forEach((functionItem) => { - if (disabledFunctions.includes(functionItem.name)) { - functionItem['visible'] = false; - } - }); - }); + const functionsTypes = ref(Object.keys(dataSource.value)); + + watch(() =>props.functionItems, (newValue) => { + dataSource.value = newValue; + functionsTypes.value = Object.keys(dataSource.value); + + if (searchFunctionValue.value) { + expandStatus.value = functionsTypes.value.reduce((result, typeName) => { + result[typeName] = true; + return result; + }, {}); } - } + }); - function functionTypeIntoView() { - const functionTypeDom = commonFunctionRef.value.querySelector('li[function-type="'+ currentFunctionType.value +'"] > div.functions-type-name'); + + function functionTypeIntoView(functionTypeName?: string) { + if (!functionTypeName) { + functionTypeName = currentFunctionType.value; + } + const functionTypeDom = commonFunctionRef.value.querySelector('li[function-type="'+ functionTypeName +'"] > div.functions-type-name'); if (functionTypeDom) { - functionTypeDom.scrollIntoView({behavior: 'smooth', block: 'center'}); + commonFunctionRef.value.querySelector('.expression-left').scrollTop = 0; + if (functionTypeDom.scrollIntoViewIfNeeded) { + functionTypeDom.scrollIntoViewIfNeeded(true); + } else { + functionTypeDom.scrollIntoView({behavior: 'smooth', block: 'nearest'}); + } } } function onFunctionTypeClick(functionTypeName: string) { - if (currentFunctionType.value === functionTypeName) { - currentFunctionType.value = ''; - return; + if (props.singleExpand) { + if (currentFunctionType.value === functionTypeName) { + currentFunctionType.value = ''; + return; + } + currentFunctionType.value = functionTypeName; + } else { + expandStatus.value = expandStatus.value || {}; + expandStatus.value[functionTypeName] = !expandStatus.value[functionTypeName]; } - currentFunctionType.value = ''; - setTimeout(() => { - currentFunctionType.value = currentFunctionType.value = functionTypeName; - functionTypeIntoView(); - }, 200); } function onFunctionItemClick($event: MouseEvent, functionItem: any) { @@ -90,47 +109,96 @@ export default defineComponent({ currentFunctionItem.value = functionItem; } + function onFunctionItemDblClick($event: MouseEvent, functionItem: any) { + $event.stopPropagation(); + context.emit('insertFunction', {$event, item: functionItem }); + } - onMounted(() => { - currentFunctionType.value = functionsTypes.value[0]; + watch(() => currentFunctionType.value, (newValue, oldValue, onCleanup) => { + if (newValue) { + const timer = setTimeout(() => { + functionTypeIntoView(newValue); + }, 200); + onCleanup(() => clearTimeout(timer)); + } }); + function onSearch() { + context.emit('search', searchFunctionValue.value); + } - return () => { - return
+ function onClearSearchValue() { + context.emit('search', ''); + } - - -
-
    - { functionsTypes.value.map((type) => { - return
  • {onFunctionTypeClick(type)}}> -
    - - {commonFunctions[type].name} -
    -
      - {commonFunctions[type].items.map((item) => { - if (item.visible !== false) { - return
    • onFunctionItemClick(payload, item)}>{item.name}
    • ; - } - })} -
    -
  • ; - }) } -
+ function onEnterHandler($event: KeyboardEvent) { + if ($event.key === 'Enter') { + onSearch(); + } + } + + function renderFunctionItem() { + return functionsTypes.value.map((type) => { + return ( +
  • +
    {onFunctionTypeClick(type)}}> + + {dataSource.value[type].name}
    - - - - - +
      + {dataSource.value[type].items.map((item) => { + if (item.visible !== false) { + return
    • onFunctionItemClick(payload, item)} + onDblclick={(payload) => onFunctionItemDblClick(payload, item)}> + {type === 'advanced'? item.key :item.name}
    • ; + } + })} +
    +
  • + ); + }); + } + + onMounted(() => { + currentFunctionType.value = functionsTypes.value[0]; + expandStatus.value = functionsTypes.value.reduce((prev, curr) => { + prev[curr] = currentFunctionType.value === curr; + return prev; + }, {}); + }); -
    ; + return () => { + return ( +
    + + + '} + enableClear={true} + popupOnClick={true} + placeholder={'请输入函数名称'} + v-model={searchFunctionValue.value} + onClickButton={onSearch} + onClear={onClearSearchValue} + onKeyup={onEnterHandler} + > + + +
      + { renderFunctionItem()} +
    +
    + + + +
    +
    + ); }; } }); diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts index dc32f668200..c53b956a2ef 100644 --- a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.props.ts @@ -3,12 +3,12 @@ import { DisabledFunction } from "../../composition/types"; export const commonFunctionsProps = { - data: { + functionItems: { type: Array, default: [] }, - disabled: { - type: Object as PropType, - default: null + singleExpand: { + type: Boolean, + default: true } }; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts index 20e9e9b58df..74009be600b 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/advanced.ts @@ -1,7 +1,7 @@ export const advancedFunctions = [ { key: "if", - name: "if()\n{\n\n}", + name: "if() {\n\n}", params: [], description: "if条件成立,执行括号中内容", type: "Advanced", @@ -9,7 +9,7 @@ export const advancedFunctions = [ className: "" }, { key: "if else", - name: "if()\n{\n\n}\nelse\n{\n\n}", + name: "if() {\n\n} else {\n\n}", params: [], description: "if条件成立,执行括号中内容;否则执行else中内容", type: "Advanced", diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts index 355e6658a9d..9933005caf4 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/index.ts @@ -7,10 +7,10 @@ import { translateFunctions } from "./translate"; export const commonFunctions = { - advanced: { name: '高级' ,items: advancedFunctions}, analytical: { name: '数据', items: analyticalFunctions}, datetime: {name: '时间',items: dateTimeFunctions}, string: {name: '字符', items: stringFunctions}, math: {name: '数字', items: mathFunctions}, - translate: {name: '转换', items: translateFunctions} + translate: {name: '转换', items: translateFunctions}, + advanced: { name: '高级' ,items: advancedFunctions} }; diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts index 457b580407f..39ef9d2c298 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts @@ -98,9 +98,6 @@ export const mathFunctions = [ type: "Math", keyFront: "Math", className: "" - }, { - key: "BankerRound", - name: "银行家舍入" }, { key: "bankerRound", name: "银行家舍入", diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts index 6bee70659b4..6421a4c3fc7 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/string.ts @@ -1,8 +1,5 @@ export const stringFunctions = [ { - key: "StringSubstring", - name: "取子字符串" - }, { key: "SubString", name: "取子字符串", params: [{ @@ -22,9 +19,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringLength", - name: "取字符串长度" }, { key: "Length", name: "取字符串长度", @@ -133,10 +127,7 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringReplace", - name: "字符串替换" - }, { + },{ key: "Replace", name: "字符串替换", params: [{ @@ -156,9 +147,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringToUpper", - name: "转大写" }, { key: "ToUpper", name: "转大写", @@ -171,9 +159,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringToLower", - name: "转小写" }, { key: "ToLower", name: "转小写", @@ -186,9 +171,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringIndexOf", - name: "首个匹配字符索引" }, { key: "IndexOf", name: "首个匹配字符索引", @@ -205,9 +187,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringLastIndexOf", - name: "最后匹配字符索引" }, { key: "LastIndexOf", name: "最后匹配字符索引", @@ -224,9 +203,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringTrimStart", - name: "删除头部空格" }, { key: "TrimStart", name: "删除头部空格", @@ -239,9 +215,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringTrimEnd", - name: "删除尾部空格" }, { key: "TrimEnd", name: "删除尾部空格", @@ -254,9 +227,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringTrim", - name: "删除头尾部空格" }, { key: "Trim", name: "删除头尾部空格", @@ -277,9 +247,6 @@ export const stringFunctions = [ type: "String", keyFront: "DefaultFunction", className: "" - }, { - key: "StringAdd", - name: "字符串相加" }, { key: "Add", name: "字符串相加", diff --git a/packages/ui-vue/components/expression-editor/src/composition/types.ts b/packages/ui-vue/components/expression-editor/src/composition/types.ts index 6a1c5ba728b..28d504132f6 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/types.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/types.ts @@ -2,3 +2,5 @@ export interface DisabledFunction { types?: string[]; functions?: string[]; } + +export type MonacoEditorTheme = 'vs' | 'vs-dark' | 'hc-black'; diff --git a/packages/ui-vue/components/expression-editor/src/composition/use-esprima.ts b/packages/ui-vue/components/expression-editor/src/composition/use-esprima.ts new file mode 100644 index 00000000000..4ce266bd466 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/use-esprima.ts @@ -0,0 +1,120 @@ +export function useEsprima(props: any) { + + async function getEsprimaConfig() { + return fetch(props.esprimaPath).then((config: Record) => { + return config.json(); + }); + } + + async function loadEsprima() { + if ((window as any).esprima == null) { + const config = await getEsprimaConfig(); + const { path: esprimaPath } = config; + return new Promise((resolve, reject) => { + const esprimaScript = document.createElement("script"); + esprimaScript.type = "text/javascript"; + esprimaScript.src = esprimaPath + "?v=" + Date.now(); + esprimaScript.onload = resolve; + esprimaScript.onerror = reject; + document.head.appendChild(esprimaScript); + + }); + } + } + + + function getTokens(ruleValue: string) { + const tokens: any = []; + + // 加载Esprima + const wholeTokens = window['esprima'].tokenize(ruleValue); + for (let i = 0; i < wholeTokens.length; i++) { + tokens.push(wholeTokens[i].value); + } + + // 根据ruleValue,获取需要填充的字符(esprima分词后导致空格、换行符丢失,需要手动记录并添加回来) + const whites: any = []; + for (let i = 0; i < tokens.length; i++) { + const pos = ruleValue.indexOf(tokens[i]); + if (pos !== -1) { + whites.push(ruleValue.substring(0, pos)); + } else { + whites.push(""); + } + ruleValue = ruleValue.slice(pos + tokens[i].length); + + // 最后一位特殊处理 + if (i === tokens.length - 1) { + whites.push(ruleValue); + } + } + + // 合并tokens和whites + const result: any = []; + const total = tokens.length; + for (let i = 0; i < total; i++) { + if (whites[i] !== "") { result.push(whites[i]); } + if (tokens[i] !== "") { result.push(tokens[i]); } + + if (i === total - 1) { + if (whites[i + 1] !== "") { result.push(whites[i + 1]); } + } + } + + return result; + } + + function getVariableMaps(variables: any, type: 'key2name' | 'name2key' = 'key2name'): Map { + const variableMap = new Map(); + if (!variables) { + return variableMap; + } + const variableList = Object.values(variables); + + + let tempLists: any = variableList; + while (tempLists.length > 0) { + const filterTempLists = tempLists.filter(i => i.name === tempLists[0].name); + if (filterTempLists.length > 1) { + tempLists.filter(i => i.name === tempLists[0].name).forEach(varEntity => { + if (type === "key2name") { + variableMap.set(varEntity.key, varEntity.key + '_' + varEntity.name); + } else if (type === "name2key") { + variableMap.set(varEntity.key + '_' + varEntity.name, varEntity.key); + } + }); + } else { + if (type === "key2name") { + variableMap.set(filterTempLists[0].key, filterTempLists[0].name); + } else if (type === "name2key") { + variableMap.set(filterTempLists[0].name, filterTempLists[0].key); + } + } + // 重置tempLists + tempLists = tempLists.filter(i => i.name !== tempLists[0].name); + } + + return variableMap; + } + + loadEsprima(); + + async function runWithEsprima(callback: any) { + if (!window['esprima']) { + return await loadEsprima().then(() => { + return callback(); + }); + } else { + return callback(); + } + } + + return { + loadEsprima, + getTokens, + getVariableMaps, + runWithEsprima + }; + +}; + diff --git a/packages/ui-vue/components/expression-editor/src/composition/use-expression.ts b/packages/ui-vue/components/expression-editor/src/composition/use-expression.ts new file mode 100644 index 00000000000..25062bdf47f --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/use-expression.ts @@ -0,0 +1,214 @@ +import { cloneDeep } from "lodash-es"; +import { ref } from "vue"; +import { useEsprima } from "./use-esprima"; + +export function useExpression(props, functionItems: any, variables: any) { + const disabled = ref(props.disabledFunctions); + + const { getTokens, getVariableMaps, runWithEsprima } = useEsprima(props); + + function resetFunctionItems() { + const functions = cloneDeep(functionItems); + if (disabled.value) { + let functionsTypes = Object.keys(functions); + + const { types: disabledTypes, functions: disabledFunctions } = disabled.value; + if (disabledTypes && disabledTypes.length) { + functionsTypes = functionsTypes.filter((functionType) => { + return disabledTypes.includes(functionType); + }); + } + + if (disabledFunctions && disabledFunctions.length) { + Object.values(functions).forEach((functions: any) => { + functions.items.forEach((functionItem) => { + if (disabledFunctions.includes(functionItem.name)) { + functionItem['visible'] = false; + } + }); + }); + } + + return functions; + } + return functions; + } + + + function getContextVariableExpression(contextVariableItem: any) { + const getContextFunctionItem = functionItems.analytical.items.find(item => item.key === 'GetContextParameter'); + if (getContextFunctionItem) { + const expression = getContextFunctionItem.name + '(' + contextVariableItem.name + ')'; + return expression; + } + } + + function getParamsText(params: Array) { + if (!params || params.length === 0) { + return ""; + } + + const formatParam = (param: { name: string, type: 'string' | 'list' | 'other' }) => { + switch (param.type) { + case 'string': + return `"${param.name}"`; + case 'list': + return `[${param.name}]`; + default: + return param.name; + } + }; + + return params.map(formatParam).join(','); + } + + function getFunctionExpression(functionItem: any) { + let expressionText = functionItem.name; + if (functionItem.type.toLowerCase() !== 'advanced') { + expressionText += '(' + getParamsText(functionItem.params) + ')'; + } + + return expressionText; + } + + function getFieldExpression(fieldItem: any) { + return fieldItem?.bindingPath; + } + + function getExpressionCodeValue(ruleValue: string) { + if (!ruleValue) { + return ""; + } + + // expr不为空,Antlr4解析获取tokens + const tokens = getTokens(ruleValue); + // 合并上下文变量、会话变量 + const varMap = getVariableMaps(variables, "name2key"); + + // 语义化文本解析为表达式串 + for (let index = 0; index < tokens.length; index++) { + let num = 0; + // 遍历变量 + if (num === 0 && varMap) { + if (tokens[index].length > 2 && tokens[index][0] === "\"" && tokens[index][tokens[index].length - 1] === "\"") { + // 校验第0位和第length-1位是否是" + const temp = tokens[index].substring(1, tokens[index].length - 1); + // 此处需要DefaultFunction.GetContextParameter、DefaultFunction.GetSessionValue + if (varMap.has(temp) && tokens[index - 1] === "(" && tokens[index + 1] === ")") { + tokens[index] = "\"" + varMap.get(temp) + "\""; + num = 1; + } + } + } + // 遍历函数 + if (num === 0) { + const allFunctionItems: any[] = Object.values(functionItems).map((item: any) => item.items).flat(); + for (let indexTok = 0; indexTok < allFunctionItems.length; indexTok++) { + if (tokens[index] === allFunctionItems[indexTok].name) { + tokens[index] = allFunctionItems[indexTok].keyFront + '.' + allFunctionItems[indexTok].key; + num = 1; + break; + }; + } + } + } + // 合并 + let temp = ""; + for (let index = 0; index < tokens.length; index++) { + temp = temp + tokens[index]; + } + return JSON.stringify({ expr: temp, sexpr: '' }); + } + + function toSemantic(tokens: any, allFunctions: any[], variableMap: Map, functionSuffixs: string[]): string { + let result = ""; + + // 表达式引擎内置Math函数 + const innerMath: any = []; + for (const func of allFunctions) { + if (func.keyFront === "Math") { + innerMath.push(func.key); + } + } + + for (let index = 0; index < tokens.length; index++) { + // 如果为非内置的Math函数,则保留"Math." + if (tokens[index] === "Math" && tokens[index + 1] === "." && !innerMath.includes(tokens[index + 2])) { + result = result + tokens[index] + tokens[index + 1] + tokens[index + 2]; + index = index + 2; + continue; + } + + if (functionSuffixs.includes(tokens[index]) && (tokens[index + 1] === ".")) { + index = index + 1; + continue; + } else { + let num = 0; + // 遍历会话变量和上下文变量 + if (num === 0) { + if (tokens[index].length > 2 && tokens[index][0] === "\"" && tokens[index][tokens[index].length - 1] === "\"") { + // 校验第0位和第length-1位是否是" + const temp = tokens[index].substring(1, tokens[index].length - 1); + // 此处需要GetContextParameter、GetSessionValue + if (variableMap.has(temp) && tokens[index - 1] === "(" && tokens[index + 1] === ")") { + result = result + "\"" + variableMap.get(temp) + "\""; + num = 1; + } + } + } + // 计数器num:如果遍历allFunctions没找到对应字段,则直接拼接(num=0);否则替换(num=1) + if (num === 0) { + for (let i = 0; i < allFunctions.length; i++) { + if (tokens[index] === allFunctions[i].key) { + if (allFunctions[i].type.toLowerCase() !== "advanced") { + result = result + allFunctions[i].name; + num = 1; + break; + } + } + } + } + // 如果计数器为0,证明没有语义化匹配。显示原始数据 + if (num === 0) { + result = result + tokens[index]; + } + } + } + return result; + } + + function convertRuleCodeToName(ruleValue: string) { + if (!ruleValue) { + return ""; + } + + // expr不为空,Antlr4解析获取tokens + const tokens = getTokens(ruleValue); + // 合并上下文变量、会话变量 + const varMap = getVariableMaps(variables, "key2name"); + + const allFunctionItems: any[] = Object.values(functionItems).map((item: any) => item.items).flat(); + + // 静态资源 + const functionSuffixs = ["DefaultFunction", "Math", "DefaultExtendFunctionProxy"]; + + return toSemantic(tokens, allFunctionItems, varMap, functionSuffixs); + } + + async function getExpressionTextValue(ruleValue: string) { + return await runWithEsprima(() => { + return convertRuleCodeToName(ruleValue); + }); + } + + return { + resetFunctionItems, + getFieldExpression, + getFunctionExpression, + getContextVariableExpression, + getExpressionCodeValue, + getExpressionTextValue + }; + + +} diff --git a/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx b/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx new file mode 100644 index 00000000000..a8838af0f89 --- /dev/null +++ b/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx @@ -0,0 +1,48 @@ +import { ref } from "vue"; +import { cloneDeep } from "lodash-es"; + + +export function useSearchFunction(props, functionItems: any) { + const searchResultList: any = ref([]); + + const originFunctionItems = cloneDeep(functionItems.value); + + const allFunctionItems: any[] = Object.values(originFunctionItems).map((item: any) => item.items).flat(); + + + function filterFunctions(resultKeys: any) { + const itemsCopy = cloneDeep(originFunctionItems); + Object.keys(itemsCopy).forEach((key) => { + const list = itemsCopy[key].items.filter((item: any) => { + return resultKeys.includes(item.key); + }); + if (list.length > 0) { + itemsCopy[key].items = list; + } else { + delete itemsCopy[key]; + } + }); + return itemsCopy; + } + + function onFunctionSearch(searchValue: string) { + if (!searchValue) { + functionItems.value = originFunctionItems; + return; + } + + const searchResultKeys = allFunctionItems.filter((item: any) => { + return item.name.toLowerCase().includes(searchValue.toLowerCase()) || + item.key.toLowerCase().includes(searchValue.toLowerCase()); + }).map(item => item.key); + + functionItems.value = filterFunctions(searchResultKeys); + } + + + return { + searchResultList, + filterFunctions, + onFunctionSearch + }; +} diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 33e3d75ef37..17d96bae879 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -14,12 +14,18 @@ * limitations under the License. * defination */ -import { defineComponent, onMounted, ref, SetupContext, watch } from 'vue'; +import { computed, defineComponent, onMounted, ref, SetupContext, watch } from 'vue'; import { ExpressionEditorProps, expressionEditorProps } from './expression-editor.props'; import { FLayout, FLayoutPane } from "../../../components/layout"; +import { commonFunctions } from "./composition/functions-data"; + import ExpressionCode from './components/expression-code.component'; -import FExpressionEditor from './components/functions/common-functions.component'; +import EntityVariable from './components/entities-variable/entity-variable.component'; +import FFunctionList from './components/functions/common-functions.component'; + +import { useExpression } from './composition/use-expression'; +import { useSearchFunction } from './composition/use-search-function'; export default defineComponent({ name: 'FExpressionEditor', @@ -27,8 +33,70 @@ export default defineComponent({ emits: [] as (string[] & ThisType) | undefined, setup(props: ExpressionEditorProps, context: SetupContext) { const elementRef = ref(); - - onMounted(() => { + const validateMessage = ref(props.validateMessage); + const modelValue = ref(props.modelValue); + const expressionEditorRef = ref(); + + const { getFunctionExpression, getContextVariableExpression, + resetFunctionItems, getFieldExpression, getExpressionCodeValue, + getExpressionTextValue } = useExpression(props, commonFunctions, props.variables); + + + const functionItems = ref(resetFunctionItems()); + + const { onFunctionSearch } = useSearchFunction(props, functionItems); + + + function onInsertFunction({$event, item}) { + const expression = getFunctionExpression(item); + expressionEditorRef.value?.insertText(expression); + } + + function onVariableItemDblClick({$event, item}) { + const expression = getContextVariableExpression(item); + expressionEditorRef.value?.insertText(expression); + } + + function onEntityItemDblClick({$event, item, entityCode}) { + const expression = getFieldExpression(item); + + let expressionText = `${entityCode}.${expression}`; + if (entityCode === expression) { + expressionText = expression; + } + expressionEditorRef.value?.insertText(`${expressionText}`); + } + + function getExpressionContext() { + return expressionEditorRef.value?.getContent(); + } + + function getExpressionValue() { + const displayText = expressionEditorRef.value?.getContent(); + return {value: getExpressionCodeValue(displayText), message: validateMessage.value}; + } + + const expressionDisplayText = ref(''); + + + function resetExpression() { + expressionEditorRef.value?.clearText(); + } + + onMounted(async () => { + if (modelValue.value) { + const ruleValue = JSON.parse(modelValue.value); + const { expr } = ruleValue; + if (expr) { + expressionDisplayText.value = await getExpressionTextValue(expr) || ''; + } + } + }); + + context.expose({ + getExpressionContext, + getExpressionValue, + resetExpression }); return () => { @@ -36,13 +104,24 @@ export default defineComponent({
    - + - - + +
    + +
    + {props.showMessage &&
    + 提示信息: +
    }
    - +
    diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts index ba04c8a80f4..33b8022f051 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts @@ -14,16 +14,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ExtractPropTypes, ref } from 'vue'; -import { createPropsResolver } from '../../dynamic-resolver'; -import { schemaMapper } from './schema/schema-mapper'; -import { schemaResolver } from './schema/schema-resolver'; -import expressionEditorSchema from './schema/expression-editor.schema.json'; +import { ExtractPropTypes, PropType, ref } from 'vue'; +import { DisabledFunction } from './composition/types'; + export const expressionEditorProps = { - + modelValue: { + type: String, + default: '' + }, + singleExpand: { + type: Boolean, + default: true + }, + entities: { + type: Array, + default: [] + }, + variables: { + type: Array, + default: [] + }, + disabledFunctions: { + type: Object as PropType, + default: null + }, + esprimaPath: { + type: String, + default: 'assets/esprima-config.json' + }, + showMessage: { + type: Boolean, + default: false + }, + validateMessage: { + type: String, + default: '' + } + } as Record; -export type ExpressionEditorProps = ExtractPropTypes; -export const propsResolver = createPropsResolver(expressionEditorProps, expressionEditorSchema, schemaMapper, schemaResolver); +export type ExpressionEditorProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx index 8477344e4e8..4000157de34 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx @@ -1,16 +1,41 @@ -import { defineComponent } from "vue"; +import { defineComponent, inject, ref } from "vue"; import FButtonEdit from '../../button-edit/src/button-edit.component'; -import { expressionTextboxProps } from "./expression-textbox.props"; +import { expressionTextboxProps, ExpressionTextboxProps } from "./expression-textbox.props"; import FExpressionEditor from './expression-editor.component'; - +import { F_NOTIFY_SERVICE_TOKEN, FNotifyService } from "../../notify"; +import { FMessageBoxService } from "../../../components/message-box"; +import { FLoadingService } from "@farris/ui-vue/components/loading"; export default defineComponent({ name: 'f-expression-textbox', props: expressionTextboxProps, - setup(props, context) { + setup(props: ExpressionTextboxProps, context) { + const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; + const loadingService: any | null = inject('FLoadingService'); + const buttonIcon = ''; + const modelValue = ref(props.modelValue); + + const entities = ref(props.entities); + const variables = ref(props.variables); + const editorRef = ref(); + const validateMessage = ref(''); + + function onSubmit() { + const {value: expressionValue, message} = editorRef.value.getExpressionValue(); + if (expressionValue) { + modelValue.value = expressionValue; + context.emit('update:modelValue', expressionValue); + if (props.onSubmitModal) { + const expressionModel = props.onSubmitModal({ expression: expressionValue, message }); + if (props.onExpressionChanged) { + props.onExpressionChanged(expressionModel); + } + } + } + } const modalOptions = { title: '表达式编辑器', @@ -23,6 +48,15 @@ export default defineComponent({ resizeable: true, draggable: true, buttons: [ + { + name: 'reset', + text: '清空', + class: 'btn btn-secondary mr-2', + handle: ($event: MouseEvent) => { + editorRef.value?.resetExpression(); + return false; + } + }, { name: 'cancel', text: '取消', @@ -36,18 +70,43 @@ export default defineComponent({ text: '确定', class: 'btn btn-primary', handle: async ($event: MouseEvent) => { + onSubmit(); return true; } } ] }; - function onBeforeOpen () {} + async function onBeforeOpen() { + if (props.beforeOpen) { + try { + loadingService?.show(); + const result = await props.beforeOpen({notifyService}); + if (result) { + entities.value = result.entities || {}; + variables.value = result.variables || {}; + validateMessage.value = result.message || ''; + loadingService?.clearAll(); + return true; + } + } catch (error) { + notifyService?.error({message: '获取数据失败!'}); + return false; + } finally { + loadingService?.clearAll(); + } + + } + + + return true; + } return () => { return
    - +
    ; } diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts index bcee56be586..5ea5ad4a046 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts @@ -1,3 +1,10 @@ +import { ExtractPropTypes, PropType } from "vue"; + +import { createPropsResolver } from '../../dynamic-resolver'; + +import schema from './schema/expression-editor.schema.json'; +import { DisabledFunction } from "./composition/types"; + export const expressionTextboxProps = { disabled: { type: Boolean, @@ -9,7 +16,7 @@ export const expressionTextboxProps = { }, enableClear: { type: Boolean, - default: false + default: true }, modelValue: { type: String, @@ -23,5 +30,45 @@ export const expressionTextboxProps = { type: Object, default: null }, - editorParams: {} -} + editorParams: {}, + singleExpand: { + type: Boolean, + default: true + }, + beforeOpen: { + type: Function, + default: () => { } + }, + onSubmitModal: { + type: Function, + default: () => { } + }, + entities: { + type: Array, + default: [] + }, + variables: { + type: Array, + default: [] + }, + disabledFunctions: { + type: Object as PropType, + default: null + }, + onExpressionChanged: { + type: Function, + default: () => { } + }, + esprimaPath: { + type: String, + default: 'assets/esprima-config.json' + }, + showMessage: { + type: Boolean, + default: false + } +} as Record; + + +export type ExpressionTextboxProps = ExtractPropTypes; +export const propsResolver = createPropsResolver(expressionTextboxProps, schema); \ No newline at end of file diff --git a/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json b/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json index bc52691acbe..61b59c01c9f 100644 --- a/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json +++ b/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json @@ -26,6 +26,50 @@ } }, "default": {} + }, + "beforeOpen": { + "type": "object", + "default": null + }, + "modelValue": { + "description": "The value of Expression Editor", + "type": "string", + "default": "" + }, + "variables": { + "description": "The variables of Expression Editor", + "type": "array", + "default": [] + }, + "entities": { + "description": "The entities of Expression Editor", + "type": "array", + "default": [] + }, + "onSubmitModal": { + "description": "The event of Expression Editor", + "type": "function", + "default": null + }, + "onExpressionChanged": { + "description": "The event of Expression Editor", + "type": "function", + "default": null + }, + "esprimaPath": { + "description": "The path of esprima", + "type": "string", + "default": "assets/esprima-config.json" + }, + "singleExpand": { + "description": "The singleExpand of Expression Editor", + "type": "boolean", + "default": true + }, + "showMessage": { + "description": "The showMessage of Expression Editor", + "type": "boolean", + "default": false } }, "required": [ diff --git a/packages/ui-vue/components/expression-editor/src/schema/schema-mapper.ts b/packages/ui-vue/components/expression-editor/src/schema/schema-mapper.ts deleted file mode 100644 index 97964aee23b..00000000000 --- a/packages/ui-vue/components/expression-editor/src/schema/schema-mapper.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { MapperFunction, resolveAppearance } from '../../../dynamic-resolver'; - -export const schemaMapper = new Map([ - ['appearance', resolveAppearance] -]); diff --git a/packages/ui-vue/components/expression-editor/src/schema/schema-resolver.ts b/packages/ui-vue/components/expression-editor/src/schema/schema-resolver.ts deleted file mode 100644 index b02bdf93eec..00000000000 --- a/packages/ui-vue/components/expression-editor/src/schema/schema-resolver.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { DynamicResolver } from "../../../dynamic-resolver"; - -export function schemaResolver(resolver: DynamicResolver, schema: Record, context: Record): Record { - return schema; -} diff --git a/packages/ui-vue/components/expression-editor/style.scss b/packages/ui-vue/components/expression-editor/style.scss index 9343f86d8e1..9770c4ab4b6 100644 --- a/packages/ui-vue/components/expression-editor/style.scss +++ b/packages/ui-vue/components/expression-editor/style.scss @@ -1,15 +1,31 @@ .expression-editor { border: 1px solid #cccccc; + .layout-border { + border: 1px solid #cccccc; + border-top: 0; + border-bottom: 0; + box-shadow: none!important; + } + + .expression-left { + .search-bar { + justify-content: center; + } + .layout-border { + border: 0; + } + } + .functions-list { .functions-type { - cursor: pointer; + overflow: hidden; - transition: max-height 0.2s ease-in-out; + transition: all 0.2s ease-in; &.open { - max-height: 1000px; + max-height: 1300px; } &.closed { @@ -18,9 +34,15 @@ .functions-type-name { + cursor: pointer; height: 28px; line-height: 28px; font-weight: bold; + + &:hover { + background: #f4f4f4; + border-radius: 6px; + } } li { @@ -31,7 +53,7 @@ .functions-item { &.selected { - background: #e4e4e4; + background: #dae9ff; border-radius: 6px; } @@ -50,5 +72,54 @@ border: 1px solid #cbcbcb; border-left: 0; border-bottom: 0; + color: rgb(70, 130, 180); + } + + .entity-variable { + ul { + list-style: none; + + li.list-group { + + overflow: hidden; + transition: all 0.2s ease-in; + + &.expand { + max-height: calc(100% - 32px); + } + &.collapse { + max-height: 32px; + } + + .title { + cursor: pointer; + border-bottom: 1px solid #d9d9d9; + justify-content: space-between; + background: #f7f8fb; + height: 32px; + min-height: 32px; + font-weight: bold; + line-height: 32px; + } + + .data-area { + background-color: white; + } + } + } } } + +/* 隐藏所有错误波浪线 */ +// .monaco-editor .squiggly-error { +// display: none !important; +// } + +/* 隐藏警告波浪线(如有需要) */ +// .monaco-editor .squiggly-warning { +// display: none !important; +// } + +// .monaco-editor .decorationsOverviewRuler{ +// display: none!important; +// } \ No newline at end of file diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index c8190863500..7b0d70217b2 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -20,7 +20,7 @@ export default defineComponent({ setup(props: FilterConditionEditorProps, context) { const repository = inject(props.repositoryToken); const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; - const loadingService: any | null = inject('FLoadingService'); + const loadingService: any | null = inject('FLoadingService'); if (notifyService) { notifyService.globalConfig = { position: 'top-center' }; diff --git a/packages/ui-vue/components/layout/src/components/layout-pane.component.tsx b/packages/ui-vue/components/layout/src/components/layout-pane.component.tsx index 43f8730230c..d37ec3d8bea 100644 --- a/packages/ui-vue/components/layout/src/components/layout-pane.component.tsx +++ b/packages/ui-vue/components/layout/src/components/layout-pane.component.tsx @@ -13,7 +13,7 @@ export default defineComponent({ const minWidth = ref(props.minWidth <= 0? 100: props.minWidth); const width = ref(props.width <=0 ? 100: props.width); - const height = ref(props.height<= 100? 100: props.height); + const height = ref(props.height<= 0? 100: props.height); const actualHeight = ref(Math.max(minHeight.value, height.value)); const actualWidth = ref(Math.max(minWidth.value, width.value)); diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index e90b1edceee..edec18a9e36 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -33,7 +33,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const dialog = this.getDialogPropertyConfig(propertyData); const pager = this.getPageConfig(propertyData.editor); const treeConfig = this.getTreePropConfig(propertyData.editor); - + const expressons = this.getExpressionConfig(propertyData, 'Field'); return { type: 'object', categories: { @@ -44,7 +44,8 @@ export class LookupPropertyConfig extends InputBaseProperty { treeConfig, eventsEditor, dialog, - pager + pager, + expressons } }; } diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts new file mode 100644 index 00000000000..00fc3e8162d --- /dev/null +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -0,0 +1,276 @@ +export interface RuleModel { + id: string, + type: 'compute' | 'dependency' | 'validate' | string, + value: string, + message?: string +} + +export interface ExpressionModel{ + target: string; + rules: Array; + targetType: string; +} + +export const getExpressionConverter = (targetType: 'Field'| string, ruleType?: string) => { + return { + convertFrom: (schema: Record, propertyKey: string, schemaService, componentId) => { + const expressionId = targetType === 'Field' ? schema.binding.field : componentId; + const rule = schemaService.getExpressionRuleValue(expressionId, ruleType || propertyKey); + return rule && rule.value || ''; + }, + convertTo: (schema: Record, propertyKey: string, propertyValue: any[], + schemaService, componentId + ) => { + schemaService.updateExpression(propertyValue); + } + }; +}; + +export class ExpressionProperty { + + private sessionVariables = [ + { + key: "CurrentSysOrgName", + name: "当前组织Name", + description: "当前组织Name" + }, + // { + // key: "CurrentSysOrgCode", + // name: "当前组织Code", + // description: "当前组织Code" + // }, + { + key: "CurrentSysOrgId", + name: "当前组织Id", + description: "当前组织Id" + }, + { + key: "CurrentUserName", + name: "当前用户Name", + description: "当前用户Name" + }, + { + key: "CurrentUserCode", + name: "当前用户Code", + description: "当前用户Code" + }, + { + key: "CurrentUserId", + name: "当前用户Id", + description: "当前用户Id" + }, + { + key: "CurrentLanguage", + name: "当前语言编号", + description: "当前登录的语言编号,例如简体中文返回'zh-CHS',英文返回'en',繁体中文'zh-CHT'" + } + ]; + + constructor(private formSchemaService: any) { + } + + private getExpressionRule(expressionId: any, rultType: string) { + const expressions = this.formSchemaService.getExpressions(); + if (!expressions) { + return ''; + } + const expressionItem = expressions.find(item => item.target === expressionId); + if (!expressionItem) { + return ''; + } + + const ruleItem = expressionItem.rules.find(item => item.type === rultType); + if (!ruleItem) { + return ''; + } + + return ruleItem; + } + + // 获取上下文表单变量 + private getContextFormVariables() { + const {module} = this.formSchemaService.getFormSchema(); + if (!module.viewmodels || module.viewmodels.length === 0) { + return []; + } + + const rootViewModelId = this.formSchemaService.getRootViewModelId(); + const viewModel = this.formSchemaService.getViewModelById(rootViewModelId); + + if (!viewModel || !viewModel.states || viewModel.states.length === 0) { + return []; + } + + const contextEntities: any = []; + viewModel.states.forEach(variable => { + if (variable.category === 'remote') { + contextEntities.push({ + key: variable.code, + name: variable.name, + description: variable.name + }); + } + }); + return contextEntities; + } + + private convertEntitiesToTreeData(fields: any[]) { + const treeData: any = []; + fields.forEach(element => { + // 关联表字段 / UDT字段 + let children = []; + if (element.type && element.type.fields && element.type.fields.length > 0) { + children = this.convertEntitiesToTreeData(element.type.fields); + + } + // 适配旧的帮助元数据没有bindingPath属性 + if (!element.bindingPath) { + element.bindingPath = element['parentPath'] ? element['parentPath'] + '.' + element.label : element.label; + } + treeData.push({ + data: element, + children, + expanded: true, + selectable: !children.length + }); + }); + return treeData; + } + + + private getEntitiesTreeData() { + const entities = this.formSchemaService.getSchemaEntities(); + if (!entities || entities.length === 0) { + return []; + } + + const mainTable = entities[0]; + if (mainTable.type && mainTable.type.fields) { + const childFields = this.convertEntitiesToTreeData(mainTable.type.fields); + const fields = [{ + data: { + id: mainTable.id, + name: mainTable.name, + bindingPath: mainTable.label + }, + children: childFields + }]; + + return { + entityCode: mainTable.label, + fields + }; + } + + return []; + } + + + private onBeforeOpenExpression(propertyData: any, expressionType: string, targetType: string) { + const expressionId = targetType === 'Field' ? propertyData.binding.field : propertyData.id; + const rule = this.getExpressionRule(expressionId, expressionType); + return { + message: expressionType === 'validate' && rule? rule.message : '', + entities: this.getEntitiesTreeData(), + variables: { + session: { + name: '系统变量', + items: this.sessionVariables + }, + forms: { + name: '表单变量', + items: this.getContextFormVariables() + } + } + }; + } + + private buildRule(targetId, expressionObject: Record, ruleType: string) { + const {expression: expressionValue, message} = expressionObject; + + return { + id: `${targetId}_${ruleType}`, + type: ruleType, + value: expressionValue, + message + }; + } + + private getExpressionData(): Array { + const { expressions } = this.formSchemaService.getFormSchema().module; + return expressions || []; + } + + private updateExpression(propertyData: any, targetType: 'Field'|'Button'|'Container', expressionObject: Record, ruleType: string) { + + const targetId = targetType === 'Field' ? propertyData.binding.field: propertyData.id; + + const newRule = this.buildRule(targetId, expressionObject, ruleType); + + const currentExpressiones = this.getExpressionData(); + let expressionItem = currentExpressiones.find((item: ExpressionModel) => { + return item.targetType === targetType && item.target === targetId; + }); + + if (expressionItem) { + const ruleItem = expressionItem.rules.find((rule) => rule.id === newRule.id); + if (ruleItem) { + ruleItem.value = newRule.value; + ruleItem.message = newRule.message; + } else { + expressionItem.rules = expressionItem.rules || []; + expressionItem.rules.push(newRule); + } + } else { + expressionItem = { + target: `${targetId}`, + rules: [newRule], + targetType: targetType + }; + + } + return expressionItem; + } + + private expressionNames = { + compute: '计算表达式', + dependency: '依赖表达式', + validate: '验证表达式' + }; + + private getExpressionEditorOptions(propertyData, targetType: 'Field'|'Button'|'Container', expressionTypes: string[]) { + return expressionTypes.reduce((expressions: Record, name: string) => { + expressions[name] = { + description: "", + title: this.expressionNames[name], + type: "string", + $converter: getExpressionConverter(targetType), + editor: { + type: "expression-editor", + singleExpand: false, + showMessage: name === 'validate', + beforeOpen: () => { + return this.onBeforeOpenExpression(propertyData, name, targetType); + }, + onSubmitModal: (expressionObject: any) => { + // const {expression: expressionValue, message} = expressionObject; + // const expressionString = JSON.stringify({ expr: expressionValue, sexpr: ""}); + return this.updateExpression(propertyData, targetType, expressionObject, name); + } + } + }; + + return expressions; + }, {}); + } + + getExpressionConfig(propertyData: any, type: 'Field'|'Button'|'Container', expressionTypes: string[] = ['compute', 'dependency', 'validate']) { + return { + description: "表达式", + title: "表达式", + properties: { + ...this.getExpressionEditorOptions(propertyData, type, expressionTypes) + } + }; + } +} diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts index ba57254841d..2bf86190799 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts @@ -11,6 +11,7 @@ import { import { useResponseLayoutEditorSetting } from "../../../../response-layout-editor/src/composition/converter/use-response-layout-editor-setting"; import { FormSchemaEntityField$Type, FormSchemaEntityFieldType$Type, FormVariable } from "@farris/ui-vue/components/common"; import { DgControl } from "../../../../designer-canvas"; +import { ExpressionProperty } from "./expression-property"; export class InputBaseProperty extends BaseControlProperty { public responseLayoutEditorFunction: UseResponseLayoutEditorSetting; @@ -29,6 +30,9 @@ export class InputBaseProperty extends BaseControlProperty { this.propertyConfig.categories['appearance'] = this.getAppearanceProperties(propertyData, componentInstance); // 编辑器 this.propertyConfig.categories['editor'] = this.getEditorProperties(propertyData); + + this.propertyConfig.categories['expressons'] = this.getExpressionConfig(propertyData, 'Field'); + return this.propertyConfig; } @@ -470,4 +474,8 @@ export class InputBaseProperty extends BaseControlProperty { } return false; } + + getExpressionConfig(propertyData: any, type: 'Field'|'Button'|'Container') { + return new ExpressionProperty(this.formSchemaUtils).getExpressionConfig(propertyData, type); + } } diff --git a/packages/ui-vue/components/tree-view/src/tree-view.component.tsx b/packages/ui-vue/components/tree-view/src/tree-view.component.tsx index 9b825ccc2fb..acf4c6a0990 100644 --- a/packages/ui-vue/components/tree-view/src/tree-view.component.tsx +++ b/packages/ui-vue/components/tree-view/src/tree-view.component.tsx @@ -15,7 +15,7 @@ import './tree-view.css'; export default defineComponent({ name: 'FTreeView', props: treeViewProps, - emits: ['outputValue', 'currentEvent', 'selectionChange', 'expandNode'] as (string[]) | undefined, + emits: ['outputValue', 'currentEvent', 'selectionChange', 'expandNode', 'dblclickNode'] as (string[]) | undefined, setup(props: TreeViewProps, context: SetupContext) { const rowHeight = props.rowOption?.height || 28; const treeContentRef = ref(); diff --git a/packages/ui-vue/components/tree-view/src/tree-view.props.ts b/packages/ui-vue/components/tree-view/src/tree-view.props.ts index a228992a69d..9b0333cc8e3 100644 --- a/packages/ui-vue/components/tree-view/src/tree-view.props.ts +++ b/packages/ui-vue/components/tree-view/src/tree-view.props.ts @@ -121,7 +121,8 @@ export const treeViewProps = { /** 虚拟化渲染数据 */ virtualized: { type: Boolean, default: false }, /** 是否出现省略号 */ - showEllipsis: { type: Boolean, default: false} + showEllipsis: { type: Boolean, default: false}, + } as Record; export type TreeViewProps = ExtractPropTypes; diff --git a/packages/ui-vue/demos/expression-editor/basic.vue b/packages/ui-vue/demos/expression-editor/basic.vue index 6924dc262ae..ae5fce950e8 100644 --- a/packages/ui-vue/demos/expression-editor/basic.vue +++ b/packages/ui-vue/demos/expression-editor/basic.vue @@ -1,6 +1,6 @@ -- Gitee From f26e95deac2c2e5a483f48165f7247ec490aaa47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 29 Mar 2025 13:33:34 +0800 Subject: [PATCH 096/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dpopover?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=B8=80=E4=BA=9B=E5=B7=B2=E7=9F=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/popover/src/popover.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/popover/src/popover.css b/packages/ui-vue/components/popover/src/popover.css index 0942966217f..402a0333de8 100644 --- a/packages/ui-vue/components/popover/src/popover.css +++ b/packages/ui-vue/components/popover/src/popover.css @@ -23,5 +23,5 @@ } .popover { - transition: all 0.12s ease-in; + transition: opacity 0.12s ease-in; } \ No newline at end of file -- Gitee From addaa6cc04ec598abb1ecdb3e156f0bf48e29a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 29 Mar 2025 13:44:12 +0800 Subject: [PATCH 097/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dpopover?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=B8=80=E4=BA=9B=E5=B7=B2=E7=9F=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../button-edit/src/components/popup-container.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/button-edit/src/components/popup-container.component.tsx b/packages/ui-vue/components/button-edit/src/components/popup-container.component.tsx index b68b82e1245..f77cee2edc1 100644 --- a/packages/ui-vue/components/button-edit/src/components/popup-container.component.tsx +++ b/packages/ui-vue/components/button-edit/src/components/popup-container.component.tsx @@ -12,7 +12,7 @@ export default function ( const { hidePopup, popoverRef } = popupComposition; return () => { - return Date: Mon, 31 Mar 2025 08:54:00 +0800 Subject: [PATCH 098/156] =?UTF-8?q?fix:=20=E6=9D=A1=E4=BB=B6=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E6=98=BE=E7=A4=BA=E6=96=87=E6=9C=AC=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/composition/use-condition-data.ts | 9 ++++++++- .../src/filter-condition-editor.component.tsx | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 87e801be81c..9226639767a 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -5,8 +5,15 @@ export function useConditionData(props, conditions) { const activeRow = ref({ index: -1, condition: null }); const displayText = computed(() => { + if (props.displayText) { + return props.displayText; + } + + if (typeof props.modelValue === 'string') { + return props.modelValue; + } const count = (props.modelValue || []).length; - return props.displayText || `共 ${count} 项`; + return `共 ${count} 项`; }); const fieldName = props.editorType !== 'sort' ? 'filterField' : 'sortField'; diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index 3901f2e8281..b363b1653b6 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -33,7 +33,7 @@ export default defineComponent({ const conditions = ref([]); const originalConditions = ref([]); - const { onAddFilter, onClear, onMoveBottom, onMoveNext, onMovePrev, onMoveTop, + const { displayText, onAddFilter, onClear, onMoveBottom, onMoveNext, onMovePrev, onMoveTop, onInsert, onRemove, activeRow, onSelectRow, canClear, canMove, validateCondition } = useConditionData(props, conditions); @@ -41,6 +41,7 @@ export default defineComponent({ return props.editorType === 'sort' ? '排序条件编辑器' : '过滤条件编辑器'; }); + function renderEditGrid() { if (props.editorType === 'sort') { return { return Date: Mon, 31 Mar 2025 09:13:49 +0800 Subject: [PATCH 099/156] =?UTF-8?q?fix:=20combo-tree:=20=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../combo-tree/src/components/tree-container.component.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui-vue/components/combo-tree/src/components/tree-container.component.tsx b/packages/ui-vue/components/combo-tree/src/components/tree-container.component.tsx index f61636e1b74..faf644703eb 100644 --- a/packages/ui-vue/components/combo-tree/src/components/tree-container.component.tsx +++ b/packages/ui-vue/components/combo-tree/src/components/tree-container.component.tsx @@ -29,8 +29,7 @@ export default defineComponent({ return [{ field: props.textField, title: '', dataType: 'string', - formatter: props.formatter, - width: 400 + formatter: props.formatter }]; }); -- Gitee From 4ea607fb3d4c85a95e123ee4a503f8e0cf7f1e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 31 Mar 2025 15:51:20 +0800 Subject: [PATCH 100/156] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96lookup?= =?UTF-8?q?=E6=A0=91=E7=BB=93=E6=9E=84=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-http.ts | 22 +++++++++++++++ .../lookup/src/composition/use-navigation.tsx | 7 +++-- .../composition/use-treegrid-row-options.ts | 27 +++---------------- .../lookup/src/composition/use-treegrid.tsx | 8 +++--- .../components/lookup/src/lookup.props.ts | 2 +- .../property-config/lookup.property-config.ts | 19 ++++++++----- 6 files changed, 48 insertions(+), 37 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index afee075dca1..f2ba3294cbb 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -313,10 +313,32 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { }); } + function setTreeNodeExpandStatus(treeNodes: any) { + treeNodes.forEach((item: any) => { + item.collapse = item.expanded == null ? false: !item.expanded; + if (item.children && item.children.length) { + setTreeNodeExpandStatus(item.children); + } + }); + } + + async function loadData(event: any, callback: (e: LookupHttpResult) => void) { const params = buildQueryParams(event) as Partial; const loadingInstance = loadingService?.show(); let httpResult = await getData(params); + + if (isTree()) { + let treeItems = httpResult.items; + if (httpResult.navigation) { + treeItems = httpResult.navigation.items; + } + + if (treeItems && treeItems.length) { + setTreeNodeExpandStatus(treeItems); + } + } + if (props.beforeLoadData) { httpResult = await props.beforeLoadData({data: httpResult}); } diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index 9054db2af79..ed2cf12b6b3 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -125,6 +125,8 @@ export function useNavigation(props: LookupProps, context) { context.emit("pageSizeChanged", params); } + const hierarchy = { collapseField: 'collapse' }; + function renderLeftTreeGrid() { return ; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts index 011ab8e572c..ee6ec8bc8d2 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts @@ -1,37 +1,16 @@ -import { RowOptions, VisualData } from "@farris/ui-vue/components/data-view"; +import { VisualData } from "@farris/ui-vue/components/data-view"; export const LOOKUP_TREEROW_OPTIONS = Symbol('LOOKUP_TREEROW_OPTIONS'); -function shoudExpand(expandLevel: number, layer: number) { - if (expandLevel === -1) { - // -1 全展开 - return true; - } else if (expandLevel === 0) { - // 0 为不展开 - return false ; - } else { - // 没有启用分层加载,通过展开层级确定是否展开该节点 - return layer <= expandLevel; - } -} - export function useTreeRowOptions(lookupOptions: any, isNavigation = false) { function customRowStatus(visualData: VisualData) { - if (visualData.collapse === undefined) { - if (lookupOptions.expandLevel !== undefined && lookupOptions.expandLevel !== 0) { - visualData.collapse = !shoudExpand(lookupOptions.expandLevel, visualData.raw.layer); - } else { - visualData.collapse = !visualData.raw.expanded; - } - } - if (visualData.raw.addtional || visualData.raw.selectable === false) { visualData.disabled = true; } - const treeinfo = isNavigation? lookupOptions.navTreeInfo : lookupOptions.treeInfo; + const treeinfo = isNavigation ? lookupOptions.navTreeInfo : lookupOptions.treeInfo; if (treeinfo.onlySelectLeaf === 'yes') { visualData.disabled = !visualData.raw.leaf; @@ -40,5 +19,5 @@ export function useTreeRowOptions(lookupOptions: any, isNavigation = false) { return visualData; } - return {customRowStatus}; + return { customRowStatus }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index cd87887a181..060e666932d 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -83,10 +83,12 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { const hierarchy = { - cascadeOption: { autoCheckChildren: false, autoCheckParent: false } }; + cascadeOption: { autoCheckChildren: false, autoCheckParent: false }, + collapseField: 'collapse' + }; function onExpandNode(node: any) { - return console.log(node); + // return console.log(node); } function renderTreeGrid() { @@ -101,7 +103,7 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { columnOption={columnOptions} selection={selectionOptions} showBorder={true} - virtualized={true} + virtualized={false} displayField={'code'} rowOption={treeRowOptions} hierarchy={hierarchy} diff --git a/packages/ui-vue/components/lookup/src/lookup.props.ts b/packages/ui-vue/components/lookup/src/lookup.props.ts index 0df0c892456..fdd84ffa12a 100644 --- a/packages/ui-vue/components/lookup/src/lookup.props.ts +++ b/packages/ui-vue/components/lookup/src/lookup.props.ts @@ -64,7 +64,7 @@ export const lookupProps = { enableMultiFieldSearch: { type: Boolean, default: false }, treeToList: { type: Boolean, default: false }, navTreeToList: { type: Boolean, default: false }, - loadTreeDataType:{ type: String as PropType, default: LoadTreeDataType.default }, + loadTreeDataType:{ type: String as PropType, default: LoadTreeDataType.all}, enableToSelect: { type: Boolean, default: true }, customData: { type: Object, default: null }, modelValue: { type: String, default: '' }, diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 2c56999dc14..074e3f2fe44 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -489,20 +489,23 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDialogOptionsConverter }, width: { - description: "", - title: "窗口宽度", + description: "窗口宽度", + title: "宽度", type: "number", $converter: lookupDialogOptionsConverter, editor: { - ...this.numberEditor + ...this.numberEditor, + min: 300 } }, height: { - title: "窗口高度", + description: "窗口高度", + title: "高度", type: "number", $converter: lookupDialogOptionsConverter, editor: { - ...this.numberEditor + ...this.numberEditor, + min: 300 } }, navigatorWidth: { @@ -564,8 +567,10 @@ export class LookupPropertyConfig extends InputBaseProperty { } private getPageConfig(editorOptions: any) { + const disablePager = !editorOptions.pagination?.enable; + return { - hide: this.getDisplayType(editorOptions) === 'TREELIST' || !editorOptions.helpId, + hide: this.getDisplayType(editorOptions) === 'TREELIST' || !editorOptions.helpId || disablePager, description: "分页配置", title: "分页", properties: { @@ -746,7 +751,7 @@ export class LookupPropertyConfig extends InputBaseProperty { expandLevel: { description: "默认展开层级: 0: 不展开; -1: 全部展开;>0: 展开到指定级数 ", $converter: lookupDefaultConverter, - title: "默认展开级别", + title: "默认展开层级", type: "number", visible: this.showLoadType(editorOptions), editor: { -- Gitee From 4b13013f140850ea82b52101791230e88cd9564b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 31 Mar 2025 16:14:13 +0800 Subject: [PATCH 101/156] =?UTF-8?q?fix:=20lookup=E6=89=93=E5=BC=80?= =?UTF-8?q?=E5=89=8D=E4=BA=8B=E4=BB=B6=E5=8F=82=E6=95=B0=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/composition/types.ts | 2 +- packages/ui-vue/components/lookup/src/composition/use-dialog.ts | 2 +- .../ui-vue/components/lookup/src/schema/callback-resolvers.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 56cbcb1fbdc..0cb019aeead 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -41,7 +41,7 @@ export interface PagerChangeParams{ export type LookupIdValueType = string | number | null; -export type ShouldContinueResult = {showDialog: boolean; message?: string; data?: any} | boolean; +export type ShouldContinueResult = {canOpen: boolean; message?: string; data?: any} | boolean; export type CanSelectResult = {canSelect: boolean; message?: string} | boolean; export type BeforeOpenDialogFunction = (params?: any) => Promise; diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index d64c075792c..8be56868212 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -255,7 +255,7 @@ export function useDialog( } if (typeof result === 'object') { - if (!result.showDialog) { + if (!result.canOpen) { shouldContinue = false; if (result.message) { diff --git a/packages/ui-vue/components/lookup/src/schema/callback-resolvers.ts b/packages/ui-vue/components/lookup/src/schema/callback-resolvers.ts index e935e543bd3..e8e5de48684 100644 --- a/packages/ui-vue/components/lookup/src/schema/callback-resolvers.ts +++ b/packages/ui-vue/components/lookup/src/schema/callback-resolvers.ts @@ -4,7 +4,7 @@ import { LookupHttpResult } from "../composition/types"; export function createLookupCallbackResolver() { function resolve(viewSchema: Record, caller: Caller) { const callbacks: Record = {}; - callbacks.dictPicking = (context: { customData: any, options: any; }): Promise => { + callbacks.dictPicking = (context: { customData: any, options: any; }): Promise => { return caller.call('dictPicking', [context, viewSchema]); }; callbacks.beforeLoadData = (data: any): Promise => { -- Gitee From c2fa7ad5103dc3956adecd80e8a0d74c91a5a86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 31 Mar 2025 16:38:04 +0800 Subject: [PATCH 102/156] =?UTF-8?q?feature:=20lookup=E6=A0=91=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E6=95=B0=E6=8D=AE=E5=BC=80=E5=90=AF=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui-vue/components/lookup/src/composition/use-navigation.tsx | 2 +- .../ui-vue/components/lookup/src/composition/use-treegrid.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index ed2cf12b6b3..76ce9f078f5 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -135,7 +135,7 @@ export function useNavigation(props: LookupProps, context) { rowNumber={{ enable: false }} columnOption={columnOptions} selection={selectionOptions} - virtualized={false} + virtualized={true} showBorder={true} rowOption={treeRowOptions} hierarchy={hierarchy} diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index 060e666932d..00c51ae42c1 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -103,7 +103,7 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { columnOption={columnOptions} selection={selectionOptions} showBorder={true} - virtualized={false} + virtualized={true} displayField={'code'} rowOption={treeRowOptions} hierarchy={hierarchy} -- Gitee From e51cc3dd836a48c53048be77b5f9aca4b92e9cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 31 Mar 2025 19:49:51 +0800 Subject: [PATCH 103/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E7=A7=BB=E9=99=A4=E4=B8=8D=E6=94=AF=E6=8C=81=E7=9A=84?= =?UTF-8?q?=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 074e3f2fe44..222cbf672d1 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -45,7 +45,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const pager = this.getPageConfig(propertyData.editor); const treeConfig = this.getTreePropConfig(propertyData.editor); const expressons = this.getExpressionConfig(propertyData, 'Field', - ['compute', 'dependency', 'validate', 'dataPicking'], + ['dependency', 'validate', 'dataPicking'], (rule: any) => { if (rule && rule.value.trim()) { propertyData.dictPickingExpressionId = rule.id; @@ -768,7 +768,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const self = this; const events = LookupEvents; - this.appendFieldValueChangeEvents(propertyData, events); + // this.appendFieldValueChangeEvents(propertyData, events); const initialData = self.eventsEditorUtils['formProperties'](propertyData, self.viewModelId, events); const properties = {}; -- Gitee From 60095961dab880db2d5ad7068978ceacbd0c51be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 31 Mar 2025 20:05:36 +0800 Subject: [PATCH 104/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E7=A7=BB=E9=99=A4=E4=B8=8D=E6=94=AF=E6=8C=81=E7=9A=84?= =?UTF-8?q?=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 222cbf672d1..c941cb831a4 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -44,8 +44,10 @@ export class LookupPropertyConfig extends InputBaseProperty { const dialog = this.getDialogPropertyConfig(propertyData); const pager = this.getPageConfig(propertyData.editor); const treeConfig = this.getTreePropConfig(propertyData.editor); + + // 'compute', 'dependency', const expressons = this.getExpressionConfig(propertyData, 'Field', - ['dependency', 'validate', 'dataPicking'], + ['validate', 'dataPicking'], (rule: any) => { if (rule && rule.value.trim()) { propertyData.dictPickingExpressionId = rule.id; -- Gitee From 026353516df5f35734a74bed4ecb26d67e47765c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 1 Apr 2025 11:40:03 +0800 Subject: [PATCH 105/156] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E7=BC=96=E8=BE=91=E5=99=A8=E6=95=B0=E6=8D=AE=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/composition/use-condition-data.ts | 2 +- .../src/property-config/lookup.property-config.ts | 11 ++++++++++- .../modal/src/composition/modal.service.tsx | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 9226639767a..cf3e2e7ed4d 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -171,7 +171,7 @@ export function useConditionData(props, conditions) { // 检查关系连接符 const emptyRelations = conditions.value .map((condition: any, index) => { - if (condition.relation === "" + FilterRelation.Empty) { + if ('' + condition.relation === "" + FilterRelation.Empty) { return { index, filter: condition }; } return null; diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index c941cb831a4..aaa000a7207 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -30,11 +30,13 @@ export class LookupPropertyConfig extends InputBaseProperty { private readonlyEditor: any = { ...this.comboListEditor, editable: true }; private visibleEditor: any = { ...this.comboListEditor, editable: false }; private requiredEditor: any = { ...this.comboListEditor, editable: false }; + private freeInputEditor: any = { ...this.comboListEditor, editable: false }; getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { this.readonlyEditor = this.getPropertyEditorParams(propertyData, [], 'readonly'); this.visibleEditor = this.getPropertyEditorParams(propertyData, [], 'visible'); this.requiredEditor = this.getPropertyEditorParams(propertyData, ['Const', 'Variable', 'StateMachine', 'Expression'], 'required'); + this.freeInputEditor = this.getPropertyEditorParams(propertyData, ['Const', 'Variable'], 'allowFreeInput'); const basic = this.getBasicProperties(propertyData, componentInstance); const behavior = this.getBehaviorConfig(propertyData); @@ -170,7 +172,7 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "任意输入", type: "boolean", $converter: lookupDefaultConverter, - editor: this.comboListEditor, + editor: this.freeInputEditor, visible: !!editorOptions.editable }, enableClear: { @@ -393,6 +395,13 @@ export class LookupPropertyConfig extends InputBaseProperty { } } }, + enableToSelect: { + description: "数据加载后是否选中现有值", + $converter: lookupDefaultConverter, + title: "选中已选值", + type: "boolean", + editor: this.comboListEditor, + }, multiSelect: { description: "启用多选", $converter: lookupDefaultConverter, diff --git a/packages/ui-vue/components/modal/src/composition/modal.service.tsx b/packages/ui-vue/components/modal/src/composition/modal.service.tsx index 24506a08a71..a8c2eef14c5 100644 --- a/packages/ui-vue/components/modal/src/composition/modal.service.tsx +++ b/packages/ui-vue/components/modal/src/composition/modal.service.tsx @@ -120,11 +120,11 @@ export default class ModalService { }; if (winWidth < width) { - width = winWidth; + width = winWidth - 14; } if (winHeight < height) { - height = winHeight; + height = winHeight - 14; } return { -- Gitee From 35f9d20099ca0bd7224795cbdd0995de3c99f906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 1 Apr 2025 16:08:27 +0800 Subject: [PATCH 106/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4Lookup?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converters/lookup-property.converter.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index e480cb8b429..b866a1da897 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -175,11 +175,8 @@ export const lookupDialogOptionsConverter = { export const lookupPaginationConverter = { convertFrom: (schema: Record, propertyKey: string) => { const options = schema.editor.pagination || {}; - if (propertyKey === 'enable') { - return options[propertyKey] || true; - } - if (propertyKey === 'showLimits') { - return options[propertyKey] || true; + if (propertyKey === 'enable' || propertyKey === 'showLimits') { + return options[propertyKey] == null ? false : options[propertyKey]; } if (propertyKey === 'sizeLimits') { -- Gitee From 47acc96bba845ea4b5cc7507bd81a0ecb933fd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 1 Apr 2025 16:47:59 +0800 Subject: [PATCH 107/156] =?UTF-8?q?feature:=20=E9=AA=8C=E8=AF=81=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E6=96=B0=E5=A2=9E=E6=8E=A7=E4=BB=B6ID?= =?UTF-8?q?=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../composition/entity/expression-property.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 7795489d714..0d3985a72eb 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -1,8 +1,10 @@ export interface RuleModel { - id: string, - type: 'compute' | 'dependency' | 'validate' | 'visable' | 'readonly' | 'require' | string, - value: string, - message?: string + id: string; + type: 'compute' | 'dependency' | 'validate' | 'visable' | 'readonly' | 'require' | string; + value: string; + message?: string; + elementId?: string; + messageType?: string; } export interface ExpressionModel { @@ -208,15 +210,21 @@ export class ExpressionProperty { return data; } - private buildRule(targetId, expressionObject: Record, ruleType: string) { + private buildRule(targetId, expressionObject: Record, ruleType: string, controlId?: string) { const { expression: expressionValue, message, messageType } = expressionObject; - return { + const rule: RuleModel = { id: `${targetId}_${ruleType}`, type: ruleType, value: expressionValue, message, messageType }; + + if (ruleType === 'validate' && controlId) { + rule.elementId = controlId; + } + + return rule; } private getExpressionData(): Array { @@ -228,7 +236,7 @@ export class ExpressionProperty { targetType: 'Field' | 'Button' | 'Container', expressionObject: Record, ruleType: string) { const targetId = targetType === 'Field' ? propertyData.binding.field : propertyData.id; - const newRule = this.buildRule(targetId, expressionObject, ruleType); + const newRule = this.buildRule(targetId, expressionObject, ruleType, propertyData.type === 'form-group' ?propertyData.id: ''); const currentExpressiones = this.getExpressionData(); let expressionItem = currentExpressiones.find((item: ExpressionModel) => { @@ -246,6 +254,10 @@ export class ExpressionProperty { } else { ruleItem.value = newRule.value; ruleItem.message = newRule.message; + + if (ruleType === 'validate' && propertyData.type === 'form-group') { + ruleItem.elementId = propertyData.id; + } } } else { if (isValueEmpty(newRule)) { -- Gitee From 806e2cfecdaf4680de26e8c487c3bc9bed428e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 1 Apr 2025 19:02:11 +0800 Subject: [PATCH 108/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=97=B6=E5=88=97=E8=A1=A8=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E4=B8=BAlookup=E6=97=B6=E6=94=AF=E6=8C=81=E7=9A=84=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property-config/lookup.property-config.ts | 26 +++++++++++-------- .../composition/entity/expression-property.ts | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index aaa000a7207..02f3fe366a7 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -32,6 +32,20 @@ export class LookupPropertyConfig extends InputBaseProperty { private requiredEditor: any = { ...this.comboListEditor, editable: false }; private freeInputEditor: any = { ...this.comboListEditor, editable: false }; + getExpressionConfig(propertyData: any, type: 'Field' | 'Button' | 'Container') { + return new ExpressionProperty(this.formSchemaUtils).getExpressionConfig( + propertyData, + 'Field', + ['validate', 'dataPicking'], + (rule: any) => { + if (rule && rule.value.trim() && rule.type === 'dataPicking') { + propertyData.dictPickingExpressionId = rule.id; + } else { + delete propertyData.dictPickingExpressionId; + } + }); + } + getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { this.readonlyEditor = this.getPropertyEditorParams(propertyData, [], 'readonly'); this.visibleEditor = this.getPropertyEditorParams(propertyData, [], 'visible'); @@ -48,17 +62,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const treeConfig = this.getTreePropConfig(propertyData.editor); // 'compute', 'dependency', - const expressons = this.getExpressionConfig(propertyData, 'Field', - ['validate', 'dataPicking'], - (rule: any) => { - if (rule && rule.value.trim()) { - propertyData.dictPickingExpressionId = rule.id; - } else { - // propertyData.dictPickingExpressionId = ''; - delete propertyData.dictPickingExpressionId; - } - } - ); + const expressons = this.getExpressionConfig(propertyData, 'Field'); return { diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 0d3985a72eb..a2e5bfe72bf 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -1,6 +1,6 @@ export interface RuleModel { id: string; - type: 'compute' | 'dependency' | 'validate' | 'visable' | 'readonly' | 'require' | string; + type: 'compute' | 'dependency' | 'validate' | 'visable' | 'readonly' | 'require' | 'dataPicking' | string; value: string; message?: string; elementId?: string; -- Gitee From 24269f00bbe27b0c5a6ce729cdc3e4640c6e4490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 2 Apr 2025 08:58:01 +0800 Subject: [PATCH 109/156] =?UTF-8?q?fix:=20lookup=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 02f3fe366a7..864f25fc0a8 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -546,8 +546,8 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDialogOptionsConverter }, resizeable: { - description: "允许调整大小", - title: "允许调整大小", + description: "允许鼠标拖拽窗口边缘调整尺寸", + title: "调整窗口尺寸", type: "boolean", $converter: lookupDialogOptionsConverter }, -- Gitee From 97b2dd52f45e623dd88a3011117631147afe312a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 2 Apr 2025 13:35:29 +0800 Subject: [PATCH 110/156] =?UTF-8?q?fix:=20lookup=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/lookup/src/composition/types.ts | 1 + .../lookup/src/composition/use-dialog.ts | 12 ++++++++---- .../property-config/lookup.property-config.ts | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 0cb019aeead..e510c84b9d6 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -304,4 +304,5 @@ export interface LookupDialogOptions { draggable?: boolean; resizeable?: boolean; enableEsc?: boolean; + rememberSize?: boolean; }; diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index 8be56868212..e3d3e40fbbe 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -127,7 +127,7 @@ export function useDialog( async function submitDialog() { const { shouldUpdate, message } = await handleSubmitValidation(); if (!shouldUpdate) { - if (message) { + if (message) { notifyService?.warning({ message, ...NOTIFY_OPTIONS }); } return false; @@ -166,6 +166,10 @@ export function useDialog( const { width, height, minHeight, minWidth } = getDefaultDialogSize(); + const dialogDraggable = dialogOptions?.draggable == null ? true : dialogOptions?.draggable; + const dialogResizeable = dialogDraggable && (dialogOptions?.resizeable == null ? true : dialogOptions?.resizeable); + dialogOptions.rememberSize = dialogOptions.rememberSize && dialogResizeable; + const modalOptions = { title: dialogOptions?.title, fitContent: false, @@ -175,8 +179,8 @@ export function useDialog( width, minWidth, minHeight, - resizeable: dialogOptions?.resizeable == null ? true : dialogOptions?.resizeable, - draggable: dialogOptions?.draggable == null ? true : dialogOptions?.draggable, + resizeable: dialogResizeable, + draggable: dialogDraggable, enableEsc: dialogOptions?.enableEsc == null ? true : dialogOptions?.enableEsc, closedCallback: ($event: Event, closeFrom: string) => { const emitParams: any = { type: dialogCloseType.value, button: $event?.target }; @@ -208,7 +212,7 @@ export function useDialog( }, showButtons: false, resizeHandle: ($event: any) => { - if (props.dialog?.rememberSize) { + if (dialogOptions.rememberSize) { dialogSize.value = $event; const { width, height } = $event.newSize.size; userDataService.setDialogSize({ width: Math.round(width), height: Math.round(height) }); diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 864f25fc0a8..a746bb15a71 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -532,24 +532,26 @@ export class LookupPropertyConfig extends InputBaseProperty { ...this.numberEditor } }, - rememberSize: { - description: "记录窗口尺寸", - title: "记录窗口尺寸", - type: "boolean", - $converter: lookupDialogOptionsConverter, - visible: !!propertyData.editor.enableUserData - }, draggable: { description: "允许拖拽", title: "允许拖拽", type: "boolean", + refreshPanelAfterChanged: true, $converter: lookupDialogOptionsConverter }, resizeable: { description: "允许鼠标拖拽窗口边缘调整尺寸", title: "调整窗口尺寸", type: "boolean", - $converter: lookupDialogOptionsConverter + $converter: lookupDialogOptionsConverter, + visible: !!propertyData.editor?.dialog?.draggable + }, + rememberSize: { + description: "记录窗口尺寸", + title: "记录窗口尺寸", + type: "boolean", + $converter: lookupDialogOptionsConverter, + visible: !!propertyData.editor.enableUserData && !!propertyData.editor?.dialog?.draggable }, enableEsc: { description: "允许ESC关闭", -- Gitee From e0909fcb63daf10decedebb66df42d2d417c4a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 2 Apr 2025 15:25:58 +0800 Subject: [PATCH 111/156] =?UTF-8?q?fix:=20=E5=88=97=E8=A1=A8Lookup?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E9=9A=90=E8=97=8F=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property-config/lookup.property-config.ts | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 335adce8bfe..63025b5b8d4 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -64,20 +64,24 @@ export class LookupPropertyConfig extends InputBaseProperty { // 'compute', 'dependency', const expressons = this.getExpressionConfig(propertyData, 'Field'); + const categories: any = { + basic, + appearance, + behavior, + lookup, + treeConfig, + dialog, + pager, + expressons + }; + + if (propertyData.type === 'form-group') { + categories.eventsEditor = eventsEditor; + } return { type: 'object', - categories: { - basic, - appearance, - behavior, - lookup, - treeConfig, - eventsEditor, - dialog, - pager, - expressons - } + categories }; } getGridFieldEdtiorPropConfig(propertyData: any) { -- Gitee From 33a23e9aacca9bc9d8703a4d43e16a729cd9e23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 3 Apr 2025 11:22:34 +0800 Subject: [PATCH 112/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dmodal=E7=A6=81?= =?UTF-8?q?=E7=94=A8=E6=8B=96=E6=8B=BD=E5=90=8E=E6=9C=80=E5=A4=A7=E5=8C=96?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/types.ts | 16 ++--------- .../lookup/src/composition/use-http.ts | 20 ++----------- .../composition/use-treegrid-row-options.ts | 2 +- .../components/lookup/src/lookup.props.ts | 4 +-- .../converters/lookup-property.converter.ts | 28 +++++++++++++------ .../property-config/lookup.property-config.ts | 17 ++--------- .../lookup/src/schema/lookup.schema.json | 4 +-- .../modal/src/composition/use-resizeable.tsx | 4 ++- .../components/modal/src/modal.component.tsx | 2 -- 9 files changed, 36 insertions(+), 61 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index e510c84b9d6..23cde836590 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -22,15 +22,8 @@ export enum LookupDisplayType { } export enum LoadTreeDataType { - default = 'default', - all ='loadall', - async = 'layerload' -} - -export enum OnlySelectLeaf { - default = 'default', - yes = 'yes', - no = 'no' + all ='all', + async = 'async' } export interface PagerChangeParams{ @@ -209,11 +202,8 @@ export interface TreeInfo { isDetailField?: string; /** * 只允许选择叶子节点 - * - default: 应用服务器端设置,如服务器未设置,功能同 `no` - * - `yes`: 服务器端设置失效。仅允许选择叶子节点。 - * - `no`: 服务器端设置失效。所有节点均可选择。 */ - onlySelectLeaf?: boolean | ONLY_SELECT_LEAF; + onlySelectLeaf?: boolean; /** 树结构数据是否已初始化完成 */ treeDataIsInit?: boolean; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index f2ba3294cbb..04274bd70f5 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -11,7 +11,6 @@ import { TreeInfo, LookupDisplayType, LoadTreeDataType, - OnlySelectLeaf } from "./types"; import { useSearchFields } from "./use-search-fields"; import { LookupStates, useLookupState } from "./use-state"; @@ -58,7 +57,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { if (resposneData) { const { layerType, dataField, parentField, pathField, layerField, isDetailField, loadDataType, - onlySelectLeaf } = resposneData; + } = resposneData; const treeInfo: TreeInfo = { layerType, dataField, @@ -70,21 +69,8 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { }; const { onlySelectLeaf: selectLeaf, loadTreeDataType } = lookupOptions; - if (typeof selectLeaf === 'boolean') { - treeInfo.onlySelectLeaf = selectLeaf? OnlySelectLeaf.yes: OnlySelectLeaf.no; - } else { - if (selectLeaf === OnlySelectLeaf.default) { - treeInfo.onlySelectLeaf = onlySelectLeaf ? OnlySelectLeaf.yes: OnlySelectLeaf.no; - } else { - treeInfo.onlySelectLeaf = selectLeaf; - } - } - - if (loadTreeDataType === LoadTreeDataType.default) { - lookupOptions.loadTreeDataType = loadDataType === 'all' ? LoadTreeDataType.all: LoadTreeDataType.async; - } else { - treeInfo.loadDataType = loadTreeDataType === LoadTreeDataType.all? 'all': 'async'; - } + treeInfo.onlySelectLeaf = selectLeaf; + treeInfo.loadDataType = loadTreeDataType; if (isNavigation) { lookupOptions.navTreeInfo = Object.assign(lookupOptions.navTreeInfo || {}, treeInfo); diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts index ee6ec8bc8d2..328c3877d94 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid-row-options.ts @@ -12,7 +12,7 @@ export function useTreeRowOptions(lookupOptions: any, isNavigation = false) { const treeinfo = isNavigation ? lookupOptions.navTreeInfo : lookupOptions.treeInfo; - if (treeinfo.onlySelectLeaf === 'yes') { + if (treeinfo.onlySelectLeaf) { visualData.disabled = !visualData.raw.leaf; } diff --git a/packages/ui-vue/components/lookup/src/lookup.props.ts b/packages/ui-vue/components/lookup/src/lookup.props.ts index fdd84ffa12a..5a4656c33f4 100644 --- a/packages/ui-vue/components/lookup/src/lookup.props.ts +++ b/packages/ui-vue/components/lookup/src/lookup.props.ts @@ -6,7 +6,7 @@ import { schemaMapper } from './schema/schema-mapper'; import lookupSchema from './schema/lookup.schema.json'; import { schemaResolver } from './schema/schema-resolver'; import { BeforeOpenDialogFunction, BeforeSubmitFunction, CallBackFunction, LoadTreeDataType, - LookupDisplayType, LookupIdValueType, LookupPagination, OnlySelectLeaf, + LookupDisplayType, LookupIdValueType, LookupPagination, NavigationOptions, SearchField, TextChangedType, BeforeLoadData, CascadeOptions, @@ -75,7 +75,7 @@ export const lookupProps = { placeholder: { type: String, default: '请选择' }, loader: { type: Function, default: null }, allowFreeInput: { type: Boolean, default: false }, - onlySelectLeaf: { type: String as PropType, default: OnlySelectLeaf.default }, + onlySelectLeaf: { type: Boolean, default: false }, enableFullTree: { type: Boolean, default: true }, enableCascade: { type: Boolean, default: false }, showCascadeControl: { type: Boolean, default: false }, diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index b866a1da897..c8c6bc547e7 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -11,7 +11,7 @@ export function getPageList(limitStr) { } } return pageSizeList.map((item) => { - return {value: parseInt(item, 10)}; + return { value: parseInt(item, 10) }; }).sort((itemA, itemB) => itemA.value - itemB.value); } @@ -25,8 +25,12 @@ export const lookupDefaultConverter = { return schema.editor[propertyKey] || ','; } - if (propertyKey === 'loadTreeDataType' || propertyKey === 'onlySelectLeaf') { - return schema.editor[propertyKey] || 'default'; + if (propertyKey === 'onlySelectLeaf') { + return schema.editor[propertyKey] == null? false: schema.editor[propertyKey]; + } + + if (propertyKey === 'loadTreeDataType') { + return schema.editor[propertyKey] || 'all'; } return schema.editor[propertyKey]; @@ -74,13 +78,13 @@ export const lookupDataSourceConverter = { convertTo: (schema: Record, propertyKey: string, propertyValue: any[]) => { if (propertyValue && propertyValue.length > 0) { const datasource = propertyValue[0]; - const {name, id, metadataContent, code} = datasource; + const { name, id, metadataContent, code } = datasource; if (!schema.editor.dataSource) { schema.editor.dataSource = {}; } - schema.editor.dataSource.displayName = `${name}(${code})` ; + schema.editor.dataSource.displayName = `${name}(${code})`; schema.editor['helpId'] = id; const { displayType, idField, textField } = metadataContent; @@ -90,9 +94,15 @@ export const lookupDataSourceConverter = { schema.editor.dataSource.type = "ViewObject"; - const {pageInfo} = metadataContent.dataSource; + const { pageInfo, treeInfo } = metadataContent.dataSource; setPageInfo(schema.editor, pageInfo); + if (treeInfo) { + const { onlySelectLeaf, loadDataType } = treeInfo; + schema.editor.loadTreeDataType = loadDataType || 'all'; + schema.editor.onlySelectLeaf = onlySelectLeaf == null ? false: onlySelectLeaf; + } + if (!schema.editor.dataSource.uri) { schema.editor.dataSource.uri = generateSourceUri(schema.id); } @@ -126,7 +136,7 @@ export const lookupTextFieldConverter = { export const lookupDisplayTypeConverter = { convertFrom: (schema: Record, propertyKey: string) => { - return schema.editor.displayType? schema.editor.displayType.toUpperCase() : 'LIST'; + return schema.editor.displayType ? schema.editor.displayType.toUpperCase() : 'LIST'; }, convertTo: (schema: Record, propertyKey: string, propertyValue: any) => { schema.editor.displayType = propertyValue; @@ -152,10 +162,10 @@ export const lookupDialogOptionsConverter = { } if (propertyKey === 'rememberSize') { - return options[propertyKey] === undefined? !!schema.editor.enableUserData: options[propertyKey]; + return options[propertyKey] === undefined ? !!schema.editor.enableUserData : options[propertyKey]; } - if (propertyKey ==='navigatorWidth') { + if (propertyKey === 'navigatorWidth') { return options[propertyKey] || 300; } diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 63025b5b8d4..b5ada5159fa 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -710,9 +710,8 @@ export class LookupPropertyConfig extends InputBaseProperty { editor: { ...this.comboListEditor, data: [ - { value: 'default', text: '默认' }, - { value: 'laodall', text: '全部加载' }, - { value: 'layerload', text: '分层加载' } + { value: 'all', text: '全部加载' }, + { value: 'async', text: '分层加载' } ], textField: 'text', valueField: 'value' @@ -730,18 +729,8 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "仅选择叶子节点", $converter: lookupDefaultConverter, title: "仅选择叶子节点", - type: "string", + type: "boolean", visible: this.showOnlySelectLeaf(editorOptions), - editor: { - ...this.comboListEditor, - data: [ - { value: 'default', text: '默认' }, - { value: 'yes', text: '是' }, - { value: 'no', text: '否' } - ], - textField: 'text', - valueField: 'value' - } }, enableCascade: { description: "启用级联选择", diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index cd13a2ecf8c..e40ff65b4bc 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -198,11 +198,11 @@ }, "loadTreeDataType": { "type": "string", - "default": "default" + "default": "all" }, "onlySelectLeaf": { "type": "boolean", - "default": "default" + "default": false }, "enableFullTree": { "type": "boolean", diff --git a/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx b/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx index e23782f5926..ba93c061b9a 100644 --- a/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx +++ b/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx @@ -18,6 +18,8 @@ export function useResizeable(props: any, context: any) { const modalBounding = ref(); const resizedEventParam = ref(); + const resizeable = ref(props.resizeable); + const lastSize = ref(); const allowDrag = ref(props.draggable); @@ -280,7 +282,7 @@ export function useResizeable(props: any, context: any) { function renderResizeBar(hostElement: any) { resizedTarget.value = hostElement; - return <> + return resizeable.value && <>
    onMouseDown(e)}>
    onMouseDown(e)}>
    onMouseDown(e)}>
    diff --git a/packages/ui-vue/components/modal/src/modal.component.tsx b/packages/ui-vue/components/modal/src/modal.component.tsx index 05532136683..803145fa479 100644 --- a/packages/ui-vue/components/modal/src/modal.component.tsx +++ b/packages/ui-vue/components/modal/src/modal.component.tsx @@ -43,7 +43,6 @@ export default defineComponent({ const buttonAlignment = ref(''); const showButtons = ref(props.showButtons); const title = ref(props.title); - const resizeable = ref(props.resizeable); const containment = ref(props.containment || null); const modalContainerRef = ref(); @@ -443,7 +442,6 @@ export default defineComponent({
    { !fitContent.value && - resizeable.value && modalElementRef.value && !maximized.value && renderResizeBar(modalElementRef.value) -- Gitee From 461e1b995168084ae6f0e82d4988242d68030660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 3 Apr 2025 11:54:18 +0800 Subject: [PATCH 113/156] =?UTF-8?q?fix:=20lookup=E6=A0=91=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E6=95=B0=E6=8D=AE=E5=B1=95=E5=BC=80=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E5=B1=82=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-http.ts | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 04274bd70f5..77e0ce8d7e8 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -2,7 +2,7 @@ import { inject, Ref, ref, toRaw } from "vue"; import { flatten, isNaN } from "lodash-es"; import { FLoadingService } from "@farris/ui-vue/components/loading"; -import { resolveField as getFieldValue } from '@farris/ui-vue/components/common'; +import { resolveField as getFieldValue } from '@farris/ui-vue/components/common'; import { @@ -49,15 +49,15 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { const includeChilds = ref(false); const isTree = () => { - const displayType = lookupOptions.displayType?.toUpperCase(); + const displayType = lookupOptions.displayType?.toUpperCase(); return displayType === LookupDisplayType.Tree || displayType === LookupDisplayType.TreeList; }; const setTreeInfo = (resposneData: TreeInfo, isNavigation = false) => { if (resposneData) { - const { layerType, dataField, parentField, + const { layerType, dataField, parentField, pathField, layerField, isDetailField, loadDataType, - } = resposneData; + } = resposneData; const treeInfo: TreeInfo = { layerType, dataField, @@ -128,6 +128,15 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return tempConditions; } + function getExpandLevel() { + let { expandLevel } = lookupOptions; + if (expandLevel && !isNaN(expandLevel)) { + expandLevel = expandLevel < -1 ? -1 : expandLevel; + } + + return expandLevel; + } + function buildSearchParam(event: any, action: LOAD_DATA_TYPE) { const searchParam: SearchParam = {}; searchParam.category = action; @@ -150,7 +159,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } if (!props.enableMultiFieldSearch && searchParam.searchField === '*') { - const searchFields = isNavigation? navSearchFieldItems.value: searchFieldItems.value; + const searchFields = isNavigation ? navSearchFieldItems.value : searchFieldItems.value; const conditions = buildConditionsWhenSearchAnyFields(searchFields, value); if (conditions && conditions.length) { if (isNavigation) { @@ -168,11 +177,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } if (isTree()) { - let {expandLevel} = lookupOptions; - if (expandLevel && !isNaN(expandLevel)) { - expandLevel = expandLevel < -1 ? -1: expandLevel; - searchParam.layerNum = expandLevel; - } + searchParam.layerNum = getExpandLevel(); } return { @@ -299,9 +304,32 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { }); } - function setTreeNodeExpandStatus(treeNodes: any) { + function shoudExpand(layer: number) { + const expandLevel = getExpandLevel(); + if (expandLevel === -1) { + // -1 全展开 + return true; + } else if (expandLevel === 0) { + // 0 为不展开 + return false; + } else { + // 没有启用分层加载,通过展开层级确定是否展开该节点 + return layer <= expandLevel; + } + } + + function setTreeNodeExpandStatus(treeNodes: any, expandAll = false) { treeNodes.forEach((item: any) => { - item.collapse = item.expanded == null ? false: !item.expanded; + if (expandAll) { + item.collapse = false; + } else { + if (lookupOptions.loadTreeDataType === 'all') { + item.collapse = !shoudExpand(item.layer); + } else { + item.collapse = item.expanded == null ? false : !item.expanded; + } + } + if (item.children && item.children.length) { setTreeNodeExpandStatus(item.children); } @@ -326,7 +354,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } if (props.beforeLoadData) { - httpResult = await props.beforeLoadData({data: httpResult}); + httpResult = await props.beforeLoadData({ data: httpResult }); } callback(httpResult); loadingInstance.value?.close(); @@ -337,7 +365,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } function getPathCode(data: any, treeInfo: TreeInfo) { - const { dataField, pathField } = treeInfo ; + const { dataField, pathField } = treeInfo; if (pathField) { if (dataField) { return data[dataField][pathField]; @@ -363,20 +391,14 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return nodes; } - function expandAllNodes(nodes: any[]): any[] { - if (nodes && nodes.length) { - return nodes.map((node: any) => { - if (node.children && node.children.length) { - node.expanded = true; - expandAllNodes(node.children); - } - return node; - }); + function expandAllNodes(treeNodes: any[]): any[] { + if (treeNodes && treeNodes.length) { + setTreeNodeExpandStatus(treeNodes, true); } - return nodes; + return treeNodes; }; - function getIdValues() { + function getIdValues() { try { const idvalues = idValues.value; @@ -391,12 +413,12 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return ''; } } - + function getIdQueryParams() { let currentIdValues = getIdValues() || []; if (!Array.isArray(currentIdValues)) { - currentIdValues = (''+ currentIdValues).split(props.separator); + currentIdValues = ('' + currentIdValues).split(props.separator); } return { selectedIds: currentIdValues, selected: true }; -- Gitee From 1c47ab247e284900ca387327b4cd9fd31cd9e206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 3 Apr 2025 13:37:41 +0800 Subject: [PATCH 114/156] =?UTF-8?q?fix:=20lookup=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A4=B9=E6=95=B0=E6=8D=AE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/favorite/lookup-favorite.component.tsx | 4 +++- .../ui-vue/components/lookup/src/composition/use-user-data.ts | 3 ++- packages/ui-vue/components/lookup/src/lookup.component.tsx | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx index d6ec66dbc87..c15dbacd4f2 100644 --- a/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/favorite/lookup-favorite.component.tsx @@ -71,7 +71,9 @@ export default defineComponent({ } if (items) { - items = expandAllNodes(items); + if (isTreeList()) { + items = expandAllNodes(items); + } gridRef.value.updateDataSource(items || []); } diff --git a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts index a8e6bd813ab..9e736b39166 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts @@ -86,7 +86,8 @@ export function useUserData(props: LookupProps, useHttpComposition: UseHttpCompo const params = { searchValue: JSON.stringify(searchValue), pageIndex: 1, - pageSize: 500 + pageSize: 500, + treeToList: lookupOptions.treeToList }; return params; diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index 1898e474133..cc6d222d9d7 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -55,7 +55,7 @@ export default defineComponent({ const showIncludeChildNodes = computed(() => { - return props.showIncludeChildNodes && props.showNavigation && !props.navTreeToList; + return props.showIncludeChildNodes && props.showNavigation && !lookupOptions.navTreeToList; }); const selectionsManager = useSelections(props, useHttpComposition.lookupStates); @@ -177,7 +177,7 @@ export default defineComponent({ const showCascadeControl = computed(() => { return lookupOptions.multiSelect && props.showCascadeControl && props.enableCascade && - LookupDisplayType.Tree === lookupOptions.displayType.toUpperCase(); + LookupDisplayType.Tree === lookupOptions.displayType.toUpperCase() && !lookupOptions.treeToList; }); const selectedIds = computed(() => { -- Gitee From 3a6cb3c2da5a5ed65eb94268ee789750c3673f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 3 Apr 2025 14:38:32 +0800 Subject: [PATCH 115/156] =?UTF-8?q?fix:=20mapping-editor=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/mapping-editor.component.tsx | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index ae47229c57e..fb7ec0f5065 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -98,16 +98,27 @@ export default defineComponent({ } function onRemove() { - if (selectedItems.value.length) { - datagridRef.value.endEditCell(); - const itemIndex = mappingFieldList.value.findIndex((item: any) => item.id === selectedItems.value[0].id); - if (itemIndex > -1) { - selectedItems.value = []; - datagridRef.value.removeDataItem(itemIndex + 1); - } - } else { + if (!selectedItems.value.length) { notifyService.warning('请选择要删除的映射字段!'); + return; } + + datagridRef.value.endEditCell(); + const itemIndex = mappingFieldList.value.findIndex(item => item.id === selectedItems.value[0].id); + if (itemIndex === -1) { return; } + + const removeRowId = selectedItems.value[0].id; + datagridRef.value.removeDataItemById(removeRowId); + selectedItems.value = []; + + if (!mappingFieldList.value.length) { return; } + + const selectedIndex = Math.min( + itemIndex, + mappingFieldList.value.length - 1 + ); + const nextRowId = mappingFieldList.value[selectedIndex]?.id; + nextRowId && datagridRef.value.selectItemById(nextRowId); } function onClearAll() { -- Gitee From 24ea7154c33708e4f49149f3a6ab7d990294ff08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 3 Apr 2025 16:46:29 +0800 Subject: [PATCH 116/156] =?UTF-8?q?fix:=20lookup=E5=AF=BC=E8=88=AA?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=88=97=E8=A1=A8=E6=95=B0=E6=8D=AE=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/use-datagrid.tsx | 6 +- .../lookup/src/composition/use-http.ts | 80 ++++++++++--------- .../lookup/src/composition/use-navigation.tsx | 10 +-- .../property-config/lookup.property-config.ts | 8 +- 4 files changed, 54 insertions(+), 50 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx index 93fdd9828e0..5ec3c1d99da 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-datagrid.tsx @@ -66,11 +66,11 @@ export function useDatagrid(props: LookupProps, context: SetupContext, navigatio let nodes = navSelectedItems.value; if (navIsTreeList() && includeChilds.value) { const treeInfo = navigationState.treeInfo as any; - if (isPathCodeTree(treeInfo)) { - return { navNodePathCode: getPathCode(nodes[0].data, treeInfo) }; - } else if (isLoadAll(treeInfo)) { + if (isLoadAll(treeInfo)) { nodes = getChildNodes(nodes[0]); return {relationFilter: getRelationFilter(nodes)}; + } else if (isPathCodeTree(treeInfo)) { + return { navNodePathCode: getPathCode(nodes[0].data, treeInfo) }; } } return {relationFilter: getRelationFilter(nodes)}; diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 77e0ce8d7e8..5ed96fd0604 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -31,9 +31,10 @@ export interface UseHttpComposition { lookupStates: LookupStates; httpService?: LookupHttpService; lookupRequest: () => (uri, params) => Promise; - expandAllNodes: (treeNodes: any[]) => any[]; + expandAllNodes: (treeNodes: any[], isNavigation?: boolean) => any[]; getIdQueryParams: () => any; setTreeInfo: (resData: TreeInfo, isNavigation?: boolean) => void; + getFieldValue: (data: any, field: string) => any; } export function useHttp(props: LookupProps, context: any): UseHttpComposition { @@ -318,46 +319,44 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { } } - function setTreeNodeExpandStatus(treeNodes: any, expandAll = false) { - treeNodes.forEach((item: any) => { - if (expandAll) { - item.collapse = false; - } else { - if (lookupOptions.loadTreeDataType === 'all') { - item.collapse = !shoudExpand(item.layer); - } else { - item.collapse = item.expanded == null ? false : !item.expanded; - } - } - - if (item.children && item.children.length) { - setTreeNodeExpandStatus(item.children); + function setTreeNodeExpandStatus(treeNodes: any[], expandAll = false, layerField = 'layer') { + treeNodes.forEach(item => { + item.collapse = expandAll + ? false + : lookupOptions.loadTreeDataType === 'all' + ? !shoudExpand(getFieldValue(item.data, layerField)) + : !(item.expanded ?? true); + + if (item.children?.length) { + setTreeNodeExpandStatus(item.children, expandAll, layerField); } }); } - async function loadData(event: any, callback: (e: LookupHttpResult) => void) { const params = buildQueryParams(event) as Partial; const loadingInstance = loadingService?.show(); - let httpResult = await getData(params); - - if (isTree()) { - let treeItems = httpResult.items; - if (httpResult.navigation) { - treeItems = httpResult.navigation.items; + + try { + let httpResult = await getData(params); + + if (isTree()) { + const { items: treeItems, treeInfo: treeInfoConfig } = httpResult.navigation || httpResult; + + if (treeItems?.length && treeInfoConfig) { + const { dataField: treeInfoDataField, layerField } = treeInfoConfig; + setTreeNodeExpandStatus(treeItems, false, `${treeInfoDataField}.${layerField}`); + } } - - if (treeItems && treeItems.length) { - setTreeNodeExpandStatus(treeItems); + + if (props.beforeLoadData) { + httpResult = await props.beforeLoadData({ data: httpResult }); } + + callback(httpResult); + } finally { + loadingInstance?.value?.close(); } - - if (props.beforeLoadData) { - httpResult = await props.beforeLoadData({ data: httpResult }); - } - callback(httpResult); - loadingInstance.value?.close(); } function updateIncludeChilds(checked: boolean) { @@ -391,12 +390,18 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { return nodes; } - function expandAllNodes(treeNodes: any[]): any[] { - if (treeNodes && treeNodes.length) { - setTreeNodeExpandStatus(treeNodes, true); - } + function expandAllNodes(treeNodes: any[], isNavigation = false): any[] { + if (!treeNodes?.length) {return treeNodes;} + + const treeConfig = isNavigation + ? lookupOptions.navigation?.treeInfo + : lookupOptions.treeInfo; + + const { dataField, layerField } = treeConfig || {}; + dataField && layerField && setTreeNodeExpandStatus(treeNodes, true, `${dataField}.${layerField}`); + return treeNodes; - }; + } function getIdValues() { try { @@ -438,6 +443,7 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { lookupRequest, expandAllNodes, getIdQueryParams, - setTreeInfo + setTreeInfo, + getFieldValue }; } diff --git a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx index 76ce9f078f5..d2cb15df47e 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-navigation.tsx @@ -14,7 +14,7 @@ import { LOOKUP_TREEROW_OPTIONS } from "./use-treegrid-row-options"; export function useNavigation(props: LookupProps, context) { const treeRowOptions = inject(LOOKUP_TREEROW_OPTIONS); const useHttpComposition: UseHttpComposition = inject(LOOKUP_HTTP_COMPOSITION) as UseHttpComposition; - const { loadData, lookupStates, expandAllNodes } = useHttpComposition; + const { loadData, lookupStates, expandAllNodes, getFieldValue } = useHttpComposition; const { navigationState, pageInfoState, searchState } = lookupStates; const { renderSearchBar } = useSearchbar(props, true, lookupStates); @@ -63,7 +63,7 @@ export function useNavigation(props: LookupProps, context) { leftDatagridRef.value?.updateDataSource(items); } else if (navIsTreeList()) { if (searchState.navigation?.value) { - items = expandAllNodes(items); + items = expandAllNodes(items, true); } leftTreegridRef.value?.updateDataSource(items); } @@ -186,10 +186,8 @@ export function useNavigation(props: LookupProps, context) { const relations = navigationState.relations.map((relationItem => { const { groupField, helpField } = relationItem; const relationValue: any = { fieldName: helpField, fieldValue: '' }; - const vals = navRows.map(n => { - return groupField.split('.').reduce((o, c) => { - return o[c]; - }, n); + const vals = navRows.map(data => { + return getFieldValue(data, groupField); }); relationValue.fieldValue = vals.join(','); diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index b5ada5159fa..0534b23d653 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -798,18 +798,18 @@ export class LookupPropertyConfig extends InputBaseProperty { refreshPanelAfterChanged: true, tabId: 'commands', tabName: '交互', - setPropertyRelates(changeObject: any, data: any) { + setPropertyRelates(changeObject: any, newPropertyData: any) { const parameters = changeObject.propertyValue; - delete propertyData[self.viewModelId]; + delete newPropertyData[self.viewModelId]; if (parameters) { parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后,调用此回调方法,用于处理联动属性 - self.eventsEditorUtils.saveRelatedParameters(propertyData, self.viewModelId, parameters['events'], parameters); + self.eventsEditorUtils.saveRelatedParameters(newPropertyData, self.viewModelId, parameters['events'], parameters); } // 同步视图模型值变化事件 const designVM = self.designViewModelUtils.getDgViewModel(self.viewModelId); if (designVM && self.designViewModelField) { - designVM.changeField(self.designViewModelField.id, { valueChanging: propertyData.fieldValueChanging, valueChanged: propertyData.fieldValueChanged }); + designVM.changeField(self.designViewModelField.id, { valueChanging: newPropertyData.fieldValueChanging, valueChanged: newPropertyData.fieldValueChanged }); } } }; -- Gitee From c0cdea892195c64b6e642727add0c5b3db0ac315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 4 Apr 2025 08:40:13 +0800 Subject: [PATCH 117/156] =?UTF-8?q?fix:=20popover=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=B5=AE=E5=B1=82=E5=8A=A8=E7=94=BB=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/popover/src/popover.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/popover/src/popover.component.tsx b/packages/ui-vue/components/popover/src/popover.component.tsx index 6481fe2481a..2f44f514531 100644 --- a/packages/ui-vue/components/popover/src/popover.component.tsx +++ b/packages/ui-vue/components/popover/src/popover.component.tsx @@ -80,7 +80,7 @@ export default defineComponent({ return styles; }); - const { delayedValue } = useDelayedRef(popupStyles, 100); + const { delayedValue } = useDelayedRef(popupStyles, 50); onMounted(() => { if (shouldFitWidthToReference.value) { -- Gitee From 691d6c37cab8959dbaaf69ddbd9ac9a8e82e41ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 4 Apr 2025 08:59:15 +0800 Subject: [PATCH 118/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E9=9D=A2=E6=9D=BF=E4=B8=8B=E6=8B=89=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E9=AB=98=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/dynamic-resolver/src/property-config-resolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/dynamic-resolver/src/property-config-resolver.ts b/packages/ui-vue/components/dynamic-resolver/src/property-config-resolver.ts index e3d7db975b7..17ee17e63da 100644 --- a/packages/ui-vue/components/dynamic-resolver/src/property-config-resolver.ts +++ b/packages/ui-vue/components/dynamic-resolver/src/property-config-resolver.ts @@ -53,7 +53,7 @@ const propertyEditorMap = new Map([ } ] }], - ['enum', { "type": "combo-list", "maxHeight": 128, "enableClear": false, "editable": false }], + ['enum', { "type": "combo-list", "maxHeight": 350, "enableClear": false, "editable": false }], ['array', { "type": "button-edit" }], ['number', { "type": "number-spinner", "placeholder": "" }], ['events-editor', { "type": "events-editor", hide: true }] -- Gitee From 95f22d502a294bbacbcb1ee4b5d679cb2a5251f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 4 Apr 2025 16:54:18 +0800 Subject: [PATCH 119/156] =?UTF-8?q?fix:=20=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../functions/common-functions.component.tsx | 2 +- .../src/components/modal-container.component.tsx | 4 ++++ .../lookup/src/composition/use-treegrid.tsx | 6 +++--- .../src/property-config/lookup.property-config.ts | 4 ++-- .../src/composition/entity/expression-property.ts | 13 +++++++++++-- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx index 5b04b8669ae..001c32343e8 100644 --- a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx @@ -190,7 +190,7 @@ export default defineComponent({ >
    -
      +
        { renderFunctionItem()}
      diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx index 09b4276e506..bc3a9641b4a 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx @@ -128,6 +128,10 @@ export default defineComponent({ if (userDataState.data.favorites && userDataState.data.favorites.length) { activeTab.value = userDataState.data?.tabIndex || LookupTabs.dataList; } + + if (showIncludeChildNodes.value) { + props.useHttpComposition.updateIncludeChilds(includeChildNodes.value); + } }); return () =>
      diff --git a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx index 00c51ae42c1..d9098256027 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-treegrid.tsx @@ -67,15 +67,15 @@ export function useTreegrid(props: LookupProps, context: SetupContext) { unSelectTreeNode(item); } - function httpRequest() { - loadData({ search: searchState.default, action: 'list' }, (result: LookupHttpResult) => { + function httpRequest(action = 'list') { + loadData({ search: searchState.default, action }, (result: LookupHttpResult) => { treeGridLoadData(result.items); }); } watch(() => searchState.default, (newSearchInfo) => { if (props.uri) { - httpRequest(); + httpRequest('search'); return; } context.emit('search', newSearchInfo); diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 0534b23d653..3ff8020502c 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -550,14 +550,14 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "调整窗口尺寸", type: "boolean", $converter: lookupDialogOptionsConverter, - visible: !!propertyData.editor?.dialog?.draggable + visible: propertyData.editor?.dialog?.draggable ?? true }, rememberSize: { description: "记录窗口尺寸", title: "记录窗口尺寸", type: "boolean", $converter: lookupDialogOptionsConverter, - visible: !!propertyData.editor.enableUserData && !!propertyData.editor?.dialog?.draggable + visible: !!propertyData.editor.enableUserData && (propertyData.editor?.dialog?.draggable ?? true) }, enableEsc: { description: "允许ESC关闭", diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 2edc903a309..24b91f61777 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -1,6 +1,6 @@ export interface RuleModel { id: string; - type: 'compute' | 'dependency' | 'validate' | 'visable' | 'readonly' | 'require' | 'dataPicking' | string; + type: 'compute' | 'dependency' | 'validate' | 'visible' | 'readonly' | 'required' | 'dataPicking' | string; value: string; message?: string; elementId?: string; @@ -255,6 +255,10 @@ export class ExpressionProperty { ruleItem.value = newRule.value; ruleItem.message = newRule.message; + if (ruleType === 'dataPicking') { + ruleItem.messageType = newRule.messageType; + } + if (ruleType === 'validate' && propertyData.type === 'form-group') { ruleItem.elementId = propertyData.id; } @@ -287,7 +291,10 @@ export class ExpressionProperty { compute: '计算表达式', dependency: '依赖表达式', validate: '验证表达式', - dataPicking: '帮助前表达式' + dataPicking: '帮助前表达式', + visible: '可见表达式', + readonly: '只读表达式', + required: '必填表达式' }; private getExpressionConverter = (expressionId: string, ruleType?: string) => { @@ -317,6 +324,7 @@ export class ExpressionProperty { editor: { type: "expression-editor", singleExpand: false, + dialogTitle: `${this.expressionNames[name]}编辑器`, showMessage: name === 'validate' || name === 'dataPicking', showMessageType: name === 'dataPicking', beforeOpen: () => { @@ -365,6 +373,7 @@ export class ExpressionProperty { getExpressionOptions(propertyData: any, targetType: 'Field' | 'Button' | 'Container', expressionType: string) { const expressionInfo = this.getExpressionInfo(propertyData, targetType, expressionType); return { + dialogTitle: `${this.expressionNames[expressionType]}编辑器`, singleExpand: false, showMessage: expressionType === 'require', beforeOpen: () => { -- Gitee From 80a48b6d2b9361b5ebba7218bce294892df150ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 4 Apr 2025 17:32:12 +0800 Subject: [PATCH 120/156] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96lookup?= =?UTF-8?q?=E5=BC=B9=E5=87=BA=E7=AA=97=E5=8F=A3=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/composition/types.ts | 2 +- packages/ui-vue/components/lookup/src/lookup.component.tsx | 4 ++-- packages/ui-vue/components/lookup/src/lookup.props.ts | 4 ++-- .../ui-vue/components/lookup/src/schema/lookup.schema.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 23cde836590..330c14ce81c 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -5,7 +5,7 @@ export const cascadeItems = [ { value: 'disable', text: '仅选择自身'} ]; -export const DefaultDialogTitle = '请选择'; +export const DefaultDialogTitle = ''; export interface SearchParams { field: string; diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index cc6d222d9d7..1591029a2b9 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -42,7 +42,7 @@ export default defineComponent({ const buttonIcon = ''; const elementRef = ref(); const modelValue = ref(props.modelValue); - const modalTitle = ref(); + const modalTitle = ref(''); customData.value = ref(props.customData); const useHttpComposition = useHttp(props, context); @@ -225,7 +225,7 @@ export default defineComponent({ placeholder={props.placeholder} enableTitle={props.enableTitle} > - onMaximizeModal($event)} useHttpComposition= {useHttpComposition} userDataService={userDataService} useDialog={{cancelDialog, submitDialog}} showSelectedList={showSelections.value} diff --git a/packages/ui-vue/components/lookup/src/lookup.props.ts b/packages/ui-vue/components/lookup/src/lookup.props.ts index 5a4656c33f4..a0d2e763e05 100644 --- a/packages/ui-vue/components/lookup/src/lookup.props.ts +++ b/packages/ui-vue/components/lookup/src/lookup.props.ts @@ -30,7 +30,7 @@ export const lookupProps = { dialog: { type: Object as PropType, default: { - title: '请选择' + title: '' } }, multiSelect: {type: Boolean, default: false}, @@ -72,7 +72,7 @@ export const lookupProps = { userDataKey: {type: String, default: ''}, onReady: { type: Function, default: null }, context: { type: Object, default: {} }, - placeholder: { type: String, default: '请选择' }, + placeholder: { type: String, default: '' }, loader: { type: Function, default: null }, allowFreeInput: { type: Boolean, default: false }, onlySelectLeaf: { type: Boolean, default: false }, diff --git a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json index e40ff65b4bc..575e1757b23 100644 --- a/packages/ui-vue/components/lookup/src/schema/lookup.schema.json +++ b/packages/ui-vue/components/lookup/src/schema/lookup.schema.json @@ -54,7 +54,7 @@ "placeholder": { "description": "", "type": "string", - "default": "请选择" + "default": "" }, "readonly": { "description": "", -- Gitee From ba08a6e2c115d81770cd3f2d7f86f45962d6011b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 5 Apr 2025 09:22:45 +0800 Subject: [PATCH 121/156] =?UTF-8?q?fix:=20lookup=E5=BC=B9=E5=87=BA?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=A0=87=E9=A2=98=E9=95=BF=E5=BA=A6=E8=87=AA?= =?UTF-8?q?=E9=80=82=E5=BA=94=E5=AE=BD=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/modal-container.component.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx index bc3a9641b4a..d9f1cf6776f 100644 --- a/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/modal-container.component.tsx @@ -119,6 +119,16 @@ export default defineComponent({ }; }); + const modalTitleWidth = computed(() => { + const baseWidth = props.enableFavorite ? '50%' : '100%'; + const buttonOffset = props.enableFavorite ? 100 : 80; + const subtractPx = (dialogOptions.showMaxButton || dialogOptions.showCloseButton) ? buttonOffset : 0; + + return { + maxWidth: `calc(${baseWidth} - ${subtractPx}px)` + }; + }); + function onTabMousedown($event) { $event.stopPropagation(); document.body.click(); @@ -136,7 +146,7 @@ export default defineComponent({ return () =>
      -
      {props.title}
      +
      {props.title}
      {props.enableFavorite &&
      -- Gitee From 09de8ddd20884b4e192bebc75390ecd5a5a2b3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 5 Apr 2025 10:24:32 +0800 Subject: [PATCH 122/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4lookup?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=97=B6=E5=B1=9E=E6=80=A7=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property-config/lookup.property-config.ts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 3ff8020502c..b33d97003aa 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -107,20 +107,6 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "Basic Infomation", title: "行为", properties: { - required: { - description: "", - title: "必填", - type: "boolean", - $converter: "/converter/property-editor.converter", - editor: this.requiredEditor - }, - readonly: { - description: "", - title: "只读", - type: "boolean", - $converter: "/converter/property-editor.converter", - editor: this.readonlyEditor - }, visible: { description: "运行时组件是否可见", title: "是否可见", @@ -156,12 +142,19 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "Basic Infomation", title: "编辑器", properties: { - enableTitle: { - description: "鼠标悬停显示文本内容", - title: "提示信息", + readonly: { + description: "", + title: "只读", type: "boolean", - $converter: lookupDefaultConverter, - editor: this.comboListEditor + $converter: "/converter/property-editor.converter", + editor: this.readonlyEditor + }, + required: { + description: "", + title: "必填", + type: "boolean", + $converter: "/converter/property-editor.converter", + editor: this.requiredEditor }, placeholder: { description: "当控件没有值时在输入框中显示的文本", @@ -169,6 +162,13 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "string", $converter: lookupDefaultConverter }, + enableTitle: { + description: "鼠标悬停显示文本内容", + title: "提示信息", + type: "boolean", + $converter: lookupDefaultConverter, + editor: this.comboListEditor + }, editable: { description: "", title: "允许编辑", -- Gitee From e2f889bde3bd8190aab342cbb83b6a8b818fbdc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 7 Apr 2025 16:13:37 +0800 Subject: [PATCH 123/156] =?UTF-8?q?fix:=20lookup=E5=BC=B9=E5=87=BA?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=98=93=E7=94=A8=E6=80=A7=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/composition/types.ts | 12 +++++- .../lookup/src/composition/use-check-props.ts | 9 +++-- .../lookup/src/composition/use-dialog.ts | 18 ++++----- .../converters/lookup-property.converter.ts | 10 ++--- .../property-config/lookup.property-config.ts | 39 ++++++++----------- .../modal/src/composition/use-resizeable.tsx | 6 ++- .../components/modal/src/modal.component.tsx | 2 +- 7 files changed, 49 insertions(+), 47 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/types.ts b/packages/ui-vue/components/lookup/src/composition/types.ts index 330c14ce81c..d564afdb049 100644 --- a/packages/ui-vue/components/lookup/src/composition/types.ts +++ b/packages/ui-vue/components/lookup/src/composition/types.ts @@ -73,8 +73,6 @@ export interface NavigationOptions { searchFields?: SearchField[]; idField: string; pagination?: LookupPagination; - width?: number; - minWidth?: number; } export type TextChangedType = 'blur' | 'enter' | 'any'; @@ -295,4 +293,14 @@ export interface LookupDialogOptions { resizeable?: boolean; enableEsc?: boolean; rememberSize?: boolean; + navigatorWidth?: number; +}; + +export const DEFAULT_LOOKUP_DIALOG_OPTIONS: Partial = { + showCloseButton: true, + showMaxButton: true, + draggable: true, + resizeable: true, + enableEsc: true, + rememberSize: true }; diff --git a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts index 4fc4bfe5a7e..aae2186bc73 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-check-props.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-check-props.ts @@ -65,14 +65,15 @@ export function useCheckProps(props: LookupProps, lookupStates: LookupStates) { } function getNavigationSize() { - const width = 300; + const width = 320; const minWidth = 200; - if (props.navigation) { + if (lookupOptions.dialog) { return { - width: props.navigation.width || 320, - minWidth: props.navigation.minWidth || 200 + width: lookupOptions.dialog?.navigatorWidth || width, + minWidth: 200 }; } + return { width, minWidth diff --git a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts index e3d3e40fbbe..41d787eb72d 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-dialog.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-dialog.ts @@ -9,7 +9,7 @@ import { useCheckProps } from "./use-check-props"; import { UserDataService } from "./use-user-data"; import { UseHttpComposition } from "./use-http"; import { useContext } from "./use-context"; -import { LookupDialogOptions } from "./types"; +import { DEFAULT_LOOKUP_DIALOG_OPTIONS, LookupDialogOptions } from "./types"; /** 窗口关闭类型 */ enum CloseType { @@ -42,13 +42,8 @@ export function useDialog( const { lookupStates } = useHttp; const { queryState, lookupState, navigationState, pageInfoState, searchState, selectionState, lookupOptions } = lookupStates; const { isDoubleList } = useCheckProps(props, lookupStates); - const dialogOptions = lookupOptions.dialog as LookupDialogOptions; - if (dialogOptions.showCloseButton == null) { - dialogOptions.showCloseButton = true; - } - if (dialogOptions.showMaxButton == null) { - dialogOptions.showMaxButton = true; - } + const dialogOptions = Object.assign({}, DEFAULT_LOOKUP_DIALOG_OPTIONS, lookupOptions.dialog) as LookupDialogOptions; + lookupOptions.dialog = dialogOptions; const NOTIFY_OPTIONS = { position: 'top-center' as const }; @@ -166,7 +161,7 @@ export function useDialog( const { width, height, minHeight, minWidth } = getDefaultDialogSize(); - const dialogDraggable = dialogOptions?.draggable == null ? true : dialogOptions?.draggable; + const dialogDraggable = true; // dialogOptions?.draggable == null ? true : dialogOptions?.draggable; const dialogResizeable = dialogDraggable && (dialogOptions?.resizeable == null ? true : dialogOptions?.resizeable); dialogOptions.rememberSize = dialogOptions.rememberSize && dialogResizeable; @@ -215,7 +210,8 @@ export function useDialog( if (dialogOptions.rememberSize) { dialogSize.value = $event; const { width, height } = $event.newSize.size; - userDataService.setDialogSize({ width: Math.round(width), height: Math.round(height) }); + const isMaximized = $event.isMaximized ?? false; + !isMaximized && userDataService.setDialogSize({ width: Math.round(width), height: Math.round(height) }); } }, enableEnter: true, @@ -243,7 +239,7 @@ export function useDialog( let shouldContinue = true; await userDataService.getUserData(); - if (userDataService?.userDataState?.data && props.enableUserData && props.dialog?.rememberSize) { + if (userDataService?.userDataState?.data && props.enableUserData && dialogOptions.rememberSize) { const { size } = userDataService.userDataState.data; if (size) { Object.assign(modalOptions, size); diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index c8c6bc547e7..4328292e8a0 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -161,15 +161,15 @@ export const lookupDialogOptionsConverter = { return options[propertyKey] || 620; } - if (propertyKey === 'rememberSize') { - return options[propertyKey] === undefined ? !!schema.editor.enableUserData : options[propertyKey]; + if (propertyKey === 'navigatorWidth') { + return options[propertyKey] || 320; } - if (propertyKey === 'navigatorWidth') { - return options[propertyKey] || 300; + if (propertyKey === 'draggable') { + return true; } - const keys = ['showMaxButton', 'showCloseButton', 'resizeable', 'draggable', 'enableEsc']; + const keys = ['showMaxButton', 'showCloseButton', 'resizeable', 'enableEsc', 'rememberSize']; if (keys.includes(propertyKey)) { return options[propertyKey] == null ? true : options[propertyKey]; } diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index b33d97003aa..0658a611ebb 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -469,15 +469,6 @@ export class LookupPropertyConfig extends InputBaseProperty { title: "启用收藏夹", type: "boolean", }, - - showNavigation: { - description: "显示导航栏", - $converter: lookupDefaultConverter, - refreshPanelAfterChanged: true, - title: "显示导航栏", - type: "boolean", - visible: this.getDisplayType(editorOptions).includes('NAV') - }, enableUserData: { description: "保存界面状态", $converter: lookupDefaultConverter, @@ -513,10 +504,11 @@ export class LookupPropertyConfig extends InputBaseProperty { description: "窗口宽度", title: "宽度", type: "number", + refreshPanelAfterChanged: true, $converter: lookupDialogOptionsConverter, editor: { ...this.numberEditor, - min: 300 + min: this.showNavigatiorWidth(propertyData.editor)? 520: 300 } }, height: { @@ -526,38 +518,41 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDialogOptionsConverter, editor: { ...this.numberEditor, - min: 300 + min: 200 } }, + showNavigation: { + description: "显示导航栏", + $converter: lookupDefaultConverter, + refreshPanelAfterChanged: true, + title: "显示导航栏", + type: "boolean", + visible: this.getDisplayType(propertyData.editor).includes('NAV') + }, navigatorWidth: { title: "导航栏宽度", type: "number", $converter: lookupDialogOptionsConverter, visible: this.showNavigatiorWidth(propertyData.editor), editor: { - ...this.numberEditor + ...this.numberEditor, + min: 200, + max: (propertyData.editor?.dialog?.width ?? 960) - 200 } }, - draggable: { - description: "允许拖拽", - title: "允许拖拽", - type: "boolean", - refreshPanelAfterChanged: true, - $converter: lookupDialogOptionsConverter - }, resizeable: { description: "允许鼠标拖拽窗口边缘调整尺寸", - title: "调整窗口尺寸", + title: "允许调整窗口尺寸", type: "boolean", $converter: lookupDialogOptionsConverter, - visible: propertyData.editor?.dialog?.draggable ?? true + refreshPanelAfterChanged: true, }, rememberSize: { description: "记录窗口尺寸", title: "记录窗口尺寸", type: "boolean", $converter: lookupDialogOptionsConverter, - visible: !!propertyData.editor.enableUserData && (propertyData.editor?.dialog?.draggable ?? true) + visible: !!propertyData.editor.enableUserData && (propertyData.editor?.dialog?.resizeable ?? true) }, enableEsc: { description: "允许ESC关闭", diff --git a/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx b/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx index ba93c061b9a..453c84c8a3c 100644 --- a/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx +++ b/packages/ui-vue/components/modal/src/composition/use-resizeable.tsx @@ -309,9 +309,11 @@ export function useResizeable(props: any, context: any) { if (maxSize && target) { currSize.value = maxSize; + currSize.value.height -= 14; + currSize.value.width -= 14; - target.style.height = (currSize.value.height - 14) + 'px'; - target.style.width = (currSize.value.width - 14) + 'px'; + target.style.height = currSize.value.height + 'px'; + target.style.width = currSize.value.width + 'px'; target.style.left = '7px'; target.style.top = '7px'; target.style.transform = ''; diff --git a/packages/ui-vue/components/modal/src/modal.component.tsx b/packages/ui-vue/components/modal/src/modal.component.tsx index 803145fa479..740fb360e21 100644 --- a/packages/ui-vue/components/modal/src/modal.component.tsx +++ b/packages/ui-vue/components/modal/src/modal.component.tsx @@ -163,7 +163,7 @@ export default defineComponent({ const oldSizeValue = oldSize || {}; if (JSON.stringify(newSizeValue) !== JSON.stringify(oldSizeValue)) { - context.emit('resize', { newSize, oldSize }); + context.emit('resize', { newSize, oldSize, isMaximized: maximized.value }); } }); -- Gitee From ef5fcd449fbb26087efa3886dd26b89cadd67396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 7 Apr 2025 17:08:38 +0800 Subject: [PATCH 124/156] =?UTF-8?q?fix:=20combo-tree=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89idField?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/combo-tree/src/schema/combo-tree.schema.json | 5 +++++ .../src/components/condition-grid.props.ts | 4 ++++ .../src/composition/use-fields-tree.tsx | 2 +- .../src/filter-condition-editor.component.tsx | 2 ++ .../src/filter-condition-editor.props.ts | 4 ++++ .../src/schema/filter-condition-editor.json | 5 +++++ .../lookup/src/property-config/lookup.property-config.ts | 5 +++-- .../components/tree-view/src/schema/tree-view.schema.json | 5 +++++ 8 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json index f2cf9285a54..a98ff0ea73a 100644 --- a/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json +++ b/packages/ui-vue/components/combo-tree/src/schema/combo-tree.schema.json @@ -127,6 +127,11 @@ "description": "", "type": "number", "default": 160 + }, + "idField": { + "description": "", + "type": "string", + "default": "id" } }, "required": [ diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts index 10a066d5144..b921e0d4ffd 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts @@ -35,5 +35,9 @@ export const conditionGridProps = { singleValue: { type: Boolean, default: true + }, + idField: { + type: String, + default: 'id' } }; diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx index 0f2d476efb4..203482df83e 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx @@ -10,7 +10,7 @@ export function useFieldsTree(props) { data={fields} textField={'name'} valueField={'path'} - idField={'id'} + idField={props.idField || 'id'} enableClear={false} minPanelWidth={220} customRowStatus={treeNodeStatus} diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx index b363b1653b6..c76ceed7514 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.component.tsx @@ -50,6 +50,7 @@ export default defineComponent({ activeIndex={activeRow.value?.index} onInsert={(payload) => onInsert(payload)} onRemove={(payload) => onRemove(payload)} + idField={props.idField} onRowClick={(payload) => onSelectRow(payload)}>; } @@ -59,6 +60,7 @@ export default defineComponent({ enableExpression={props.enableExpression} conditions={conditions.value} fields={fields.value} + idField={props.idField} activeIndex={activeRow.value?.index} onInsert={(payload) => onInsert(payload)} onRemove={(payload) => onRemove(payload)} diff --git a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts index 7017eb0ea02..5957a9786b2 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/filter-condition-editor.props.ts @@ -69,6 +69,10 @@ export const filterConditionEditorProps = { singleValue: { type: Boolean, default: true + }, + idField: { + type: String, + default: 'id' } } as Record; diff --git a/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json index 51815d776b1..8e98b9d0101 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json +++ b/packages/ui-vue/components/filter-condition-editor/src/schema/filter-condition-editor.json @@ -78,6 +78,11 @@ "description": "", "type": "boolean", "default": true + }, + "idField": { + "description": "", + "type": "string", + "default": "id" } } } \ No newline at end of file diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 0658a611ebb..0ad4db4d414 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -252,6 +252,7 @@ export class LookupPropertyConfig extends InputBaseProperty { formBasicInfo: this.formSchemaUtils.getFormMetadataBasicInfo(), viewModelId: this.formSchemaUtils.getFormSchema().module.entity[0].id, }, + idField: 'path', repositoryToken: FieldSelectorRepositoryToken, beforeOpen: async ({ repository, notifyService }) => { const hasDataSource = editorOptions?.helpId; @@ -389,13 +390,13 @@ export class LookupPropertyConfig extends InputBaseProperty { formatter: (cell, data) => { return `${data.raw['name']} [${data.raw['bindingPath']}]`; }, - idField: 'id', + idField: 'bindingPath', textField: 'bindingPath', valueField: 'bindingPath', repositoryToken: FieldSelectorRepositoryToken }, toData: { - idField: 'id', + idField: 'bindingPath', textField: 'bindingPath', valueField: 'bindingPath', dataSource: this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId), diff --git a/packages/ui-vue/components/tree-view/src/schema/tree-view.schema.json b/packages/ui-vue/components/tree-view/src/schema/tree-view.schema.json index 03c11e2a599..206201fc06c 100644 --- a/packages/ui-vue/components/tree-view/src/schema/tree-view.schema.json +++ b/packages/ui-vue/components/tree-view/src/schema/tree-view.schema.json @@ -65,6 +65,11 @@ "description": "", "type": "boolean", "default": true + }, + "idField": { + "description": "", + "type": "string", + "default": "id" } }, "required": [ -- Gitee From 30c72c06892e35bc5ccec5b34dd74eeb965680f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 7 Apr 2025 19:53:26 +0800 Subject: [PATCH 125/156] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0lookup?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 0ad4db4d414..31ab75be6ec 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -164,7 +164,7 @@ export class LookupPropertyConfig extends InputBaseProperty { }, enableTitle: { description: "鼠标悬停显示文本内容", - title: "提示信息", + title: "悬停提示", type: "boolean", $converter: lookupDefaultConverter, editor: this.comboListEditor -- Gitee From 75864b68407e93a9d22fa9a3b50b683888dc9b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 8 Apr 2025 16:09:07 +0800 Subject: [PATCH 126/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E5=B1=9E=E6=80=A7=E9=85=8D=E7=BD=AE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 18 ++++++++- .../src/composition/use-disable-date.ts | 6 ++- .../src/composition/use-disable-month.ts | 4 +- .../date-picker/src/composition/use-year.ts | 6 +-- .../date-picker/src/date-picker.component.tsx | 40 +++++++------------ .../src/composition/use-search-function.tsx | 4 +- .../search-bar/search-bar.component.tsx | 1 + .../property-config/lookup.property-config.ts | 7 ++++ .../composition/entity/expression-property.ts | 32 +++++++-------- 9 files changed, 67 insertions(+), 51 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index f6465e7bbe9..cc1470b712c 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { computed, defineComponent, onMounted, ref, SetupContext, watch } from "vue"; +import { computed, defineComponent, onMounted, ref, SetupContext, watch, watchEffect } from "vue"; import { datePickerContainerProps, DatePickerContainerProps, DisplayMode } from "./date-picker-container.props"; import FCalenderNavBar from '../calendar-navbar/calendar-navbar.component'; import FTimePickerTimeView from '../../../../time-picker/src/components/time.component'; @@ -262,6 +262,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[activeMonth.value.month || '1'], displayTextOfYear: `${previousYear}` }; + activeMonth.value = previous; } @@ -273,6 +274,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[previousMonthDate.month || '1'], displayTextOfYear: `${previousMonthDate.year}` }; + activeMonth.value = previous; } @@ -284,6 +286,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[nextMonthDate.month || '1'], displayTextOfYear: `${nextMonthDate.year}` }; + activeMonth.value = next; } @@ -298,6 +301,7 @@ export default defineComponent({ displayTextOfMonth: nameOfMonths.value[activeMonth.value.month || '1'], displayTextOfYear: `${nextYear}` }; + activeMonth.value = next; } @@ -311,6 +315,7 @@ export default defineComponent({ selectingYear.value = !selectingYear.value; } + const primaryCalendarNavBarProps = computed(() => { return { 'active-month': activeMonth.value, @@ -368,6 +373,17 @@ export default defineComponent({ return selectingYear.value && !selectingMonth.value; }); + watchEffect(() => { + if (shouldShowCalendarView.value) { + activeMonth.value = { + year: selectedMonth.value.year || 1, + month: selectedMonth.value.month || 1, + displayTextOfMonth: nameOfMonths.value[selectedMonth.value.month || '1'], + displayTextOfYear: `${selectedMonth.value.year}` + }; + } + }); + const primaryCalendarProps = computed(() => { return { dates: dates.value, diff --git a/packages/ui-vue/components/date-picker/src/composition/use-disable-date.ts b/packages/ui-vue/components/date-picker/src/composition/use-disable-date.ts index c924dc686e5..6410775bf94 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-disable-date.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-disable-date.ts @@ -41,7 +41,11 @@ export function useDisableDate( return true; } const dateMonths: number = getTimeInMilliseconds(date); - if (isInitializedDate(disableUntil) && (dateMonths + 24 * 60 * 60 * 1000 - 1) < getTimeInMilliseconds(disableUntil)) { + + const hasHour = date.hour !== undefined; + + + if (isInitializedDate(disableUntil) && (hasHour ? dateMonths : dateMonths + 24 * 60 * 60 * 1000 - 1) < getTimeInMilliseconds(disableUntil)) { return true; } if (isInitializedDate(disableSince) && dateMonths > getTimeInMilliseconds(disableSince)) { diff --git a/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts b/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts index 0cd3f40fd63..e7d21ed071e 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts @@ -24,11 +24,11 @@ export default function useDisableMonth(): UseDisableMonth { const { isInitializedDate } = useCompare(); function isMonthDisabledByDisableUntil(date: DateObject, disableUntil: DateObject): boolean { - return (isInitializedDate(disableUntil) && getTimeInMilliseconds(date) <= getTimeInMilliseconds(disableUntil)); + return (isInitializedDate(disableUntil) && getTimeInMilliseconds(date) < getTimeInMilliseconds(disableUntil)); } function isMonthDisabledByDisableSince(date: DateObject, disableSince: DateObject): boolean { - return (isInitializedDate(disableSince) && getTimeInMilliseconds(date) >= getTimeInMilliseconds(disableSince)); + return (isInitializedDate(disableSince) && getTimeInMilliseconds(date) > getTimeInMilliseconds(disableSince)); } return { isMonthDisabledByDisableSince, isMonthDisabledByDisableUntil }; diff --git a/packages/ui-vue/components/date-picker/src/composition/use-year.ts b/packages/ui-vue/components/date-picker/src/composition/use-year.ts index 1762e7180ab..6dd295287b3 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-year.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-year.ts @@ -48,15 +48,15 @@ export function useYear(): UseYear { for (let startYearInRow = beginningYearInDecenniad - 1; startYearInRow < nextDecenniad; startYearInRow += capacityPerRow) { const yearsInRow: YearViewItem[] = []; for (let year = startYearInRow; year < startYearInRow + capacityPerRow; year++) { - const disabled: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, disableSince) || - isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month || 0, year) }, disableUntil); + // const disabled: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, disableSince) || + // isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month || 0, year) }, disableUntil); const isOverstepped: boolean = year < min || year > max; yearsInRow.push({ year, isCurrent: year === today.year, selected: year === selectedYear, - disable: disabled || isOverstepped, + disable: isOverstepped, date: { year } }); } diff --git a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx index fec3ec8c089..ec997e59f4d 100644 --- a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx +++ b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx @@ -116,6 +116,16 @@ export default defineComponent({ context.emit('datePicked', realValue.value); } + function setMaxAndMinYear() { + minYear.value = minDate.value.year ?? minYear.value; + maxYear.value = maxDate.value.year ?? maxYear.value; + + // 确保 minYear.value 不大于 maxYear.value + if (minYear.value > maxYear.value) { + maxYear.value = minYear.value; + } + } + watch(() => props.modelValue, (newValue, oldValue) => { if (newValue !== oldValue) { setModelValue(newValue); @@ -132,38 +142,16 @@ export default defineComponent({ } ); - function validateAndSetDefault( - value: unknown, - defaultValue: number, - lowerBound?: number, - upperBound?: number - ): number { - // 处理非数字输入 - const newValue = typeof value === 'number' && Number.isFinite(value) - ? value - : defaultValue; - - // 边界值处理(同时处理反向边界情况) - const safeValue = Math.max( - lowerBound ?? -Infinity, - Math.min(upperBound ?? Infinity, newValue) - ); - - return safeValue; - } + watch([() => props.maxDate, () => props.minDate], ([newMaxDate, newMinDate]) => { + setMaxAndMinYear(); + }); onMounted(() => { if (modelValue.value) { setModelValue(modelValue.value); } - minYear.value = validateAndSetDefault(minYear.value, 1900, 1900); - maxYear.value = validateAndSetDefault(maxYear.value, 9999, undefined, 9999); - - // 确保 minYear.value 不大于 maxYear.value - if (minYear.value > maxYear.value) { - maxYear.value = minYear.value; - } + setMaxAndMinYear(); }); const onConfirm = (selectedDate: DateObject) => { diff --git a/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx b/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx index a8838af0f89..3f9d36a7acc 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx +++ b/packages/ui-vue/components/expression-editor/src/composition/use-search-function.tsx @@ -32,8 +32,8 @@ export function useSearchFunction(props, functionItems: any) { } const searchResultKeys = allFunctionItems.filter((item: any) => { - return item.name.toLowerCase().includes(searchValue.toLowerCase()) || - item.key.toLowerCase().includes(searchValue.toLowerCase()); + return item.name.toLowerCase().includes(searchValue.toLowerCase()); + // || item.key.toLowerCase().includes(searchValue.toLowerCase()); }).map(item => item.key); functionItems.value = filterFunctions(searchResultKeys); diff --git a/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx b/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx index 1ac46ffbcb7..4c89110beea 100644 --- a/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx +++ b/packages/ui-vue/components/lookup/src/components/search-bar/search-bar.component.tsx @@ -94,6 +94,7 @@ export default defineComponent({
      '} + maxLength={200} v-model={searchValue.value} onClickButton={onSearch} enableClear={true} diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 31ab75be6ec..6820848b434 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -274,6 +274,12 @@ export class LookupPropertyConfig extends InputBaseProperty { result = { fieldList: data, conditionList: conditions }; } + if (entitiesAndVariables.variables?.forms) { + entitiesAndVariables.variables.forms.items = entitiesAndVariables.variables.forms.items.filter((item: any) => { + return item.category === 'remote'; + }); + } + return { ...result, ...entitiesAndVariables }; }, onSubmitModal: async ({ loadingService, repository, conditions, originalConditions, FMessageBoxService }) => { @@ -456,6 +462,7 @@ export class LookupPropertyConfig extends InputBaseProperty { refreshPanelAfterChanged: true, title: "启用搜索框", type: "boolean", + visible: false }, searchAnyField: { description: "显示所有列", diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 24b91f61777..750c1ef45ba 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -91,13 +91,12 @@ export class ExpressionProperty { const contextEntities: any = []; viewModel.states.forEach(variable => { - if (variable.category === 'remote') { - contextEntities.push({ - key: variable.code, - name: variable.name, - description: variable.name - }); - } + contextEntities.push({ + key: variable.code, + name: variable.name, + description: variable.name, + category: variable.category + }); }); return contextEntities; } @@ -215,15 +214,21 @@ export class ExpressionProperty { const rule: RuleModel = { id: `${targetId}_${ruleType}`, type: ruleType, - value: expressionValue, - message, - messageType + value: expressionValue }; + + if (ruleType === 'validate' || ruleType === 'dataPicking') { + rule.message = message; + } + + if (ruleType === 'dataPicking') { + rule.messageType = messageType; + } if (ruleType === 'validate' && controlId) { rule.elementId = controlId; } - + return rule; } @@ -253,11 +258,6 @@ export class ExpressionProperty { expressionItem.rules = expressionItem.rules.filter((rule) => rule.id !== newRule.id); } else { ruleItem.value = newRule.value; - ruleItem.message = newRule.message; - - if (ruleType === 'dataPicking') { - ruleItem.messageType = newRule.messageType; - } if (ruleType === 'validate' && propertyData.type === 'form-group') { ruleItem.elementId = propertyData.id; -- Gitee From 47fe8c4e3c056d2dfa9e30e16480bb09b250a0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 11 Apr 2025 14:47:20 +0800 Subject: [PATCH 127/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dlookup?= =?UTF-8?q?=E3=80=81=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E7=AD=89=E4=B8=80=E4=BA=9B=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 2 +- .../entity-variable.component.tsx | 108 +++++++++++++-- .../entity-tree/entity-treeview.component.tsx | 14 +- .../components/expression-code.component.tsx | 3 + .../functions/common-functions.component.tsx | 5 +- .../composition/functions-data/analytical.ts | 3 - .../composition/functions-data/math-number.ts | 3 - .../composition/functions-data/translate.ts | 6 - .../src/expression-editor.component.tsx | 13 +- .../src/expression-textbox.component.tsx | 4 +- .../components/expression-editor/style.scss | 9 ++ .../src/components/condition-grid.props.ts | 12 +- .../filter-condition-grid.component.tsx | 4 +- .../components/sort-editor-grid.component.tsx | 4 +- .../src/composition/use-condition-data.ts | 130 ++++++++---------- .../src/composition/use-fields-tree.tsx | 7 +- .../src/filter-condition-editor.component.tsx | 3 +- .../src/filter-condition-editor.props.ts | 16 +++ .../src/schema/filter-condition-editor.json | 17 +++ .../lookup-selected-list.component.tsx | 10 ++ .../lookup/src/composition/use-user-data.ts | 4 +- .../converters/lookup-property.converter.ts | 11 +- .../property-config/lookup.property-config.ts | 87 +++++++----- .../modal/src/composition/modal.service.tsx | 5 + .../components/modal/src/composition/type.ts | 1 + .../modal/src/composition/use-draggable.ts | 2 + .../components/modal/src/modal.component.tsx | 2 +- .../components/notify/src/notify.props.ts | 3 +- .../components/notify/src/notify.service.tsx | 25 ++++ .../composition/entity/expression-property.ts | 23 +++- 30 files changed, 375 insertions(+), 161 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index cc1470b712c..24715f23d53 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -665,7 +665,7 @@ export default defineComponent({ const btnTodayStyle = computed(() => { return (date: any) => { - const todayIsDisable = refDisableDate.isDisabledDate(date); + const todayIsDisable = refDisableDate.isDisabledDate(props.showTime ? date : { year: date.year, month: date.month, day: date.day }); return { "pointer-events": todayIsDisable ? "none" : "auto", opacity: todayIsDisable ? 0.3 : 1 diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx index ad7f4b98ec5..4d974abac56 100644 --- a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx @@ -1,19 +1,37 @@ import { computed, defineComponent, onMounted, ref } from "vue"; import { entityVariableProps } from "./entity-variable.props"; import FEntitiesTree from "../entity-tree/entity-treeview.component"; +import { FButtonEdit } from "@farris/ui-vue/components/button-edit"; + +type TreeNode = { + data: { name: string, bindingPath: string }, + children: TreeNode[] +} export default defineComponent({ name: 'entity-variable', props: entityVariableProps, - emits: ['variableItemDblClick', 'entityItemDblClick'], + emits: ['variableItemDblClick', 'entityItemDblClick', 'fieldClick'], setup(props, context) { const currentExpandName = ref('dataEntity'); const dataSource = ref(props.dataSource); const { entities, variables } = dataSource.value; + const searchFieldValue = ref(''); + const fieldsDataSource = ref(entities?.fields || []); - const entityTreeDisplayFormat = (cell, data) => { - return `${data.raw['name']} [${data.raw['bindingPath']}]`; + const onFieldClick = ($event, data) => { + $event.stopPropagation(); + context.emit('fieldClick', { $event, item: data.raw }); + }; + + const entityTreeDisplayFormat = (cell, data) => { + const textContent = `${data.raw['name']} [${data.raw['bindingPath']}]`; + return
      + {textContent} + +
      ; }; const variableExpandStatus = ref({}); @@ -54,7 +72,7 @@ export default defineComponent({ return (variableTypeName: string) => { return { "f-icon f-icon-arrow-chevron-down": variableExpandStatus.value[variableTypeName], - "f-icon f-icon-arrow-chevron-right":!variableExpandStatus.value[variableTypeName] + "f-icon f-icon-arrow-chevron-right": !variableExpandStatus.value[variableTypeName] }; }; }); @@ -68,7 +86,7 @@ export default defineComponent({ }; }); - function onVariableTypeClick($event:MouseEvent, type: string) { + function onVariableTypeClick($event: MouseEvent, type: string) { $event.stopPropagation(); variableExpandStatus.value = variableExpandStatus.value || {}; variableExpandStatus.value[type] = !variableExpandStatus.value[type]; @@ -80,12 +98,12 @@ export default defineComponent({ } function onVariableItemDblClick($event: MouseEvent, variableItem: any) { - context.emit('variableItemDblClick', {$event, item: variableItem}); + context.emit('variableItemDblClick', { $event, item: variableItem }); } - function onFieldDblclick({$event, node}) { + function onFieldDblclick({ $event, node }) { context.emit('entityItemDblClick', { - $event, + $event, item: node.data, entityCode: entities?.entityCode, parentCodes: node.data.parents.join('.') @@ -93,8 +111,8 @@ export default defineComponent({ } function renderEntities() { - return ; + return ; } function renderVariables() { @@ -138,6 +156,62 @@ export default defineComponent({ }); + // 核心递归函数(优化版) + function searchTree(node: TreeNode, keyword: string): TreeNode | null { + // 先处理子节点(深度优先) + const filteredChildren = node.children + .map(child => searchTree(child, keyword)) + .filter(child => child !== null) as TreeNode[]; + + // 判断当前节点是否匹配 + const isMatch = node.data.name + .toLowerCase() + .includes(keyword.toLowerCase()) || node.data.bindingPath.toLowerCase().includes(keyword.toLowerCase()); + + // 构造返回条件 + if (isMatch) { + // 当前节点匹配时,保留完整子结构 + return { + data: { ...node.data }, + children: node.children // 注意这里保留原始子节点 + }; + } else if (filteredChildren.length > 0) { + // 子节点有匹配时,返回过滤后的子结构 + return { + data: { ...node.data }, + children: filteredChildren + }; + } + + return null; + } + + function searchForest(trees: TreeNode[], keyword: string): TreeNode[] { + // 处理每个根节点并过滤空结果 + return trees + .map(root => searchTree(root, keyword)) + .filter(node => node !== null) as TreeNode[]; + } + + + function onSearch() { + const result = searchForest(entities?.fields || [], searchFieldValue.value); + fieldsDataSource.value = result; + + } + + function onClearSearchValue() { + // 加载所有实体数据 + fieldsDataSource.value = entities?.fields || []; + } + + function onEnterHandler($event: KeyboardEvent) { + if ($event.key === 'Enter') { + onSearch(); + } + } + + return () => { return
        @@ -146,7 +220,19 @@ export default defineComponent({ 数据实体
      -
      +
      +
      + '} + enableClear={true} + popupOnClick={true} + placeholder={'请输入名称或编码,按回车查询'} + v-model={searchFieldValue.value} + onClickButton={onSearch} + onClear={onClearSearchValue} + onKeyup={onEnterHandler} + > +
      {renderEntities()}
      diff --git a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx index d478934171d..585402dc314 100644 --- a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, inject, onMounted, ref } from "vue"; +import { computed, defineComponent, inject, onMounted, ref, watch } from "vue"; import FTreeView from '@farris/ui-vue/components/tree-view'; import { entityTreeviewProps, EntityTreeviewProps } from "./entity-treeview.props"; @@ -9,6 +9,12 @@ export default defineComponent({ emits: ['dblclickNode'], setup(props: EntityTreeviewProps, context) { const dataSource = ref(props.data); + const treeViewRef = ref(); + + watch(() => props.data, (newValue) => { + dataSource.value = newValue; + treeViewRef.value?.updateDataSource(newValue); + }); const rowOption = { customRowStatus: props.customRowStatus @@ -34,8 +40,8 @@ export default defineComponent({ return () => { return ( -
      - +
      diff --git a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx index afd9b83534e..5449d2bd221 100644 --- a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx @@ -45,6 +45,9 @@ export default defineComponent({ lineNumbers: 'on', lineNumbersMinChars: 3, overviewRulerLanes: 0, + // 关键配置:强制面板溢出可见 + fixedOverflowWidgets: true, + scrollBeyondLastLine: false, // 避免滚动条干扰 scrollbar: { verticalScrollbarSize: 8, horizontalScrollbarSize: 8, diff --git a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx index 001c32343e8..5cf8c605b16 100644 --- a/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/functions/common-functions.component.tsx @@ -14,6 +14,7 @@ export default defineComponent({ const currentFunctionItem = ref(); const expandStatus = ref({}); const searchFunctionValue = ref(''); + const emptyMessage = '没有与搜索条件匹配的项'; const dataSource = ref(props.functionItems); @@ -160,7 +161,7 @@ export default defineComponent({ ); }); } - return
    • 没有与搜索条件匹配的项。
    • ; + return
    • { emptyMessage }
    • ; } @@ -182,7 +183,7 @@ export default defineComponent({ buttonContent={''} enableClear={true} popupOnClick={true} - placeholder={'请输入函数名称'} + placeholder={'请输入函数名称,按回车查询'} v-model={searchFunctionValue.value} onClickButton={onSearch} onClear={onClearSearchValue} diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts index 369d4788aa3..25f7fcecd0a 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/analytical.ts @@ -451,9 +451,6 @@ export const analyticalFunctions = [ type: "Analytical", keyFront: "DefaultFunction", className: "" - }, { - key: "getComputeJsonData", - name: "根据属性名获取JSON串" }, { key: "GetInjectedEntity", name: "根据注入名获取注入对象", diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts index 39ef9d2c298..29d4aa801cb 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/math-number.ts @@ -23,9 +23,6 @@ export const mathFunctions = [ type: "Math", keyFront: "Math", className: "" - }, { - key: "Round", - name: "四舍五入" }, { key: "round", name: "四舍五入", diff --git a/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts b/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts index 808a90aee83..2817e9c26e2 100644 --- a/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts +++ b/packages/ui-vue/components/expression-editor/src/composition/functions-data/translate.ts @@ -36,9 +36,6 @@ export const translateFunctions = [ type: "Translate", keyFront: "DefaultFunction", className: "" - }, { - key: "ToDecimal", - name: "转数值" }, { key: "ToBigDecimal", name: "转数值", @@ -79,9 +76,6 @@ export const translateFunctions = [ type: "Translate", keyFront: "DefaultFunction", className: "" - }, { - key: "ToSingle", - name: "转单精度浮点数" }, { key: "ToFloat", name: "转单精度浮点数", diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 5f3573a87c8..54cfd5a6b01 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -76,6 +76,12 @@ export default defineComponent({ expressionEditorRef.value?.insertText(`${expressionText}`); } + function onEntityItemClick({$event, item}) { + const expression = getFieldExpression(item); + expressionEditorRef.value?.insertText(`${expression}`); + } + + function getExpressionContext() { return expressionEditorRef.value?.getContent(); } @@ -96,6 +102,7 @@ export default defineComponent({ expressionEditorRef.value?.clearText(); } + onMounted(async () => { if (modelValue.value) { const ruleValue = JSON.parse(modelValue.value); @@ -146,8 +153,10 @@ export default defineComponent({ + onVariableItemDblClick={onVariableItemDblClick} + onEntityItemDblClick={onEntityItemDblClick} + onFieldClick={onEntityItemClick}> +
      diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx index 0212c15c93d..64fc596aaac 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx @@ -65,8 +65,8 @@ export default defineComponent({ minWidth: 300, minHeight: 200, showMaxButton: true, - resizeable: true, - draggable: true, + resizeable: false, + draggable: false, // 开启后移动窗口位置,导致monaco编辑器智能感知位置错乱,暂时禁用拖拽 buttons: [ { name: 'reset', diff --git a/packages/ui-vue/components/expression-editor/style.scss b/packages/ui-vue/components/expression-editor/style.scss index e802217734e..e5ee262a457 100644 --- a/packages/ui-vue/components/expression-editor/style.scss +++ b/packages/ui-vue/components/expression-editor/style.scss @@ -116,6 +116,15 @@ } } } + + .monaco-editor .suggest-widget { + z-index: 9999 !important; + } + + .fv-grid-row-selected .entity-field .d-none, + .entity-field:hover .d-none { + display: block !important; + } } /* 隐藏所有错误波浪线 */ diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts index b921e0d4ffd..2820dd93058 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/components/condition-grid.props.ts @@ -1,4 +1,4 @@ -import { PropType } from "vue"; +import { ExtractPropTypes, PropType } from "vue"; import { ExpressionOptions } from "../composition/types"; export const conditionGridProps = { @@ -39,5 +39,15 @@ export const conditionGridProps = { idField: { type: String, default: 'id' + }, + textField: { + type: String, + default: '' + }, + valueField: { + type: String, + default: '' } }; + +export type ConditionGridProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx index a228436a7af..700eabbb95f 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/filter-condition-grid.component.tsx @@ -1,5 +1,5 @@ import { defineComponent, onUpdated, ref, render } from "vue"; -import { conditionGridProps } from "./condition-grid.props"; +import { ConditionGridProps, conditionGridProps } from "./condition-grid.props"; import { FComboList } from "../../../combo-list"; import { FButtonEdit } from '../../../button-edit'; import { FExpressionTextbox } from '../../../expression-editor'; @@ -14,7 +14,7 @@ export default defineComponent({ name: 'filter-condition-grid', props: conditionGridProps, emits: ['insert', 'remove', 'rowClick'], - setup(props, context) { + setup(props: ConditionGridProps, context) { const { compareOperators, leftBracketItems, valueTypes, relationItems, righttBracketItems } = useConstantData(props); diff --git a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx index 4fcc4e9fac0..5a26039c9b5 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/components/sort-editor-grid.component.tsx @@ -3,14 +3,14 @@ import { FComboList } from "../../../combo-list"; import { useConstantData } from "../composition/use-constant-data"; import { useFieldsTree } from "../composition/use-fields-tree"; import { useConditionEditor } from "../composition/use-condition-editor"; -import { conditionGridProps } from "./condition-grid.props"; +import { ConditionGridProps, conditionGridProps } from "./condition-grid.props"; import { SortCondition } from "../composition/types"; export default defineComponent({ name: 'sort-editor-grid', props: conditionGridProps, emits: ['insert','remove', 'rowClick'], - setup(props, context) { + setup(props: ConditionGridProps, context) { const { sortTypes } = useConstantData(); const {renderFieldsComboTree} = useFieldsTree(props); const tbodyRef = ref(); diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts index 1ababd43521..ab72aab5cba 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-condition-data.ts @@ -24,19 +24,19 @@ export function useConditionData(props, conditions) { rbracket: '', relation: FilterRelation.Empty, compare: Compare.Equal, - expresstype:props.singleValue ? ValueType.Value : ValueType.Variable + expresstype: props.singleValue ? ValueType.Value : ValueType.Variable } : { sortField: '', sortType: 'asc' }; - + const canClear = computed(() => { return conditions.value.length > 0; }); const canMove = computed(() => { - return (direction: 'up'| 'down' = 'down') => { + return (direction: 'up' | 'down' = 'down') => { if (conditions.value.length > 1) { if (direction === 'up') { return activeRow.value.index > 0; @@ -59,21 +59,21 @@ export function useConditionData(props, conditions) { } }); } - + conditions.value = [...conditions.value, newItem]; const newIndex = conditions.value.length - 1; activeRow.value = { index: newIndex, condition: newItem }; } - function insertCondition({index}) { + function insertCondition({ index }) { const _newCondition = Object.assign({}, newCondition); if (props.editorType !== 'sort') { - Object.assign({}, _newCondition, { relation: FilterRelation.And }); + Object.assign({}, _newCondition, { relation: FilterRelation.And }); } if (props.insertType === 'above') { - if (index === 0) { + if (index === 0) { conditions.value.unshift(_newCondition); } else { conditions.vlaue.splice(index, 0, _newCondition); @@ -84,7 +84,7 @@ export function useConditionData(props, conditions) { conditions.value = [...conditions.value]; } - function removeCondition({index}) { + function removeCondition({ index }) { conditions.value.splice(index, 1); conditions.value = [...conditions.value]; @@ -104,7 +104,7 @@ export function useConditionData(props, conditions) { if (activeRow.value.index > index) { activeRow.value.index = activeRow.value.index - 1; } else { - activeRow.value.index = activeRow.value.index + 1 ; + activeRow.value.index = activeRow.value.index + 1; } } } @@ -126,7 +126,7 @@ export function useConditionData(props, conditions) { function onMovePrev() { if (activeRow.value) { - const {index} = activeRow.value; + const { index } = activeRow.value; const tempArr = conditions.value.splice(index, 1); conditions.value.splice(index - 1, 0, ...tempArr); @@ -136,7 +136,7 @@ export function useConditionData(props, conditions) { function onMoveNext() { if (activeRow.value) { - const {index} = activeRow.value; + const { index } = activeRow.value; const tempArr = conditions.value.splice(index, 1); conditions.value.splice(index + 1, 0, ...tempArr); @@ -152,78 +152,60 @@ export function useConditionData(props, conditions) { } } - function onSelectRow({index}) { + function onSelectRow({ index }) { activeRow.value = { index: index, condition: conditions.value[index] }; } - function validateCondition() { - const total = conditions.value.length; - if (total) { - - let bracketChecked = true; // 括号是否匹配 - let relationChecked = true; // 关系连接符是否完整 - - if (props.editorType !== 'sort') { - // 清除最后条件的关系符 - conditions.value[total - 1].relation = FilterRelation.Empty; - - // 检查关系连接符 - const emptyRelations = conditions.value - .map((condition: any, index) => { - if ('' + condition.relation === "" + FilterRelation.Empty) { - return { index, filter: condition }; - } - return null; - }) - .filter((condition: any, index) => { - return condition && index !== total - index; - }); - - - if (emptyRelations.length) { - relationChecked = false; - } + function checkBrackets(brackets: string) { + if (brackets.length % 2 !== 0) { return false; } - - let bracketResult = ''; - for (let i = 0; i < total; i++) { - const item = conditions.value[i]; - bracketResult += item.lbracket + item.rbracket; - } - - const l = bracketResult.length ; - if (l % 2 > 0) { - bracketChecked = false; - } else { - for(let i =0; i< l; i++){ - bracketResult = bracketResult.replace('()', ''); - } - bracketChecked = !bracketResult.length; - } + let stack = ''; + for (const char of brackets) { + if (char === '(') { + stack += char; + } else if (char === ')') { + if (!stack.endsWith('(')) { return false; } + stack = stack.slice(0, -1); } + } + return stack.length === 0; + } - // 检查字段是否设置 - const emptyFields = conditions.value.filter((n: any) => !n[fieldName]).length === 0; - - const result = [ - { - result: bracketChecked, - message: '括号不匹配,请检查。' - }, - { - result: relationChecked, - message: '关系设置不完整,请检查。' - }, - { - result: emptyFields, - message: '字段不允许为空,请检查。' - } - ]; + function validateCondition() { + const total = conditions.value.length; + if (!total) { return true; } + + let bracketChecked = true; + let relationChecked = true; - return result.find(n => !n.result); + if (props.editorType !== 'sort') { + // 清除最后条件的关系符 + conditions.value[total - 1].relation = FilterRelation.Empty; + + // 检查关系连接符 + const hasInvalidRelation = conditions.value + .slice(0, -1) // 排除最后一个条件 + .some(condition => + condition.relation === FilterRelation.Empty || !condition.relation + ); + relationChecked = !hasInvalidRelation; + + // 检查括号匹配 + const brackets = conditions.value + .flatMap(item => [item.lbracket, item.rbracket]) + .join(''); + + bracketChecked = checkBrackets(brackets); } - return true; + // 检查字段是否设置 + const emptyFields = conditions.value.some(n => !n[fieldName]); + + return [ + { result: bracketChecked, message: '括号不匹配,请检查。' }, + { result: relationChecked, message: '关系设置不完整,请检查。' }, + { result: !emptyFields, message: '字段不允许为空,请检查。' } + ].find(n => !n.result); } diff --git a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx index 203482df83e..e1282b41621 100644 --- a/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx +++ b/packages/ui-vue/components/filter-condition-editor/src/composition/use-fields-tree.tsx @@ -1,15 +1,16 @@ import { FComboTree } from "../../../combo-tree"; +import { ConditionGridProps } from "../components/condition-grid.props"; import { treeNodeStatus } from "./use-constant-data"; -export function useFieldsTree(props) { +export function useFieldsTree(props: ConditionGridProps) { function renderFieldsComboTree(model: any, fields: any[], bindFieldName = 'filterField') { return { return
      selectionState.value, (selections) => { selectedGridRef.value?.updateDataSource(selections || []); + if (removeRowIndex.value > -1) { + selectedGridRef.value?.scrollToRowByIndex(removeRowIndex.value); + } }); watch(() => modalElementRef.value, (modalElement) => { diff --git a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts index 9e736b39166..297ff872931 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts @@ -42,7 +42,7 @@ export function useUserData(props: LookupProps, useHttpComposition: UseHttpCompo const userDataState = reactive({ key: dataKey.value, data: {} }); function getUserData() { - if (props.enableFavorite && httpService) { + if (httpService) { return httpService.getSettings(userDataState.key).then(res => { if (res && res.textValue) { userDataState.data = JSON.parse(res.textValue); @@ -67,7 +67,7 @@ export function useUserData(props: LookupProps, useHttpComposition: UseHttpCompo } function saveUserData() { - if (props.enableFavorite && httpService) { + if (props.enableUserData && httpService) { const { key, data } = userDataState; const configData = { configkey1: key, diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index 4328292e8a0..502ccc418bb 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -201,10 +201,17 @@ export const lookupPaginationConverter = { convertTo: (schema: Record, propertyKey: string, propertyValue: any) => { schema.editor.pagination = schema.editor.pagination || {}; if (propertyKey === 'sizeLimits') { - const limitStr = propertyValue.map((item) => { + const limitItems = propertyValue.map((item) => { return item.value; }); - schema.editor.pagination[propertyKey] = limitStr; + schema.editor.pagination[propertyKey] = limitItems; + + // check pagesize in pagelist + const pageSize = schema.editor?.pagination?.size ?? 20; + if (!limitItems.includes(pageSize)) { + schema.editor.pagination.size = limitItems[0]; + } + return; } diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 6820848b434..7cf0e5cf48f 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -33,17 +33,12 @@ export class LookupPropertyConfig extends InputBaseProperty { private freeInputEditor: any = { ...this.comboListEditor, editable: false }; getExpressionConfig(propertyData: any, type: 'Field' | 'Button' | 'Container') { - return new ExpressionProperty(this.formSchemaUtils).getExpressionConfig( - propertyData, - 'Field', - ['validate', 'dataPicking'], - (rule: any) => { - if (rule && rule.value.trim() && rule.type === 'dataPicking') { - propertyData.dictPickingExpressionId = rule.id; - } else { - delete propertyData.dictPickingExpressionId; - } - }); + const suportTypes = ['validate',]; + if (propertyData.type === 'form-group') { + suportTypes.push('dataPicking'); + } + + return new ExpressionProperty(this.formSchemaUtils).getExpressionConfig(propertyData, 'Field', suportTypes); } getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance | null) { @@ -55,7 +50,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const basic = this.getBasicProperties(propertyData, componentInstance); const behavior = this.getBehaviorConfig(propertyData); const appearance = this.getAppearanceProperties(propertyData, componentInstance); - const lookup = this.getLookupConfig(propertyData.editor); + const lookup = this.getLookupConfig(propertyData); const eventsEditor = this.getEventPropConfig(propertyData); const dialog = this.getDialogPropertyConfig(propertyData); const pager = this.getPageConfig(propertyData.editor); @@ -64,7 +59,7 @@ export class LookupPropertyConfig extends InputBaseProperty { // 'compute', 'dependency', const expressons = this.getExpressionConfig(propertyData, 'Field'); - const categories: any = { + const categories: any = { basic, appearance, behavior, @@ -88,18 +83,36 @@ export class LookupPropertyConfig extends InputBaseProperty { return this.getPropertyConfig(propertyData, null).categories; } - private isSimpleStringField() { - const fullPath = this.designViewModelField?.path || ''; - if (fullPath) { - const field = fullPath.indexOf('.') > -1 ? fullPath.split('.')[0] : fullPath; - const fields = this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId); - if (fields && fields.length) { - const fieldInfo = fields.map(node => node.data).find(data => data.code === field); - return fieldInfo?.type?.$type === "StringType" && fieldInfo?.$type === 'SimpleField'; + private flattenTreeNodes(treeNodes: any[]): any[] { + return treeNodes.reduce((result, item) => { + result.push(item); + if (item.children?.length) { + result.push(...this.flattenTreeNodes(item.children)); } - return false; - } - return true; + return result; + }, [] as any[]); + } + + private isSimpleStringField(): boolean { + const fullPath = this.designViewModelField?.path || ''; + if (!fullPath || !fullPath.includes('.')) { return true; } + + const fieldList = fullPath.split('.'); + const fields = this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId); + if (!fields?.length) { return false; } + + const fieldInfo = fields.find(item => item.data.code === fieldList[0]); + if (!fieldInfo) { return false; } + + const allFields = [fieldInfo, ...this.flattenTreeNodes(fieldInfo.children)]; + return !fieldList + .reduce((paths, current, index) => + [...paths, index ? `${paths[index - 1]}.${current}` : current], + [] as string[] + ) + .some(path => + allFields.find(field => field.data.path === path)?.data?.type?.$type === 'EntityType' + ); } getBehaviorConfig(propertyData) { @@ -114,8 +127,8 @@ export class LookupPropertyConfig extends InputBaseProperty { editor: this.visibleEditor } }, - setPropertyRelates: (changeObject, propertyData) => { - this.afterMutilEditorChanged(propertyData, changeObject); + setPropertyRelates: (changeObject, newPropertyData) => { + this.afterMutilEditorChanged(newPropertyData, changeObject); } }; } @@ -130,8 +143,8 @@ export class LookupPropertyConfig extends InputBaseProperty { return editorOptions.displayType ? editorOptions.displayType.toUpperCase() : ''; } - private getLookupConfig(editorOptions: any) { - + private getLookupConfig(propertyData: any) { + const editorOptions = propertyData.editor; const getRemoteParams = () => { const viewModelId = this.formSchemaUtils.getFormSchema().module.entity[0].id; const formBasicInfo = this.formSchemaUtils.getFormMetadataBasicInfo(); @@ -141,6 +154,17 @@ export class LookupPropertyConfig extends InputBaseProperty { return { description: "Basic Infomation", title: "编辑器", + setPropertyRelates: (changeObject, newPropertyData: any) => { + if (!changeObject) { + return; + } + switch (changeObject.propertyID) { + case 'readonly': + case 'required': + this.afterMutilEditorChanged(newPropertyData, changeObject); + break; + } + }, properties: { readonly: { description: "", @@ -509,18 +533,18 @@ export class LookupPropertyConfig extends InputBaseProperty { $converter: lookupDialogOptionsConverter }, width: { - description: "窗口宽度", + description: "窗口宽度,最小值:300px", title: "宽度", type: "number", refreshPanelAfterChanged: true, $converter: lookupDialogOptionsConverter, editor: { ...this.numberEditor, - min: this.showNavigatiorWidth(propertyData.editor)? 520: 300 + min: this.showNavigatiorWidth(propertyData.editor) ? 520 : 300 } }, height: { - description: "窗口高度", + description: "窗口高度,最小值:200px", title: "高度", type: "number", $converter: lookupDialogOptionsConverter, @@ -538,6 +562,7 @@ export class LookupPropertyConfig extends InputBaseProperty { visible: this.getDisplayType(propertyData.editor).includes('NAV') }, navigatorWidth: { + description: "导航栏宽度,最小200px, 最大为窗口宽度减去200px", title: "导航栏宽度", type: "number", $converter: lookupDialogOptionsConverter, diff --git a/packages/ui-vue/components/modal/src/composition/modal.service.tsx b/packages/ui-vue/components/modal/src/composition/modal.service.tsx index a8c2eef14c5..2339bf9910c 100644 --- a/packages/ui-vue/components/modal/src/composition/modal.service.tsx +++ b/packages/ui-vue/components/modal/src/composition/modal.service.tsx @@ -36,6 +36,7 @@ function createModalInstance(options: ModalOptions) { const modalClosedCallback = options.closedCallback || (($event: Event) => { }); const modalResizedCallback = options.resizeHandle || (($event: Event) => { }); + const modalStopMoveCallback = options.stopMoveHandle || (($event: Event) => { }); const contentRender = getContentRender(options); @@ -70,6 +71,7 @@ function createModalInstance(options: ModalOptions) { fitContent={options.fitContent == null ? true : options.fitContent} onClosed={onClosed} onResize={modalResizedCallback} + onStopMove={modalStopMoveCallback} > {contentRender && contentRender(app)} @@ -171,6 +173,8 @@ export default class ModalService { const modalClosedCallback = modalOptions.value.closedCallback || (($event?: Event, from?: string) => { }); const modalResizedCallback = modalOptions.value.resizeHandle || (($event: Event) => { }); + const modalStopMoveCallback = options.stopMoveHandle || (($event: Event) => { }); + let modalInstance: VNode | null; const contentRender = getContentRender(modalOptions.value); @@ -228,6 +232,7 @@ export default class ModalService { onClosed={destroy} onResize={modalResizedCallback} onEsc={onEsc} + onStopMove={modalStopMoveCallback} > {contentRender && contentRender(this.app)} diff --git a/packages/ui-vue/components/modal/src/composition/type.ts b/packages/ui-vue/components/modal/src/composition/type.ts index 2b1ba1d30da..7fcca8f0a58 100644 --- a/packages/ui-vue/components/modal/src/composition/type.ts +++ b/packages/ui-vue/components/modal/src/composition/type.ts @@ -36,6 +36,7 @@ export interface ModalOptions { rejectCallback?: () => void; closedCallback?: ($event?: Event, from?: 'esc' | 'icon' | 'button') => void; resizeHandle?: (event: IResizeEvent) => void; + stopMoveHandle?: (event?: MouseEvent) => void; enableEsc?: boolean; dialogType?: string; src?: string; diff --git a/packages/ui-vue/components/modal/src/composition/use-draggable.ts b/packages/ui-vue/components/modal/src/composition/use-draggable.ts index 9d255607991..9171a29d099 100644 --- a/packages/ui-vue/components/modal/src/composition/use-draggable.ts +++ b/packages/ui-vue/components/modal/src/composition/use-draggable.ts @@ -135,6 +135,8 @@ export function useDraggable(props: any, context: any, canMove: Ref) { dragTarget.value?.classList.remove('ng-dragging'); + context.emit('stopMove'); + document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', stopMove); } diff --git a/packages/ui-vue/components/modal/src/modal.component.tsx b/packages/ui-vue/components/modal/src/modal.component.tsx index 740fb360e21..e194c8e7824 100644 --- a/packages/ui-vue/components/modal/src/modal.component.tsx +++ b/packages/ui-vue/components/modal/src/modal.component.tsx @@ -25,7 +25,7 @@ import { useEnter, useEsc } from './composition/use-shortcut'; export default defineComponent({ name: 'FModal', props: modalProps, - emits: ['update:modelValue', 'accept', 'cancel', 'closed', 'resize', 'esc', 'enter'] as (string[] & ThisType) | undefined, + emits: ['update:modelValue', 'accept', 'cancel', 'closed', 'resize', 'esc', 'enter', 'stopMove'] as (string[] & ThisType) | undefined, setup(props: ModalProps, context: SetupContext) { const width = ref(props.width || 300); const height = ref(props.height || 200); diff --git a/packages/ui-vue/components/notify/src/notify.props.ts b/packages/ui-vue/components/notify/src/notify.props.ts index 5ff181fc2c4..fef0ef04917 100644 --- a/packages/ui-vue/components/notify/src/notify.props.ts +++ b/packages/ui-vue/components/notify/src/notify.props.ts @@ -61,7 +61,8 @@ export const notifyProps = { bottom: { type: Number }, id: { type: String }, animate: { type: String as PropType, default: 'fadeIn' }, - options: { type: Object as PropType } + options: { type: Object as PropType }, + safeHtml: { type: Boolean, default: true } }; export type NotifyProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/notify/src/notify.service.tsx b/packages/ui-vue/components/notify/src/notify.service.tsx index f33ee844153..9b23449aed1 100644 --- a/packages/ui-vue/components/notify/src/notify.service.tsx +++ b/packages/ui-vue/components/notify/src/notify.service.tsx @@ -8,6 +8,26 @@ export default class NotifyService { globalConfig: Partial = reactive({}); + + escapeAllHtml(htmlString: string) { + if (typeof htmlString !== 'string' || !htmlString) { + return ''; + } + + // 创建临时容器(内存操作,不污染 DOM) + const container = document.createElement('div'); + // 核心安全转义逻辑:浏览器自动处理转义 + container.textContent = htmlString || ''; + + // 获取完全转义后的内容(含 < > & 等字符转义) + const escapedContent = container.innerHTML; + return escapedContent + .replace(/ /g, ' ') // 普通空格转义 + .replace(/\\n/g, '
      ') // 保留换行 + .replace(/\\t/g, '    ') // 保留制表符 + .replace(/\\r/g, ''); // 移除回车(通常不需要单独处理) + } + private createNotifyInstance(options: Partial): App { const self = this; @@ -15,6 +35,7 @@ export default class NotifyService { timeout: 3000, position: 'bottom-right', showCloseButton: true, + safeHtml: true }; const notifySettings: any = Object.assign(defulatConfig, this.globalConfig, { ...options }); @@ -42,6 +63,10 @@ export default class NotifyService { } } + if (notifySettings.safeHtml && notifySettings.options?.message) { + notifySettings.options.message = self.escapeAllHtml(notifySettings.options.message); + } + onUnmounted(() => { document.body.removeChild(container); }); diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 750c1ef45ba..37bb496cbe7 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -217,7 +217,7 @@ export class ExpressionProperty { value: expressionValue }; - if (ruleType === 'validate' || ruleType === 'dataPicking') { + if (ruleType === 'validate' || ruleType === 'dataPicking' || ruleType === 'required') { rule.message = message; } @@ -257,7 +257,7 @@ export class ExpressionProperty { if (isValueEmpty(newRule)) { expressionItem.rules = expressionItem.rules.filter((rule) => rule.id !== newRule.id); } else { - ruleItem.value = newRule.value; + Object.assign(ruleItem, newRule); if (ruleType === 'validate' && propertyData.type === 'form-group') { ruleItem.elementId = propertyData.id; @@ -303,9 +303,18 @@ export class ExpressionProperty { const rule = schemaService.getExpressionRuleValue(expressionId, ruleType || propertyKey); return rule && rule.value || ''; }, - convertTo: (schema: Record, propertyKey: string, propertyValue: any[], - schemaService, componentId - ) => { + convertTo: (schema: Record, propertyKey: string, propertyValue: any, schemaService, componentId) => { + if (propertyKey === 'dataPicking' && propertyValue?.target) { + const dictPickingExpressionId = `${propertyValue.target}_dataPicking`; + const hasValidRule = propertyValue.rules?.some(rule => + rule.id === dictPickingExpressionId && rule.value + ); + if (hasValidRule) { + schema.dictPickingExpressionId = dictPickingExpressionId; + } else { + delete schema.dictPickingExpressionId; + } + } schemaService.updateExpression(propertyValue); } }; @@ -325,7 +334,7 @@ export class ExpressionProperty { type: "expression-editor", singleExpand: false, dialogTitle: `${this.expressionNames[name]}编辑器`, - showMessage: name === 'validate' || name === 'dataPicking', + showMessage: name === 'validate' || name === 'dataPicking' || name === 'required', showMessageType: name === 'dataPicking', beforeOpen: () => { return this.onBeforeOpenExpression(propertyData, name, targetType); @@ -375,7 +384,7 @@ export class ExpressionProperty { return { dialogTitle: `${this.expressionNames[expressionType]}编辑器`, singleExpand: false, - showMessage: expressionType === 'require', + showMessage: expressionType === 'required', beforeOpen: () => { return this.onBeforeOpenExpression(propertyData, expressionType, targetType); }, -- Gitee From 905a5dabd29542462db9ab53e82b8283db762463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 11 Apr 2025 16:17:21 +0800 Subject: [PATCH 128/156] =?UTF-8?q?fix:=20datepicker=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=9C=88=E8=A7=86=E5=9B=BE=E4=B8=8E=E5=B9=B4=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 25 +++++++++++++++++-- .../date-picker.property-config.ts | 8 +++--- .../ui-vue/demos/date-picker/month_view.vue | 21 ++++++++++++++++ .../ui-vue/demos/date-picker/year_view.vue | 21 ++++++++++++++++ .../docs/components/date-picker/index.md | 13 +++++++--- 5 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 packages/ui-vue/demos/date-picker/month_view.vue create mode 100644 packages/ui-vue/demos/date-picker/year_view.vue diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 24715f23d53..b0e0167c374 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -311,8 +311,8 @@ export default defineComponent({ } function navigateToYearView(inPeriod: boolean) { - selectingMonth.value = false; - selectingYear.value = !selectingYear.value; + selectingMonth.value =selectMode.value === 'month'? !selectingMonth.value : false; + selectingYear.value = selectMode.value === 'year'? true: !selectingYear.value; } @@ -502,6 +502,12 @@ export default defineComponent({ year: currentMonth.year || 1, displayTextOfYear: `${currentMonth.year}` }; + + if (selectMode.value === 'month') { + const selectedMonth = cloneDeep(currentMonth); + selectedMonth.day = 1; + context.emit('datePicked', selectedMonth); + } } function onKeyDownMonthView($event: any) { } @@ -550,6 +556,13 @@ export default defineComponent({ year: currentYear.year || 1, displayTextOfYear: `${currentYear.year}` }; + + if (selectMode.value === 'year') { + const selectedYear = cloneDeep(currentYear); + selectedYear.month = 1; + selectedYear.day = 1; + context.emit('datePicked', selectedYear); + } } function onKeyDownYearView($event: any) { } @@ -649,6 +662,14 @@ export default defineComponent({ timeValue.value = formatTo(dateValue.value, timeFormat); formatDate(); } + + if (selectMode.value === 'month') { + selectingMonth.value = true; + selectingYear.value = false; + } else if (selectMode.value === 'year') { + selectingYear.value = true; + selectingMonth.value = false; + } }); const onValueChangeHandler = (textValue: TimeValueText) => { diff --git a/packages/ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts b/packages/ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts index edb255b2ad8..b3848504ab5 100644 --- a/packages/ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts +++ b/packages/ui-vue/components/date-picker/src/property-config/date-picker.property-config.ts @@ -42,8 +42,8 @@ export class DatePickerProperty extends InputBaseProperty { type: "string", editor: { type: 'date-picker', - displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', - valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + displayFormat: 'yyyy-MM-dd' + (propertyData?.editor?.showTime ? ' HH:mm:ss' : ''), + valueFormat: 'yyyy-MM-dd' + (propertyData?.editor?.showTime ? ' HH:mm:ss' : ''), minDate: propertyData?.editor?.minDate || '1900-01-01', maxDate: '9999-12-31', showTime: propertyData?.editor?.showTime, @@ -56,8 +56,8 @@ export class DatePickerProperty extends InputBaseProperty { type: "string", editor: { type: 'date-picker', - displayFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', - valueFormat: propertyData?.editor?.valueFormat || 'yyyy-MM-dd', + displayFormat: 'yyyy-MM-dd' + (propertyData?.editor?.showTime ? ' HH:mm:ss' : ''), + valueFormat: 'yyyy-MM-dd' + (propertyData?.editor?.showTime ? ' HH:mm:ss' : ''), minDate: '1900-01-01', maxDate: propertyData?.editor?.maxDate || '9999-12-31', showTime: propertyData?.editor?.showTime, diff --git a/packages/ui-vue/demos/date-picker/month_view.vue b/packages/ui-vue/demos/date-picker/month_view.vue new file mode 100644 index 00000000000..72bf436a107 --- /dev/null +++ b/packages/ui-vue/demos/date-picker/month_view.vue @@ -0,0 +1,21 @@ + + diff --git a/packages/ui-vue/demos/date-picker/year_view.vue b/packages/ui-vue/demos/date-picker/year_view.vue new file mode 100644 index 00000000000..5f7201c26ba --- /dev/null +++ b/packages/ui-vue/demos/date-picker/year_view.vue @@ -0,0 +1,21 @@ + + diff --git a/packages/ui-vue/docs/components/date-picker/index.md b/packages/ui-vue/docs/components/date-picker/index.md index 20f33a4f66a..25d0646b244 100644 --- a/packages/ui-vue/docs/components/date-picker/index.md +++ b/packages/ui-vue/docs/components/date-picker/index.md @@ -84,16 +84,23 @@ Date Picker 组件用来选择日期。 ::: -## 日期范围 +## 月份视图 :::vdemo ```vue -{demos/date-picker/date-range.vue} +{demos/date-picker/month_view.vue} ``` - ::: +## 年视图 + +:::vdemo + +```vue +{demos/date-picker/year_view.vue} +``` +::: ## 类型 -- Gitee From 88a42101734d0f9cea543e1876002e4583d584eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 12 Apr 2025 13:58:39 +0800 Subject: [PATCH 129/156] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E7=BC=96=E8=BE=91=E5=99=A8=E6=99=BA=E8=83=BD?= =?UTF-8?q?=E6=84=9F=E8=A7=89=E9=9D=A2=E6=9D=BF=E6=98=BE=E7=A4=BA=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/expression-code.component.tsx | 18 ++++++++--- .../src/expression-editor.component.tsx | 31 +++++++++---------- .../src/expression-textbox.component.tsx | 24 +++++++------- .../components/expression-editor/style.scss | 11 +++++++ 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx index 5449d2bd221..3f4b161c470 100644 --- a/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/expression-code.component.tsx @@ -46,7 +46,7 @@ export default defineComponent({ lineNumbersMinChars: 3, overviewRulerLanes: 0, // 关键配置:强制面板溢出可见 - fixedOverflowWidgets: true, + fixedOverflowWidgets: false, scrollBeyondLastLine: false, // 避免滚动条干扰 scrollbar: { verticalScrollbarSize: 8, @@ -61,8 +61,18 @@ export default defineComponent({ codeValues.value = newValue; editorInstance?.setValue(newValue); }); + + + const codeEditorStyles = ref(); + const resizeObserver = new ResizeObserver(entries => { editorInstance?.layout(); + + const { width, height } = entries[0].contentRect; + codeEditorStyles.value = { + width: `${width - 1}px`, + height: `${height}px` + }; }); function getContent() { @@ -89,7 +99,8 @@ export default defineComponent({ onMounted(() => { initMonacoEditor(); - editorContainer.value && resizeObserver.observe(editorContainer.value); + editorContainer.value && resizeObserver.observe(editorContainer.value.parentElement); + }); onBeforeUnmount(() => { @@ -112,7 +123,6 @@ export default defineComponent({ setContent(''); } - context.expose({ getContent, insertText, @@ -121,7 +131,7 @@ export default defineComponent({ }); return () => { - return
      ; + return
      ; }; } }); diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 54cfd5a6b01..389a74f374c 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -40,15 +40,15 @@ export default defineComponent({ const modelValue = ref(props.modelValue); const expressionEditorRef = ref(); - const MESSAGE_TYPES =[ + const MESSAGE_TYPES = [ { label: '提示', value: 'info' }, { label: '警告', value: 'warning' }, { label: '错误', value: 'error' } ]; const { getFunctionExpression, getContextVariableExpression, - resetFunctionItems, getFieldExpression, getExpressionCodeValue, - getExpressionTextValue } = useExpression(props, commonFunctions, props.variables); + resetFunctionItems, getFieldExpression, getExpressionCodeValue, + getExpressionTextValue } = useExpression(props, commonFunctions, props.variables); const functionItems = ref(resetFunctionItems()); @@ -56,17 +56,17 @@ export default defineComponent({ const { onFunctionSearch } = useSearchFunction(props, functionItems); - function onInsertFunction({$event, item}) { + function onInsertFunction({ $event, item }) { const expression = getFunctionExpression(item); expressionEditorRef.value?.insertText(expression); } - function onVariableItemDblClick({$event, item}) { + function onVariableItemDblClick({ $event, item }) { const expression = getContextVariableExpression(item); expressionEditorRef.value?.insertText(expression); } - function onEntityItemDblClick({$event, item, parentCodes, entityCode}) { + function onEntityItemDblClick({ $event, item, parentCodes, entityCode }) { const expression = getFieldExpression(item); let expressionText = `${parentCodes}.${expression}`; @@ -76,7 +76,7 @@ export default defineComponent({ expressionEditorRef.value?.insertText(`${expressionText}`); } - function onEntityItemClick({$event, item}) { + function onEntityItemClick({ $event, item }) { const expression = getFieldExpression(item); expressionEditorRef.value?.insertText(`${expression}`); } @@ -89,20 +89,19 @@ export default defineComponent({ function getExpressionValue() { const displayText = expressionEditorRef.value?.getContent(); return { - value: getExpressionCodeValue(displayText), + value: getExpressionCodeValue(displayText), message: validateMessage.value, messageType: messageType.value }; } const expressionDisplayText = ref(''); - + function resetExpression() { expressionEditorRef.value?.clearText(); } - onMounted(async () => { if (modelValue.value) { const ruleValue = JSON.parse(modelValue.value); @@ -124,14 +123,14 @@ export default defineComponent({
      - +
      - +
      {props.showMessage &&
      提示信息: @@ -152,7 +151,7 @@ export default defineComponent({
      } - diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx index 64fc596aaac..d28972cf004 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx @@ -11,7 +11,7 @@ export default defineComponent({ props: expressionTextboxProps, setup(props: ExpressionTextboxProps, context) { const notifyService: FNotifyService = inject(F_NOTIFY_SERVICE_TOKEN) as FNotifyService; - const loadingService: any | null = inject('FLoadingService'); + const loadingService: any | null = inject('FLoadingService'); const buttonIcon = ''; const modelValue = ref(props.modelValue); @@ -24,18 +24,18 @@ export default defineComponent({ const messageType = ref('info'); async function onSubmit() { - const {value: expressionValue, message: validMessage, messageType: validMessageType} = editorRef.value.getExpressionValue(); + const { value: expressionValue, message: validMessage, messageType: validMessageType } = editorRef.value.getExpressionValue(); validateMessage.value = validMessage; messageType.value = validMessageType; if (props.beforeSubmit && typeof props.beforeSubmit === 'function') { - const result = await props.beforeSubmit({notifyService, expressionValue}); + const result = await props.beforeSubmit({ notifyService, expressionValue }); if (typeof result === 'boolean' && !result) { return false; } else if (typeof result === 'object') { - const {canClose, message} = result; + const { canClose, message } = result; if (!canClose) { - message && notifyService?.error({message}); + message && notifyService?.error({ message }); return false; } } @@ -65,8 +65,8 @@ export default defineComponent({ minWidth: 300, minHeight: 200, showMaxButton: true, - resizeable: false, - draggable: false, // 开启后移动窗口位置,导致monaco编辑器智能感知位置错乱,暂时禁用拖拽 + resizeable: true, + draggable: true, // 开启后移动窗口位置,导致monaco编辑器智能感知位置错乱,暂时禁用拖拽 buttons: [ { name: 'reset', @@ -100,7 +100,7 @@ export default defineComponent({ if (props.beforeOpen) { try { loadingService?.show(); - const result = await props.beforeOpen({notifyService}); + const result = await props.beforeOpen({ notifyService }); if (result) { entities.value = result.entities || {}; variables.value = result.variables || {}; @@ -111,12 +111,12 @@ export default defineComponent({ return true; } } catch (error) { - notifyService?.error({message: '获取数据失败!'}); + notifyService?.error({ message: '获取数据失败!' }); return false; } finally { loadingService?.clearAll(); } - + } return true; @@ -137,7 +137,7 @@ export default defineComponent({ return Date: Sat, 12 Apr 2025 14:06:17 +0800 Subject: [PATCH 130/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4layout?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/expression-editor/style.scss | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/ui-vue/components/expression-editor/style.scss b/packages/ui-vue/components/expression-editor/style.scss index 98afa004e70..5ce938c0e6f 100644 --- a/packages/ui-vue/components/expression-editor/style.scss +++ b/packages/ui-vue/components/expression-editor/style.scss @@ -129,12 +129,11 @@ .expression-code-editor { position: fixed; z-index: 201; + } - .f-layout-horizontal-resize-proxy, - .f-layout-vertical-resize-proxy { - z-index: 300!important; - } - + .f-layout-horizontal-resize-proxy, + .f-layout-vertical-resize-proxy { + z-index: 300!important; } } -- Gitee From cb2e4ec0c8134a8332a7905c6f78018ab63ad144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 12 Apr 2025 16:02:02 +0800 Subject: [PATCH 131/156] =?UTF-8?q?fix:=20=E9=9A=90=E8=97=8F=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E7=BC=96=E8=BE=91=E5=99=A8=E4=B8=AD=E4=B8=8D?= =?UTF-8?q?=E8=A2=AB=E6=94=AF=E6=8C=81=E7=9A=84=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/entities-variable/entity-model.ts | 3 ++- .../entities-variable/entity-variable.component.tsx | 2 +- .../src/composition/entity/expression-property.ts | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts index a9ccec6b087..6954050dba1 100644 --- a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-model.ts @@ -12,7 +12,8 @@ export interface VariableModel { export interface VariableModels { [key: string]: { name: string, - items: VariableModel[] + items: VariableModel[], + visible: boolean } } diff --git a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx index 4d974abac56..8e6d6379599 100644 --- a/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/entities-variable/entity-variable.component.tsx @@ -119,7 +119,7 @@ export default defineComponent({ if (variables) { return
        {Object.keys(variables).map((key) => { - return
      • + return variables[key].visible &&
      • { onVariableTypeClick($event, key); }}> {variables[key].name} diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index 37bb496cbe7..d576768cbac 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -183,11 +183,13 @@ export class ExpressionProperty { variables: { session: { name: '系统变量', - items: this.sessionVariables + items: this.sessionVariables, + visible: false }, forms: { name: '表单变量', - items: this.getContextFormVariables() + items: this.getContextFormVariables(), + visible: true } } }; -- Gitee From 7acba43bd285d76c1af2b598baf5354b984d73fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 15 Apr 2025 15:45:59 +0800 Subject: [PATCH 132/156] =?UTF-8?q?fix:=20=E8=AE=BE=E8=AE=A1=E6=97=B6?= =?UTF-8?q?=E7=A7=BB=E9=99=A4lookup=E7=BB=84=E4=BB=B6=E4=B8=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 746dedbc4f2..6d9ff7dd2ba 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -207,7 +207,7 @@ export class LookupPropertyConfig extends InputBaseProperty { type: "boolean", $converter: lookupDefaultConverter, editor: this.freeInputEditor, - visible: !!editorOptions.editable + visible: false // !!editorOptions.editable }, enableClear: { title: "启用清除按钮", -- Gitee From 28144b00e4b06d2a91df657c0e25ef89df8d2291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 15 Apr 2025 16:51:13 +0800 Subject: [PATCH 133/156] =?UTF-8?q?fix:=20=E5=AD=97=E6=AE=B5=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=BC=96=E8=BE=91=E5=99=A8=E5=90=8C=E6=AD=A5=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=95=B0=E6=8D=AE=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../property-config/lookup.property-config.ts | 2 +- .../src/mapping-editor.component.tsx | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 6d9ff7dd2ba..1422f026cbc 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -429,7 +429,7 @@ export class LookupPropertyConfig extends InputBaseProperty { idField: 'bindingPath', textField: 'bindingPath', valueField: 'bindingPath', - dataSource: this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId), + dataSource: () => this.designViewModelUtils.getAllFields2TreeByVMId(this.viewModelId), formatter: (cell, data) => { return `${data.raw['name']} [${data.raw['bindingPath']}]`; } diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index fb7ec0f5065..4a2c94d0b17 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -21,7 +21,7 @@ export default defineComponent({ const selectedItems: any = ref([]); const fromDataSource = ref(props.fromData.dataSource || []); - const toDataSource = ref(props.toData.dataSource || []); + const toDataSource = ref([]); const repository = inject(props.fromData.repositoryToken); const toDataRepository = inject(props.toData.repositoryToken); @@ -212,17 +212,28 @@ export default defineComponent({ return false; } - const promises: Array> = []; const fromDataPromise = repository ? repository.getData(props.editorParams) : Promise.resolve(fromDataSource.value); promises.push(fromDataPromise); + + if (typeof props.toData.dataSource === 'function') { + toDataSource.value = props.toData.dataSource(); + } else { + toDataSource.value = props.toData.dataSource; + } + const toDataPromise = toDataRepository ? toDataRepository.getData(props.editorParams) : Promise.resolve(toDataSource.value); promises.push(toDataPromise); return Promise.all(promises).then(([fromData, toData]) => { fromDataSource.value = fromData; toDataSource.value = toData; + + + gridColumns[0].editor.data = fromData; + gridColumns[1].editor.data = toData; + return true; }); } @@ -246,7 +257,7 @@ export default defineComponent({ resetTreeDataSource(fromDataSource.value, disabledFields); editor.data = cloneDeep(fromDataSource.value); - } + } return true; } -- Gitee From 8e3f163f509302b68110c23ff62e453da7d0b078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 16 Apr 2025 14:21:21 +0800 Subject: [PATCH 134/156] =?UTF-8?q?fix:=20=E5=AD=97=E6=AE=B5=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=BC=96=E8=BE=91=E5=99=A8=E6=98=93=E7=94=A8=E6=80=A7?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/mapping-editor/src/mapping-editor.component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx index 4a2c94d0b17..345a9329232 100644 --- a/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx +++ b/packages/ui-vue/components/mapping-editor/src/mapping-editor.component.tsx @@ -123,6 +123,7 @@ export default defineComponent({ function onClearAll() { FMessageBoxService.question('确定要清空所有映射字段吗?', '', () => { + selectedItems.value = []; mappingFields.value = {}; mappingFieldList.value = []; datagridRef.value.updateDataSource(mappingFieldList.value); -- Gitee From 70a5693dfe6eeecd707e0be31c0e1c5003c2c495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 16 Apr 2025 15:34:39 +0800 Subject: [PATCH 135/156] =?UTF-8?q?fix:=20lookup=20=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/lookup.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index 1591029a2b9..ef42f751419 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -43,7 +43,7 @@ export default defineComponent({ const elementRef = ref(); const modelValue = ref(props.modelValue); const modalTitle = ref(''); - customData.value = ref(props.customData); + customData.value = props.customData; const useHttpComposition = useHttp(props, context); const { lookupOptions, selectionState } = useHttpComposition.lookupStates; -- Gitee From 113420b2a64a79a1caa685d2dcea88584703f553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 16 Apr 2025 20:14:14 +0800 Subject: [PATCH 136/156] =?UTF-8?q?fix:=20lookup=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/lookup/src/composition/use-context.ts | 8 +++++++- .../lookup/src/composition/use-freeinput.ts | 2 +- .../lookup/src/composition/use-input-change.ts | 11 ++++++----- .../ui-vue/components/lookup/src/lookup.component.tsx | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-context.ts b/packages/ui-vue/components/lookup/src/composition/use-context.ts index 30de872e0f4..306dc5d8112 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-context.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-context.ts @@ -1,8 +1,14 @@ -export function useContext(props: any, params: { items: any, mappingFields: any}) { +export function useContext(props: any, params?: { items?: any, mappingFields: any}) { if (props.context) { + if (!params) { + delete props.context.editor; + return; + } const { editor } = props.context; if (editor) { Object.assign(editor, params); + } else { + props.context.editor = params; } } } diff --git a/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts b/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts index 20611a75d02..3e6042a1ded 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-freeinput.ts @@ -6,7 +6,7 @@ export function useFreeInput(props: any, context: any, inputValue: string, looku } context.emit('update:modelValue', inputValue); context.emit('update:idValue', ''); - const clearParams = {items: null, mappingFields: lookupOptions.mappingFields}; + const clearParams = {mappingFields: lookupOptions.mappingFields}; useContext(props, clearParams); } diff --git a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts index 847787fce9e..97977dce073 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-input-change.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-input-change.ts @@ -79,12 +79,13 @@ export function useInputChange(props: LookupProps, context: any, options: Lookup searchText = searchText.trim(); } - if (props.allowFreeInput) { - useFreeInput(props, context, searchText, lookupOptions); - return; - } - if (isTextChange(searchText)) { + + if (props.allowFreeInput) { + useFreeInput(props, context, searchText, lookupOptions); + return; + } + if (props.uri) { queryDataBySearchKeys(searchText); } else { diff --git a/packages/ui-vue/components/lookup/src/lookup.component.tsx b/packages/ui-vue/components/lookup/src/lookup.component.tsx index ef42f751419..044401f3ec7 100644 --- a/packages/ui-vue/components/lookup/src/lookup.component.tsx +++ b/packages/ui-vue/components/lookup/src/lookup.component.tsx @@ -106,7 +106,7 @@ export default defineComponent({ }); onUnmounted(() => { - useContext(props, { items: [], mappingFields: {} }); + useContext(props); }); watch(() => dialogSize.value, (newSizeValue) => { -- Gitee From 7837bb8867c02af6252297cfbe58dba6bfc679b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 17 Apr 2025 09:21:59 +0800 Subject: [PATCH 137/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Ddatepicker?= =?UTF-8?q?=E6=98=93=E7=94=A8=E6=80=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 18 ++++++++++++++++-- .../src/composition/use-disable-month.ts | 2 +- .../date-picker/src/composition/use-month.ts | 4 ++-- .../date-picker/src/composition/use-year.ts | 8 ++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 510d4f01bd3..436d9c8d465 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -35,6 +35,8 @@ import { useDateFormat } from '@farris/ui-vue/components/common'; import { CalenderDayItem } from "../../types/calendar"; import { cloneDeep } from "lodash-es"; +import { useDisableMonth } from "../../composition/use-disable-month"; + export default defineComponent({ name: 'FDateView', props: datePickerContainerProps, @@ -131,10 +133,11 @@ export default defineComponent({ ); const { formatTo } = useDateFormat(); + const { isMonthDisabledByDisableSince, isMonthDisabledByDisableUntil } = useDisableMonth(); const { generateCalendar } = useCalendar(refDisableDate); const { getToday, getDateObject } = useDate(); - const { generateMonths, getNextMonth, getPreviousMonth } = useMonth(); + const { generateMonths, getNextMonth, getPreviousMonth, daysInMonth } = useMonth(); const { generateYears } = useYear(); const today = getToday(); @@ -694,6 +697,17 @@ export default defineComponent({ }; }); + const btnMonthStyle = computed(() => { + const { year, month } = today; + const disable: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, disableSince.value) || + isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month || 0, year || 0) }, disableUntil.value); + + return { + "pointer-events": disable ? "none" : "auto", + opacity: disable ? 0.3 : 1 + }; + }); + const btnCurrentYearStyle = computed(() => { const canSelected = today.year ? today.year >= minYear.value && today.year <= maxYear.value : false; @@ -717,7 +731,7 @@ export default defineComponent({ diff --git a/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts b/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts index e7d21ed071e..bcaa78293cb 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-disable-month.ts @@ -18,7 +18,7 @@ import { UseDisableMonth } from './types'; import { useCompare } from './use-compare'; import { useDate } from './use-date'; -export default function useDisableMonth(): UseDisableMonth { +export function useDisableMonth(): UseDisableMonth { const { getTimeInMilliseconds } = useDate(); const { isInitializedDate } = useCompare(); diff --git a/packages/ui-vue/components/date-picker/src/composition/use-month.ts b/packages/ui-vue/components/date-picker/src/composition/use-month.ts index 8dd16b73eea..c4d1b7e51d3 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-month.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-month.ts @@ -17,7 +17,7 @@ import { DateObject } from '../types/common'; import { ActiveMonth, MonthViewItem } from '../types/month'; import { UseMonth } from './types'; import { useDate } from './use-date'; -import useDisableMonth from './use-disable-month'; +import { useDisableMonth } from './use-disable-month'; export function useMonth(): UseMonth { @@ -100,5 +100,5 @@ export function useMonth(): UseMonth { return previousMonthDate; } - return { daysInMonth, daysInPreMonth, generateMonths, parseDefaultMonth,getNextMonth,getPreviousMonth }; + return { daysInMonth, daysInPreMonth, generateMonths, parseDefaultMonth, getNextMonth, getPreviousMonth }; } diff --git a/packages/ui-vue/components/date-picker/src/composition/use-year.ts b/packages/ui-vue/components/date-picker/src/composition/use-year.ts index 6dd295287b3..c8e93d98671 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-year.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-year.ts @@ -16,15 +16,15 @@ import { YearViewItem } from '../types/year'; import { DateObject } from '../types/common'; import { useDate } from './use-date'; -import { useMonth } from './use-month'; -import useDisableMonth from './use-disable-month'; +// import { useMonth } from './use-month'; +// import { useDisableMonth } from './use-disable-month'; import { UseYear } from './types'; export function useYear(): UseYear { const { getToday } = useDate(); - const { daysInMonth } = useMonth(); - const { isMonthDisabledByDisableSince, isMonthDisabledByDisableUntil } = useDisableMonth(); + // const { daysInMonth } = useMonth(); + // const { isMonthDisabledByDisableSince, isMonthDisabledByDisableUntil } = useDisableMonth(); function generateYears( input: number, -- Gitee From 295a535a624cadf3ea6856c5ed789bbefe4d4784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 17 Apr 2025 14:04:42 +0800 Subject: [PATCH 138/156] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96datepcker?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E4=B8=AD=E6=9C=88=E4=BB=BD=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=8F=AF=E7=94=A8=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 6 ++++-- .../components/date-picker/src/composition/use-month.ts | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 436d9c8d465..40f6b506b37 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -699,8 +699,10 @@ export default defineComponent({ const btnMonthStyle = computed(() => { const { year, month } = today; - const disable: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, disableSince.value) || - isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month || 0, year || 0) }, disableUntil.value); + const maxDate = { year: disableSince.value.year, month: disableSince.value.month, day: disableSince.value.day }; + const minDate = { year: disableUntil.value.year, month: disableUntil.value.month, day: disableUntil.value.day }; + const disable: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, maxDate) || + isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month || 0, year || 0) }, minDate); return { "pointer-events": disable ? "none" : "auto", diff --git a/packages/ui-vue/components/date-picker/src/composition/use-month.ts b/packages/ui-vue/components/date-picker/src/composition/use-month.ts index c4d1b7e51d3..b8aae24cde9 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-month.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-month.ts @@ -63,11 +63,15 @@ export function useMonth(): UseMonth { const { year } = selectedMonth; const capacityPerRow = 3; + const maxDate = { year: disableSince.year, month: disableSince.month, day: disableSince.day }; + const minDate = { year: disableUntil.year, month: disableUntil.month, day: disableUntil.day }; + + for (let startMonthInRow = 1; startMonthInRow <= 12; startMonthInRow += capacityPerRow) { const monthsInRow: MonthViewItem[] = []; for (let month = startMonthInRow; month < startMonthInRow + capacityPerRow; month++) { - const disable: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, disableSince) || - isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month, year || 0) }, disableUntil); + const disable: boolean = isMonthDisabledByDisableSince({ year, month, day: 1 }, maxDate) || + isMonthDisabledByDisableUntil({ year, month, day: daysInMonth(month, year || 0) }, minDate); monthsInRow.push({ month, -- Gitee From cf1e9d5d43794222e0b43b91a7fe65347c60bd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 17 Apr 2025 16:13:06 +0800 Subject: [PATCH 139/156] =?UTF-8?q?fix:=20datepicker=20=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=83=A8=E5=88=86=E8=BD=AC=E6=8D=A2=E9=80=BB=E8=BE=91=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/date/use-date-format.ts | 4 ++-- .../date-picker-container.component.tsx | 19 +++++++------------ .../date-picker/src/date-picker.component.tsx | 4 +++- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/ui-vue/components/common/date/use-date-format.ts b/packages/ui-vue/components/common/date/use-date-format.ts index 05a937d8616..1a4e0c14cee 100644 --- a/packages/ui-vue/components/common/date/use-date-format.ts +++ b/packages/ui-vue/components/common/date/use-date-format.ts @@ -1,5 +1,5 @@ /* eslint-disable eqeqeq */ -import { format, isValid, parseISO } from "date-fns"; +import { format, isValid, parse, parseISO } from "date-fns"; import { UseDateFormat } from "../types"; import { DateConverter } from "./date-converter"; @@ -21,7 +21,7 @@ export function useDateFormat(): UseDateFormat { return format(dateValue, dateFormat); } - let dateObject: any = parseISO(dateValue); + let dateObject: any = parse(dateValue, dateFormat, new Date()); if (dateObject == "Invalid Date") { dateObject = dateConverter.create(dateValue) || new Date(dateValue); diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 40f6b506b37..2981f6ca373 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -34,6 +34,7 @@ import { convertToDate, convertToString } from "../../../../time-picker/src/comp import { useDateFormat } from '@farris/ui-vue/components/common'; import { CalenderDayItem } from "../../types/calendar"; import { cloneDeep } from "lodash-es"; +import { parse } from "date-fns"; import { useDisableMonth } from "../../composition/use-disable-month"; @@ -640,10 +641,9 @@ export default defineComponent({ } function formatDate() { - const dateAndTimeFormatList = valueFormat.value.split(' '); - const timeFormat = dateAndTimeFormatList[1] || 'HH:mm:ss'; - if (timeValue.value) { - const convertedDate = convertToDate(timeValue.value, timeFormat); + const timeFormat = 'HH:mm:ss'; + if (dateValue.value) { + const convertedDate = convertToDate(dateValue.value, valueFormat.value); timeValue.value = convertToString(convertedDate, timeFormat); if (selectedDate.value) { selectedDate.value.hour = convertedDate?.getHours() || 0; @@ -652,17 +652,14 @@ export default defineComponent({ } } else { const { hour, minute, second } = selectedDate.value; - timeValue.value = `${hour || 0}:${minute || 0}:${second || 0}`; - const convertedDate = convertToDate(timeValue.value, timeFormat); + timeValue.value = `${hour || '0'}:${minute || 0}:${second || 0}`; + const convertedDate = convertToDate('2025-04-17 ' + timeValue.value, 'yyyy-MM-dd HH:mm:ss'); timeValue.value = convertToString(convertedDate, timeFormat); } } onMounted(() => { if (props.showTime) { - const dateAndTimeFormatList = valueFormat.value.split(' '); - const timeFormat = dateAndTimeFormatList[1] || 'HH:mm:ss'; - timeValue.value = formatTo(dateValue.value, timeFormat); formatDate(); } @@ -677,9 +674,7 @@ export default defineComponent({ const onValueChangeHandler = (textValue: TimeValueText) => { timeValue.value = textValue.text; - const dateAndTimeFormatList = valueFormat.value.split(' '); - const timeFormat = dateAndTimeFormatList[1] || 'HH:mm:ss'; - const convertedDate = convertToDate(timeValue.value, timeFormat); + const convertedDate = convertToDate('2025-04-17 ' + timeValue.value, 'yyyy-MM-dd HH:mm:ss'); if (selectedDate.value) { selectedDate.value.hour = convertedDate?.getHours() || 0; selectedDate.value.minute = convertedDate?.getMinutes() || 0; diff --git a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx index ec997e59f4d..c6f70323f45 100644 --- a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx +++ b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx @@ -22,6 +22,7 @@ import { useDateFormat } from '@farris/ui-vue/components/common'; import { DateObject } from './types/common'; import './date-picker.css'; import { useDate } from './composition/use-date'; +import { convertToDate } from '@/components/time-picker/src/composition/utils'; export default defineComponent({ name: 'FDatePicker', @@ -82,7 +83,8 @@ export default defineComponent({ function onClickButton() { } const displayDate = computed(() => { - return formatTo(realValue.value, props.displayFormat); + const dateObj: any = convertToDate(realValue.value, props.valueFormat); + return formatTo(dateObj, props.displayFormat); }); function setModelValue(dateValue: string, emit = true) { -- Gitee From 7f2fe9161e0dc7dc706e8baee4462cac004e1f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Thu, 17 Apr 2025 17:05:40 +0800 Subject: [PATCH 140/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E6=B7=BB=E5=8A=A0=E4=BA=8B=E4=BB=B6=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lookup/src/property-config/lookup.property-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index 1422f026cbc..563c5028553 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -830,7 +830,7 @@ export class LookupPropertyConfig extends InputBaseProperty { const parameters = changeObject.propertyValue; delete newPropertyData[self.viewModelId]; if (parameters) { - parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后,调用此回调方法,用于处理联动属性 + // parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后,调用此回调方法,用于处理联动属性 self.eventsEditorUtils.saveRelatedParameters(newPropertyData, self.viewModelId, parameters['events'], parameters); } -- Gitee From 13192338cb5f173dd6add1d7621d7d293d0afe11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 18 Apr 2025 10:19:54 +0800 Subject: [PATCH 141/156] =?UTF-8?q?fix:=20datepicker=20=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E8=BD=AC=E6=8D=A2=E9=80=BB=E8=BE=91=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 2 +- .../components/date-picker/src/composition/use-date.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 2981f6ca373..2b17d53d82e 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -144,7 +144,7 @@ export default defineComponent({ const today = getToday(); const selectedDateObj = computed(() => { if (dateValue.value) { - return getDateObject(dateValue.value.split(' ')[0], valueFormat.value.split(' ')[0]); + return getDateObject(dateValue.value, valueFormat.value); } return cloneDeep(today); }); diff --git a/packages/ui-vue/components/date-picker/src/composition/use-date.ts b/packages/ui-vue/components/date-picker/src/composition/use-date.ts index b2ce62494ed..c31520c444d 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-date.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-date.ts @@ -110,7 +110,7 @@ export function useDate(): UseDate { } function getDateObject(dateString: string, dateFormat: string): DateObject { - const delimeters = dateFormat.match(/[^(DdMmYy)]{1,}/g); + const delimeters = dateFormat.match(/[^(dMyHms)]{1,}/g); const dateObject: DateObject = {}; if (delimeters) { @@ -150,6 +150,11 @@ export function useDate(): UseDate { dateObject.day = Number(dateString.substring(dayIndex, dayIndex + 2) || '01'); } } + + if (dateObject.year === undefined) { + dateObject.year = getToday().year; + } + return dateObject; } -- Gitee From 139514ca2c25b94e0157412abe52b2577ecde9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Fri, 18 Apr 2025 14:55:50 +0800 Subject: [PATCH 142/156] =?UTF-8?q?fix:=20treeview=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=87=AA=E5=8A=A8=E9=AB=98=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/data-view/composition/types.ts | 3 ++ .../visualization/use-virtual-scroll.ts | 3 +- .../entity-tree/entity-treeview.component.tsx | 38 ++++++++++++++++--- .../tree-view/src/tree-view.props.ts | 4 +- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/ui-vue/components/data-view/composition/types.ts b/packages/ui-vue/components/data-view/composition/types.ts index e68f91f92f2..ef08b74f2d0 100644 --- a/packages/ui-vue/components/data-view/composition/types.ts +++ b/packages/ui-vue/components/data-view/composition/types.ts @@ -516,6 +516,9 @@ export interface DataViewOptions { /** 虚拟化渲染数据 */ virtualized: boolean; keepSelectingOnClick: boolean; + + /** 自动高度 */ + autoHeight: boolean; } export interface UseDataView { diff --git a/packages/ui-vue/components/data-view/composition/visualization/use-virtual-scroll.ts b/packages/ui-vue/components/data-view/composition/visualization/use-virtual-scroll.ts index abb0c3450ac..b72bcf2649f 100644 --- a/packages/ui-vue/components/data-view/composition/visualization/use-virtual-scroll.ts +++ b/packages/ui-vue/components/data-view/composition/visualization/use-virtual-scroll.ts @@ -306,8 +306,9 @@ export function useVirtualScroll( }); const gridDataStyle = computed(() => { + const dataItems = props.autoHeight ? visibleDataItems.value : dataView.value; const styleObject = { - height: `${dataView.value.length * rowHeight}px`, + height: `${dataItems.length * rowHeight}px`, width: `${gridViewWidth.value}px`, transform: `translate(${offsetX.value}px, ${offsetY.value}px)` } as Record; diff --git a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx index 585402dc314..37e7d0d308c 100644 --- a/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/components/entity-tree/entity-treeview.component.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, inject, onMounted, ref, watch } from "vue"; +import { computed, defineComponent, inject, nextTick, onMounted, ref, watch } from "vue"; import FTreeView from '@farris/ui-vue/components/tree-view'; import { entityTreeviewProps, EntityTreeviewProps } from "./entity-treeview.props"; @@ -10,6 +10,22 @@ export default defineComponent({ setup(props: EntityTreeviewProps, context) { const dataSource = ref(props.data); const treeViewRef = ref(); + const minWidthStyle = ref(); + + function getMaxColumnWidth() { + let maxWidth = 0; + // 选择所有目标单元格 + const cells = document.querySelectorAll('.entity-variable .fv-grid-hierarchy-cell'); + cells.forEach((cell: any) => { + // 使用scrollWidth获取内容实际宽度 + cell.style.width = 'auto'; + const currentWidth = cell.scrollWidth; + if (currentWidth > maxWidth) { + maxWidth = currentWidth; + } + }); + return maxWidth; + } watch(() => props.data, (newValue) => { dataSource.value = newValue; @@ -33,17 +49,24 @@ export default defineComponent({ context.emit('dblclickNode', {$event, node}); } + function updateTreeViewMinWidth() { + const maxWidth = getMaxColumnWidth(); + minWidthStyle.value = { minWidth: `${maxWidth + 10}px` }; + } + + function onExpandNode({row}) { + nextTick(updateTreeViewMinWidth); + } onMounted(() => { - + nextTick(updateTreeViewMinWidth); }); return () => { return ( -
        - +
        ); diff --git a/packages/ui-vue/components/tree-view/src/tree-view.props.ts b/packages/ui-vue/components/tree-view/src/tree-view.props.ts index 84cf4c9b6b6..7b3f3a6d204 100644 --- a/packages/ui-vue/components/tree-view/src/tree-view.props.ts +++ b/packages/ui-vue/components/tree-view/src/tree-view.props.ts @@ -121,7 +121,9 @@ export const treeViewProps = { /** 虚拟化渲染数据 */ virtualized: { type: Boolean, default: false }, /** 是否出现省略号 */ - showEllipsis: { type: Boolean, default: false} + showEllipsis: { type: Boolean, default: false}, + /** 自动高度 **/ + autoHeight: { type: Boolean, default: false } } as Record; export type TreeViewProps = ExtractPropTypes; -- Gitee From 42ddf88adb66887197936eb12c2ab8c73e636062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 19 Apr 2025 11:35:48 +0800 Subject: [PATCH 143/156] =?UTF-8?q?fix:=20datepicker=20=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E6=A0=BC=E5=BC=8F=E8=BD=AC=E6=8D=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 13 +++++----- .../time-picker/src/composition/utils.ts | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index 2b17d53d82e..d6308207b85 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -30,7 +30,7 @@ import { useMonth } from "../../composition/use-month"; import { useYear } from "../../composition/use-year"; import { FButton } from "../../../../button"; import { TimeValueText } from "../../../../time-picker/src/composition/types"; -import { convertToDate, convertToString } from "../../../../time-picker/src/composition/utils"; +import { convertToDate, convertToString, formatTime, getTimeObject } from "../../../../time-picker/src/composition/utils"; import { useDateFormat } from '@farris/ui-vue/components/common'; import { CalenderDayItem } from "../../types/calendar"; import { cloneDeep } from "lodash-es"; @@ -653,8 +653,7 @@ export default defineComponent({ } else { const { hour, minute, second } = selectedDate.value; timeValue.value = `${hour || '0'}:${minute || 0}:${second || 0}`; - const convertedDate = convertToDate('2025-04-17 ' + timeValue.value, 'yyyy-MM-dd HH:mm:ss'); - timeValue.value = convertToString(convertedDate, timeFormat); + timeValue.value = formatTime(timeValue.value); } } @@ -674,11 +673,11 @@ export default defineComponent({ const onValueChangeHandler = (textValue: TimeValueText) => { timeValue.value = textValue.text; - const convertedDate = convertToDate('2025-04-17 ' + timeValue.value, 'yyyy-MM-dd HH:mm:ss'); + const { hour, minute, second } = getTimeObject(timeValue.value); if (selectedDate.value) { - selectedDate.value.hour = convertedDate?.getHours() || 0; - selectedDate.value.minute = convertedDate?.getMinutes() || 0; - selectedDate.value.second = convertedDate?.getSeconds() || 0; + selectedDate.value.hour = hour || 0; + selectedDate.value.minute = minute || 0; + selectedDate.value.second = second || 0; } }; diff --git a/packages/ui-vue/components/time-picker/src/composition/utils.ts b/packages/ui-vue/components/time-picker/src/composition/utils.ts index 0a2edb28683..ec974a29570 100644 --- a/packages/ui-vue/components/time-picker/src/composition/utils.ts +++ b/packages/ui-vue/components/time-picker/src/composition/utils.ts @@ -9,6 +9,30 @@ export function toBoolean(value: boolean | string): boolean { return !!value; } +export function formatTime(timeValue: string) { + if (!timeValue?.trim()) {return '';} + const timeFormat = 'HH:mm:ss'; + const dateValue = fnsFormat(new Date(), 'yyyy-MM-dd'); + return fnsFormat(new Date(`${dateValue} ${timeValue.trim()}`), timeFormat); +} + +export function getTimeObject(timeValue: string): { hour: number; minute: number; second: number } { + if (!timeValue?.trim()) { + return { + hour: 0, + minute: 0, + second: 0, + }; + } + const dateValue = fnsFormat(new Date(), 'yyyy-MM-dd'); + const date = fnsParse(`${dateValue} ${timeValue.trim()}`, 'yyyy-MM-dd HH:mm:ss', new Date()); + return { + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + }; +} + export function convertToDate(value: string, format: string = 'hh:mm:ss'): Date|undefined { if (!value || !format) { return; -- Gitee From eb8457bd5d5aa071dbd60dc3d394fee9c6724a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 19 Apr 2025 11:43:32 +0800 Subject: [PATCH 144/156] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4datepicker?= =?UTF-8?q?=E5=86=85=E5=A4=9A=E4=BD=99=E7=9A=84=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container/date-picker-container.component.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index d6308207b85..c22ab98af8c 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -34,7 +34,6 @@ import { convertToDate, convertToString, formatTime, getTimeObject } from "../.. import { useDateFormat } from '@farris/ui-vue/components/common'; import { CalenderDayItem } from "../../types/calendar"; import { cloneDeep } from "lodash-es"; -import { parse } from "date-fns"; import { useDisableMonth } from "../../composition/use-disable-month"; -- Gitee From da5ccd68761f0822f4be99e30591d006ef5ca557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Sat, 19 Apr 2025 17:57:25 +0800 Subject: [PATCH 145/156] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E6=A0=BC=E5=BC=8F=E5=8C=96=E7=9B=B8=E5=85=B3=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/common/date/use-date-format.ts | 7 +++++-- .../date-picker-container.component.tsx | 2 +- .../components/date-picker/src/date-picker.component.tsx | 6 ++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/common/date/use-date-format.ts b/packages/ui-vue/components/common/date/use-date-format.ts index 1a4e0c14cee..a15375d1caf 100644 --- a/packages/ui-vue/components/common/date/use-date-format.ts +++ b/packages/ui-vue/components/common/date/use-date-format.ts @@ -23,10 +23,13 @@ export function useDateFormat(): UseDateFormat { let dateObject: any = parse(dateValue, dateFormat, new Date()); - if (dateObject == "Invalid Date") { - dateObject = dateConverter.create(dateValue) || new Date(dateValue); + if (isNaN(dateObject.getTime())) { + dateObject = [parseISO, (value: any) => dateConverter.create(value), (value: string) => new Date(value)].reduce((result, parser) => { + return isNaN(result.getTime()) ? parser(dateValue) : result; + }, dateObject); } + // const d = parseISO(value); if (isValid(dateObject)) { dateObject = parseISO(format(dateObject, "yyyy-MM-dd HH:mm:ss")); diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index c22ab98af8c..cf79e86cabe 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -682,7 +682,7 @@ export default defineComponent({ const btnTodayStyle = computed(() => { return (date: any) => { - const todayIsDisable = refDisableDate.isDisabledDate(props.showTime ? date : { year: date.year, month: date.month, day: date.day }); + const todayIsDisable = date.day == null || refDisableDate.isDisabledDate(props.showTime ? date : { year: date.year, month: date.month, day: date.day }); return { "pointer-events": todayIsDisable ? "none" : "auto", opacity: todayIsDisable ? 0.3 : 1 diff --git a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx index c6f70323f45..fc53c00dd19 100644 --- a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx +++ b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx @@ -103,6 +103,12 @@ export default defineComponent({ } function onDatePicked(dateValue: DateObject) { + for(const key in {...dateValue}) { + if (dateValue[key] != null) { + dateValue[key] = dateValue[key].toString().padStart(2, '0'); + } + } + let dateValueString = `${dateValue.year}-${dateValue.month}-${dateValue.day}`; if (props.showTime) { dateValueString += ` ${dateValue.hour}:${dateValue.minute}:${dateValue.second}`; -- Gitee From 92cc7335b82bba715db46d55f1a0d9db511536be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 21 Apr 2025 09:48:52 +0800 Subject: [PATCH 146/156] =?UTF-8?q?fix:=20=E6=97=A5=E6=9C=9F=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/date/use-date-format.ts | 47 +++++++++++++++++-- packages/ui-vue/components/common/types.ts | 1 + .../date-picker-container.component.tsx | 18 ++----- .../date-picker/src/date-picker.component.tsx | 6 +-- .../time-picker/src/composition/utils.ts | 24 ---------- 5 files changed, 50 insertions(+), 46 deletions(-) diff --git a/packages/ui-vue/components/common/date/use-date-format.ts b/packages/ui-vue/components/common/date/use-date-format.ts index a15375d1caf..fcde4d33077 100644 --- a/packages/ui-vue/components/common/date/use-date-format.ts +++ b/packages/ui-vue/components/common/date/use-date-format.ts @@ -8,17 +8,20 @@ export function useDateFormat(): UseDateFormat { const dateConverter = new DateConverter(); - function formatTo(dateValue: string | Date, dateFormat: string): string { + function parseToDate(dateValue: string | Date, dateFormat: string): Date | null { if (!dateValue) { - return ""; + return null; } if (typeof dateValue === "string" && dateValue.indexOf("0001") === 0) { - return ""; + return null; } if (dateValue instanceof Date) { - return format(dateValue, dateFormat); + if(isNaN(dateValue.getTime())) { + return null; + } + return dateValue; } let dateObject: any = parse(dateValue, dateFormat, new Date()); @@ -29,7 +32,16 @@ export function useDateFormat(): UseDateFormat { }, dateObject); } + return dateObject; + } + function formatTo(dateValue: string | Date, dateFormat: string): string { + + let dateObject = parseToDate(dateValue, dateFormat); + if (dateObject === null) { + return ""; + } + // const d = parseISO(value); if (isValid(dateObject)) { dateObject = parseISO(format(dateObject, "yyyy-MM-dd HH:mm:ss")); @@ -38,7 +50,7 @@ export function useDateFormat(): UseDateFormat { if (dateFormat.indexOf("HH") === 0 || dateFormat.indexOf("hh") === 0) { // 仅有时间部分 // 提取时间 - const _time = dateValue.match(/\d*/g)?.filter((n) => n !== "").join(":"); + const _time = dateValue?.match(/\d*/g)?.filter((n) => n !== "").join(":"); if (dateFormat === "HH" || dateFormat === "hh") { dateFormat += ":mm"; @@ -52,6 +64,31 @@ export function useDateFormat(): UseDateFormat { } return { + parseToDate, formatTo }; } + +export function formatTime(timeValue: string) { + if (!timeValue?.trim()) {return '';} + const timeFormat = 'HH:mm:ss'; + const dateValue = format(new Date(), 'yyyy-MM-dd'); + return format(new Date(`${dateValue} ${timeValue.trim()}`), timeFormat); +} + +export function getTimeObject(timeValue: string): { hour: number; minute: number; second: number } { + if (!timeValue?.trim()) { + return { + hour: 0, + minute: 0, + second: 0, + }; + } + const dateValue = format(new Date(), 'yyyy-MM-dd'); + const date = parse(`${dateValue} ${timeValue.trim()}`, 'yyyy-MM-dd HH:mm:ss', new Date()); + return { + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + }; +} \ No newline at end of file diff --git a/packages/ui-vue/components/common/types.ts b/packages/ui-vue/components/common/types.ts index 147885f34ad..0b874782f34 100644 --- a/packages/ui-vue/components/common/types.ts +++ b/packages/ui-vue/components/common/types.ts @@ -97,6 +97,7 @@ export interface UseTextBox { } export interface UseDateFormat { + parseToDate: (date: string | Date, format: string) => Date | null; formatTo: (date: string | Date, format: string) => string; } export type NumberType = string | number; diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index cf79e86cabe..a6442abd9b6 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -30,8 +30,7 @@ import { useMonth } from "../../composition/use-month"; import { useYear } from "../../composition/use-year"; import { FButton } from "../../../../button"; import { TimeValueText } from "../../../../time-picker/src/composition/types"; -import { convertToDate, convertToString, formatTime, getTimeObject } from "../../../../time-picker/src/composition/utils"; -import { useDateFormat } from '@farris/ui-vue/components/common'; +import { useDateFormat, formatTime, getTimeObject } from '@farris/ui-vue/components/common'; import { CalenderDayItem } from "../../types/calendar"; import { cloneDeep } from "lodash-es"; @@ -132,7 +131,7 @@ export default defineComponent({ disableWeekdays.value ); - const { formatTo } = useDateFormat(); + const { formatTo, parseToDate } = useDateFormat(); const { isMonthDisabledByDisableSince, isMonthDisabledByDisableUntil } = useDisableMonth(); const { generateCalendar } = useCalendar(refDisableDate); @@ -442,15 +441,6 @@ export default defineComponent({ selectedDate.value.year = year; selectedDate.value.month = month; selectedDate.value.day = day; - // // 赋值时间 - // const dateAndTimeFormatList = valueFormat.value.split(' '); - // const timeFormat = dateAndTimeFormatList[1] || 'HH:mm:ss'; - // const convertedDate = convertToDate(timeValue.value, timeFormat); - // if (selectedDate.value) { - // selectedDate.value.hour = convertedDate?.getHours() || 0; - // selectedDate.value.minute = convertedDate?.getMinutes() || 0; - // selectedDate.value.second = convertedDate?.getSeconds() || 0; - // } } } @@ -642,8 +632,8 @@ export default defineComponent({ function formatDate() { const timeFormat = 'HH:mm:ss'; if (dateValue.value) { - const convertedDate = convertToDate(dateValue.value, valueFormat.value); - timeValue.value = convertToString(convertedDate, timeFormat); + const convertedDate = parseToDate(dateValue.value, valueFormat.value); + timeValue.value = formatTo(convertedDate || '', timeFormat) || '00:00:00'; if (selectedDate.value) { selectedDate.value.hour = convertedDate?.getHours() || 0; selectedDate.value.minute = convertedDate?.getMinutes() || 0; diff --git a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx index fc53c00dd19..005fea23256 100644 --- a/packages/ui-vue/components/date-picker/src/date-picker.component.tsx +++ b/packages/ui-vue/components/date-picker/src/date-picker.component.tsx @@ -22,7 +22,7 @@ import { useDateFormat } from '@farris/ui-vue/components/common'; import { DateObject } from './types/common'; import './date-picker.css'; import { useDate } from './composition/use-date'; -import { convertToDate } from '@/components/time-picker/src/composition/utils'; + export default defineComponent({ name: 'FDatePicker', @@ -78,12 +78,12 @@ export default defineComponent({ const enableClear = ref(props.enableClear); const editable = ref(props.editable); - const { formatTo } = useDateFormat(); + const { formatTo, parseToDate } = useDateFormat(); function onClickButton() { } const displayDate = computed(() => { - const dateObj: any = convertToDate(realValue.value, props.valueFormat); + const dateObj: any = parseToDate(realValue.value, props.valueFormat); return formatTo(dateObj, props.displayFormat); }); diff --git a/packages/ui-vue/components/time-picker/src/composition/utils.ts b/packages/ui-vue/components/time-picker/src/composition/utils.ts index ec974a29570..0a2edb28683 100644 --- a/packages/ui-vue/components/time-picker/src/composition/utils.ts +++ b/packages/ui-vue/components/time-picker/src/composition/utils.ts @@ -9,30 +9,6 @@ export function toBoolean(value: boolean | string): boolean { return !!value; } -export function formatTime(timeValue: string) { - if (!timeValue?.trim()) {return '';} - const timeFormat = 'HH:mm:ss'; - const dateValue = fnsFormat(new Date(), 'yyyy-MM-dd'); - return fnsFormat(new Date(`${dateValue} ${timeValue.trim()}`), timeFormat); -} - -export function getTimeObject(timeValue: string): { hour: number; minute: number; second: number } { - if (!timeValue?.trim()) { - return { - hour: 0, - minute: 0, - second: 0, - }; - } - const dateValue = fnsFormat(new Date(), 'yyyy-MM-dd'); - const date = fnsParse(`${dateValue} ${timeValue.trim()}`, 'yyyy-MM-dd HH:mm:ss', new Date()); - return { - hour: date.getHours(), - minute: date.getMinutes(), - second: date.getSeconds(), - }; -} - export function convertToDate(value: string, format: string = 'hh:mm:ss'): Date|undefined { if (!value || !format) { return; -- Gitee From d85537cf0ad6ca6405519f4f6b73a2bbceab68b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Mon, 21 Apr 2025 14:02:50 +0800 Subject: [PATCH 147/156] =?UTF-8?q?fix:=20=E6=97=A5=E6=9C=9F=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E5=87=BD=E6=95=B0=E7=B1=BB=E5=9E=8B=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/date/use-date-format.ts | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/ui-vue/components/common/date/use-date-format.ts b/packages/ui-vue/components/common/date/use-date-format.ts index fcde4d33077..b8475a93520 100644 --- a/packages/ui-vue/components/common/date/use-date-format.ts +++ b/packages/ui-vue/components/common/date/use-date-format.ts @@ -4,6 +4,30 @@ import { format, isValid, parse, parseISO } from "date-fns"; import { UseDateFormat } from "../types"; import { DateConverter } from "./date-converter"; + +export function formatTime(timeValue: string, timeFormat: string = 'HH:mm:ss') { + if (!timeValue?.trim()) {return '';} + const dateValue = format(new Date(), 'yyyy-MM-dd'); + return format(new Date(`${dateValue} ${timeValue.trim()}`), timeFormat); +} + +export function getTimeObject(timeValue: string): { hour: number; minute: number; second: number } { + if (!timeValue?.trim()) { + return { + hour: 0, + minute: 0, + second: 0, + }; + } + const dateValue = format(new Date(), 'yyyy-MM-dd'); + const date = parse(`${dateValue} ${timeValue.trim()}`, 'yyyy-MM-dd HH:mm:ss', new Date()); + return { + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds(), + }; +} + export function useDateFormat(): UseDateFormat { const dateConverter = new DateConverter(); @@ -47,17 +71,21 @@ export function useDateFormat(): UseDateFormat { dateObject = parseISO(format(dateObject, "yyyy-MM-dd HH:mm:ss")); return format(dateObject, dateFormat); } - if (dateFormat.indexOf("HH") === 0 || dateFormat.indexOf("hh") === 0) { + + if (typeof dateValue === 'string' && (dateFormat.indexOf("HH") === 0 || dateFormat.indexOf("hh") === 0)) { // 仅有时间部分 // 提取时间 - const _time = dateValue?.match(/\d*/g)?.filter((n) => n !== "").join(":"); + const timeValue = dateValue?.match(/\d*/g)?.filter((n) => n !== "").join(":"); if (dateFormat === "HH" || dateFormat === "hh") { dateFormat += ":mm"; } + if (timeValue) { + return formatTime(timeValue, dateFormat); + } - const fullDateTime = parseISO("2024-06-05 " + _time); - return format(fullDateTime, dateFormat); + return ""; + } return ""; @@ -68,27 +96,3 @@ export function useDateFormat(): UseDateFormat { formatTo }; } - -export function formatTime(timeValue: string) { - if (!timeValue?.trim()) {return '';} - const timeFormat = 'HH:mm:ss'; - const dateValue = format(new Date(), 'yyyy-MM-dd'); - return format(new Date(`${dateValue} ${timeValue.trim()}`), timeFormat); -} - -export function getTimeObject(timeValue: string): { hour: number; minute: number; second: number } { - if (!timeValue?.trim()) { - return { - hour: 0, - minute: 0, - second: 0, - }; - } - const dateValue = format(new Date(), 'yyyy-MM-dd'); - const date = parse(`${dateValue} ${timeValue.trim()}`, 'yyyy-MM-dd HH:mm:ss', new Date()); - return { - hour: date.getHours(), - minute: date.getMinutes(), - second: date.getSeconds(), - }; -} \ No newline at end of file -- Gitee From d1d00765cb247499fe2a3f8254fa14470fff4bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 22 Apr 2025 10:49:46 +0800 Subject: [PATCH 148/156] =?UTF-8?q?fix:=20=E5=88=97=E8=A1=A8lookup?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E8=BF=9B=E5=85=A5=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E6=80=81=E3=80=81=E7=BB=93=E6=9D=9F=E7=BC=96=E8=BE=91=E5=90=8E?= =?UTF-8?q?=E9=87=8D=E7=BD=AE=E4=B8=8A=E4=B8=8B=E6=96=87=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui-vue/components/data-view/composition/use-edit.tsx | 3 +++ .../components/lookup/src/composition/use-context.ts | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/ui-vue/components/data-view/composition/use-edit.tsx b/packages/ui-vue/components/data-view/composition/use-edit.tsx index de7a8170b75..6b9d8dbc68c 100644 --- a/packages/ui-vue/components/data-view/composition/use-edit.tsx +++ b/packages/ui-vue/components/data-view/composition/use-edit.tsx @@ -69,6 +69,9 @@ export function useEdit( editingRow = row; oldCellValue = resolveField(row?.raw, cell.field); editingColumn = column; + for(const key in controlData) { + delete controlData[key]; + } } function endEditCell(currentEditingCell: VisualDataCell) { diff --git a/packages/ui-vue/components/lookup/src/composition/use-context.ts b/packages/ui-vue/components/lookup/src/composition/use-context.ts index 306dc5d8112..a22fd73cb33 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-context.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-context.ts @@ -1,9 +1,12 @@ export function useContext(props: any, params?: { items?: any, mappingFields: any}) { if (props.context) { - if (!params) { - delete props.context.editor; + if (!params && props.context.editor) { + for(const key in props.context.editor) { + delete props.context.editor[key]; + } return; } + const { editor } = props.context; if (editor) { Object.assign(editor, params); -- Gitee From 2ffb3a4934607b7fa27ca11caa446b2b739bc81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 22 Apr 2025 11:43:21 +0800 Subject: [PATCH 149/156] =?UTF-8?q?fix:=20=E6=97=A5=E6=9C=9F=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E5=87=BD=E6=95=B0=E5=85=BC=E5=AE=B9=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/common/date/use-date-format.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui-vue/components/common/date/use-date-format.ts b/packages/ui-vue/components/common/date/use-date-format.ts index b8475a93520..7acdb871cfd 100644 --- a/packages/ui-vue/components/common/date/use-date-format.ts +++ b/packages/ui-vue/components/common/date/use-date-format.ts @@ -52,7 +52,7 @@ export function useDateFormat(): UseDateFormat { if (isNaN(dateObject.getTime())) { dateObject = [parseISO, (value: any) => dateConverter.create(value), (value: string) => new Date(value)].reduce((result, parser) => { - return isNaN(result.getTime()) ? parser(dateValue) : result; + return (isNaN(result) || isNaN(result?.getTime())) ? parser(dateValue) : result; }, dateObject); } -- Gitee From a08017af30b92a700120f20fcd3749d6e3717c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 22 Apr 2025 16:17:56 +0800 Subject: [PATCH 150/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E6=A0=BC=E5=BC=8F=E5=8C=96=E7=9B=B8=E5=85=B3=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../date-picker-container.component.tsx | 7 +++---- .../components/date-picker/src/composition/use-date.ts | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index a6442abd9b6..a45df747a87 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -141,10 +141,9 @@ export default defineComponent({ const today = getToday(); const selectedDateObj = computed(() => { - if (dateValue.value) { - return getDateObject(dateValue.value, valueFormat.value); - } - return cloneDeep(today); + const todayClone = cloneDeep(today); + const parsedDate = dateValue.value && parseToDate(dateValue.value, valueFormat.value); + return parsedDate ? getDateObject(formatTo(parsedDate, 'yyyy-MM-dd'), 'yyyy-MM-dd') : todayClone; }); selectedDate.value = selectedDateObj.value; diff --git a/packages/ui-vue/components/date-picker/src/composition/use-date.ts b/packages/ui-vue/components/date-picker/src/composition/use-date.ts index c31520c444d..b8ca85ef15e 100644 --- a/packages/ui-vue/components/date-picker/src/composition/use-date.ts +++ b/packages/ui-vue/components/date-picker/src/composition/use-date.ts @@ -110,7 +110,7 @@ export function useDate(): UseDate { } function getDateObject(dateString: string, dateFormat: string): DateObject { - const delimeters = dateFormat.match(/[^(dMyHms)]{1,}/g); + const delimeters = dateFormat.match(/[^(DdMmYy)]{1,}/g); const dateObject: DateObject = {}; if (delimeters) { -- Gitee From 1d0c3ea4f9e7c334230020d0326e797d669d230f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 22 Apr 2025 17:26:11 +0800 Subject: [PATCH 151/156] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dlookup?= =?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A4=B9=E5=8A=9F=E8=83=BD=E5=A4=B1=E6=95=88?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/lookup/src/composition/use-favorite.tsx | 2 +- .../components/lookup/src/composition/use-user-data.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx index df8282d02f3..9dce96862a7 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx +++ b/packages/ui-vue/components/lookup/src/composition/use-favorite.tsx @@ -35,7 +35,7 @@ export function useFavorite(props: LookupProps, idField: string) { userDataState.favoriteItems = userDataState.favoriteItems.filter(item => item[idField] !== itemId); } - userDataService?.saveUserData().then((res) => { + userDataService?.saveUserData(true).then((res) => { const message = actiion === 'add' ? '已添加到收藏' : '已从收藏中移除'; notifyService?.success({ message, position: 'top-center' }); }); diff --git a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts index 297ff872931..d0eb50ecb07 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-user-data.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-user-data.ts @@ -23,7 +23,7 @@ export const LOOKUP_USER_DATA_SERVICE = 'F_LOOKUP_USER_DATA_SERVICE'; export interface UserDataService { userDataState: any; - saveUserData: () => Promise; + saveUserData: (isFavorites?: boolean) => Promise; getFavoriteData: () => Promise; getUserData: () => Promise; setDialogSize: (size: { width: number; height: number }) => void; @@ -66,8 +66,8 @@ export function useUserData(props: LookupProps, useHttpComposition: UseHttpCompo userDataState.data.size = { width, height }; } - function saveUserData() { - if (props.enableUserData && httpService) { + function saveUserData(isFavorites = false) { + if ((props.enableUserData || isFavorites) && httpService) { const { key, data } = userDataState; const configData = { configkey1: key, -- Gitee From 90a2d60c2b1133c11fe1e6dc28f4fa54c95b539a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 23 Apr 2025 11:15:37 +0800 Subject: [PATCH 152/156] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4lookup?= =?UTF-8?q?=E6=A0=91=E7=BB=93=E6=9E=84=E6=95=B0=E6=8D=AE=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui-vue/components/lookup/src/composition/use-http.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/ui-vue/components/lookup/src/composition/use-http.ts b/packages/ui-vue/components/lookup/src/composition/use-http.ts index 5ed96fd0604..9e4973465b9 100644 --- a/packages/ui-vue/components/lookup/src/composition/use-http.ts +++ b/packages/ui-vue/components/lookup/src/composition/use-http.ts @@ -43,6 +43,8 @@ export function useHttp(props: LookupProps, context: any): UseHttpComposition { const lookupStates = useLookupState(props); const { pageInfoState, lookupState, navigationState, lookupOptions } = lookupStates; + lookupOptions.loadTreeDataType = 'all'; + const { searchFieldItems, navSearchFieldItems } = useSearchFields(props, lookupState, navigationState); const uri = ref(props.uri); const idValues = ref(props.idValue); -- Gitee From 101a10529a041362a9ca4dbd0bc5041cbe697b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Wed, 23 Apr 2025 14:12:14 +0800 Subject: [PATCH 153/156] =?UTF-8?q?fix:=20lookup=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=97=B6=E5=90=8C=E6=AD=A5=E6=A0=91=E7=BB=93=E6=9E=84=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converters/lookup-property.converter.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts index 502ccc418bb..aa394bfc1d7 100644 --- a/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts +++ b/packages/ui-vue/components/lookup/src/property-config/converters/lookup-property.converter.ts @@ -26,7 +26,7 @@ export const lookupDefaultConverter = { } if (propertyKey === 'onlySelectLeaf') { - return schema.editor[propertyKey] == null? false: schema.editor[propertyKey]; + return schema.editor[propertyKey] == null ? false : schema.editor[propertyKey]; } if (propertyKey === 'loadTreeDataType') { @@ -94,13 +94,15 @@ export const lookupDataSourceConverter = { schema.editor.dataSource.type = "ViewObject"; - const { pageInfo, treeInfo } = metadataContent.dataSource; + const { pageInfo } = metadataContent.dataSource; setPageInfo(schema.editor, pageInfo); + const { treeInfo } = displayType.toUpperCase() === 'NAVTREELIST' ? metadataContent.navigation : metadataContent.dataSource; + if (treeInfo) { const { onlySelectLeaf, loadDataType } = treeInfo; schema.editor.loadTreeDataType = loadDataType || 'all'; - schema.editor.onlySelectLeaf = onlySelectLeaf == null ? false: onlySelectLeaf; + schema.editor.onlySelectLeaf = onlySelectLeaf == null ? false : onlySelectLeaf; } if (!schema.editor.dataSource.uri) { -- Gitee From c381d1f5950a2dce9afb54aa1c0f7762edfa87ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=A7=80=E6=89=8D?= Date: Tue, 29 Apr 2025 19:09:42 +0800 Subject: [PATCH 154/156] =?UTF-8?q?fix:=20time-picker=E6=98=93=E7=94=A8?= =?UTF-8?q?=E6=80=A7=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../button-edit/src/composition/use-text-box.ts | 2 +- .../date-picker-container.component.tsx | 7 +++++++ .../input-group/src/input-group.props.ts | 2 +- .../src/components/time.component.tsx | 16 ++++++++-------- .../time-picker/src/time-picker.component.tsx | 1 + .../ui-vue/demos/date-picker/date_format.vue | 2 +- packages/ui-vue/demos/input-group/extend.vue | 17 +++++++++++++++++ .../demos/time-picker/disabled-minutes.vue | 12 +++++------- .../demos/time-picker/disabled-seconds.vue | 15 ++++++++------- .../ui-vue/docs/components/date-picker/index.md | 4 +++- .../ui-vue/docs/components/input-group/index.md | 4 ++-- 11 files changed, 54 insertions(+), 28 deletions(-) diff --git a/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts b/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts index 43fd950cc26..91a54ed85e9 100644 --- a/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts +++ b/packages/ui-vue/components/button-edit/src/composition/use-text-box.ts @@ -51,7 +51,7 @@ export function useTextBox( 'input-group': true, 'f-state-disabled': props.disable, 'f-state-editable': props.editable && !props.disable && !props.readonly, - 'f-state-readonly': props.readonly && !props.disable, + 'f-state-readonly': props.readonly, 'f-state-focus': hasFocusedTextBox.value, 'input-group--has-clear':props.enableClear&&hasClearClass.value }; diff --git a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx index a45df747a87..a7cd40acb60 100644 --- a/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx +++ b/packages/ui-vue/components/date-picker/src/components/date-picker-container/date-picker-container.component.tsx @@ -441,6 +441,13 @@ export default defineComponent({ selectedDate.value.month = month; selectedDate.value.day = day; } + + const { year, month } = currentDate; + selectedMonth.value = { + year: year, + month: month + }; + } function onClickWeek($event: any) { } diff --git a/packages/ui-vue/components/input-group/src/input-group.props.ts b/packages/ui-vue/components/input-group/src/input-group.props.ts index 0617ed5c79b..ed395f72255 100644 --- a/packages/ui-vue/components/input-group/src/input-group.props.ts +++ b/packages/ui-vue/components/input-group/src/input-group.props.ts @@ -60,7 +60,7 @@ export const inputGroupProps = { /** 当组件禁用或只读时显示后边的按钮 */ showButtonWhenDisabled: { Type: Boolean, default: false }, /** tab索引 */ - tabIndex: { Type: Number || undefined, default: undefined }, + tabIndex: { Type: Number, default: 0 }, /** 文本在输入框中的对齐方式 */ textAlign: { Type: String, default: 'left' }, /** 是否启用前置扩展信息;在输入框前面 显示 ① 图标鼠标滑过后显示 */ diff --git a/packages/ui-vue/components/time-picker/src/components/time.component.tsx b/packages/ui-vue/components/time-picker/src/components/time.component.tsx index 60e30c55b0e..e7253902a47 100644 --- a/packages/ui-vue/components/time-picker/src/components/time.component.tsx +++ b/packages/ui-vue/components/time-picker/src/components/time.component.tsx @@ -168,7 +168,7 @@ export default defineComponent({ const timePickerComboBoxStyle = computed(() => { const styleObject = { - width: use12Hours.value ? `${panelWidth.value}px` : '' + width: `${panelWidth.value}px` } as Record; return styleObject; }); @@ -439,22 +439,22 @@ export default defineComponent({ if (props.showHeader) { return (
        {showHour.value &&
        -
          +
        } {showMinute.value &&
        -
          +
        } {showSecond.value &&
        -
          +
        } {props.use12Hours &&
        -
          +
        } @@ -466,9 +466,9 @@ export default defineComponent({ return () => { return ( -
        +
        -
        +
        {getHeaderHtml()}
        {showHour.value && ( @@ -518,7 +518,7 @@ export default defineComponent({ )} {use12Hours.value && (
        -
          +
            {use12HoursRange.value.map((hour: any) => { return (
          • 存储格式:{{ currentDate11 }} diff --git a/packages/ui-vue/demos/input-group/extend.vue b/packages/ui-vue/demos/input-group/extend.vue index 6a3caa95df8..3b4b86116a7 100644 --- a/packages/ui-vue/demos/input-group/extend.vue +++ b/packages/ui-vue/demos/input-group/extend.vue @@ -72,6 +72,23 @@ function onUpdateExtendInfo() {
        + +
        +
        +
        + +
        + +
        +
        +
        +
        diff --git a/packages/ui-vue/demos/time-picker/disabled-minutes.vue b/packages/ui-vue/demos/time-picker/disabled-minutes.vue index b39926b6e72..ffbfec84cfb 100644 --- a/packages/ui-vue/demos/time-picker/disabled-minutes.vue +++ b/packages/ui-vue/demos/time-picker/disabled-minutes.vue @@ -20,9 +20,9 @@ function disabledMinutesUseHour(hour: number){
        - function disableHours(){ - return [4,5,8,14]; - } + function disabledMinutes(hour: number){ + return [2,4,6,8,10,12,14,16,18,20,22]; +}
        @@ -37,13 +37,11 @@ function disabledMinutesUseHour(hour: number){
        -
        +
      @@ -57,6 +55,6 @@ function disabledMinutesUseHour(hour: number){
      -
      +
      -->
      diff --git a/packages/ui-vue/demos/time-picker/disabled-seconds.vue b/packages/ui-vue/demos/time-picker/disabled-seconds.vue index e4e6ee20a3a..326d7b5cda7 100644 --- a/packages/ui-vue/demos/time-picker/disabled-seconds.vue +++ b/packages/ui-vue/demos/time-picker/disabled-seconds.vue @@ -2,11 +2,12 @@ import { ref } from 'vue' const defaultValue = ref('15:08:16') function disabledSeconds(hour: number, minute: number){ - let result:Array=[]; - for(let index=0;index<=minute;index++){ - result.push(index); - } - return result; + // let result:Array=[]; + // for(let index=0;index<=minute;index++){ + // result.push(index); + // } + // return result; + return [2,4,6,8,10,12,14,16,18,20,22]; }