From 4dc5dac8936f8e7b236d70b8c97a5ab644ccda76 Mon Sep 17 00:00:00 2001 From: Cano1997 <1978141412@qq.com> Date: Fri, 24 Oct 2025 20:13:37 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=8D=A1=E7=89=87=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8E=92=E5=BA=8F=E3=80=81?= =?UTF-8?q?=E5=88=86=E7=BB=84=E9=94=9A=E7=82=B9=E5=8A=9F=E8=83=BD=E3=80=81?= =?UTF-8?q?=E5=B8=B8=E8=A7=84=E6=96=B0=E5=BB=BA=E3=80=81=E5=88=86=E7=BB=84?= =?UTF-8?q?=E6=96=B0=E5=BB=BA,=E4=BC=98=E5=8C=96=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E6=9B=B4=E5=A4=9A=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + src/control/data-view/data-view.scss | 155 +++++++++++++-- src/control/data-view/data-view.tsx | 177 ++++++++++++++---- .../setting-container.controller.ts | 4 +- 4 files changed, 281 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa98e56570c..81003c5f4a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - 数据关系分页栏支持侧边显示 - 新增应用全局参数和路由参数 - 树新增计数器 +- 卡片支持自定义排序、分组锚点功能、常规新建、分组新建 ### Change @@ -61,6 +62,7 @@ - 数据关系分页栏样式变量抽取 - 日历部件样式变量抽取,并支持暗色主题 - 视图消息添加padding +- 优化卡片加载更多样式 ### Fixed diff --git a/src/control/data-view/data-view.scss b/src/control/data-view/data-view.scss index e11c5c64f4f..edbe243bf49 100644 --- a/src/control/data-view/data-view.scss +++ b/src/control/data-view/data-view.scss @@ -3,12 +3,24 @@ $control-dataview: ( item-padding: getCssVar(spacing, base-tight) getCssVar(spacing, base), padding: getCssVar(spacing, tight), item-gap: getCssVar(spacing, base, tight), - pagination-height: var(--van-pagination-height), item-bg-color: transparent, - group-height: getCssVar(height, control, large), - group-padding: 0 getCssVar(spacing, base), - more-color: getCssVar(color, link), + active-text-color: getCssVar(color, primary), + active-bg-color: getCssVar(color, primary, light, default), + group-font-size: getCssVar(font-size, header-6), + group-bg-color: getCssVar(color, bg, 0), + group-text-color: getCssVar(color, text, 1), + group-header-padding: getCssVar(spacing, base), + group-padding: 0 getCssVar(spacing, tight), + group-anchor-bg-color: getCssVar(color, bg, 1), + group-anchor-border-radius: getCssVar(border, radius, small), + group-anchor-right: getCssVar('spacing', 'tight'), + group-anchor-item-padding: getCssVar('spacing', 'tight') getCssVar('spacing', 'base'), item-shadow: getCssVar(shadow, elevated), + button-padding: getCssVar(spacing, tight) 0, + button-bg: getCssVar(color, fill, 0), + button-active-bg: getCssVar(color, fill, 2), + button-color: getCssVar(color, primary), + add-border: 2px dashed getCssVar(color, border), ); @include b(control-dataview) { @@ -27,7 +39,12 @@ $control-dataview: ( @include e(content) { display: flex; flex-wrap: wrap; + height: 100%; gap: getCssVar(control-dataview, item-gap); + + @include when(enable-anchor) { + height: 100%; + } } @include e(row) { @@ -37,29 +54,39 @@ $control-dataview: ( } } - @include e(collapse-item) { - .van-collapse-item__title { - height: getCssVar(control-dataview, group-height); - align-items: center; - padding: getCssVar(control-dataview, group-padding); + @include when(enable-page) { + display: flex; + flex-direction: column; + .#{bem(control-dataview, content-container)} { + flex: auto; + } + .#{bem(control-dataview, pagination)} { + flex: none; } } - @include when(enable-page) { - .#{bem(control-dataview, content-container)} { - height: calc(100% - getCssVar(control-dataview, pagination-height)); + @include when(enable-pagination) { + .#{bem(control-dataview, content)} { + height: auto; } } @include e(load-more) { - @include flex(row, center, center); - height: getCssVar(control-dataview, pagination-height); - cursor: pointer; - color: getCssVar(control-dataview, more-color); + padding: getCssVar(control-dataview, button-padding); + .van-button { + width: 100%; + border: none; + background-color: getCssVar(control-dataview, button-bg); + color: getCssVar(control-dataview, button-color); + &:active { + background-color: getCssVar(control-dataview, button-active-bg); + } + } } } @include b(control-dataview-item) { + flex: none; padding: getCssVar(control-dataview, item-padding); box-shadow: getCssVar(control-dataview, item-shadow); background-color: getCssVar(control-dataview, item-bg-color); @@ -73,4 +100,100 @@ $control-dataview: ( >.van-card { padding: 0 } +} + +// 分组样式 +@include b('control-dataview-group') { + height: 100%; + width: 100%; + @include e('container') { + width: 100%; + height: 100%; + padding: getCssVar(control-dataview, group-padding); + overflow-y: auto; + } + + @include e(item) { + display: flex; + flex-direction: column; + gap: getCssVar(control-dataview, item-gap); + } + + // 分组标题样式 + @include e('caption') { + padding: getCssVar(control-dataview, group-header-padding); + font-size: getCssVar(control-dataview, group-font-size); + color: getCssVar(control-dataview, group-text-color); + background-color: getCssVar(control-dataview, group-bg-color); + } + + // 分组锚点容器样式 + @include e('anchor-container') { + position: absolute; + right: getCssVar(control-dataview, group-anchor-right); + top: 45%; + transform: translateY(-50%); + border-radius: getCssVar(control-dataview, group-anchor-border-radius); + overflow: hidden; + display: flex; + flex-direction: column; + background-color: getCssVar(control-dataview, group-anchor-bg-color); + box-shadow: + getCssVar(control-dataview, box-shadow-inner), + getCssVar(control-dataview, box-shadow-outer); + } + + // 分组锚点项样式 + @include e('anchor-item') { + width: 100%; + text-align: center; + padding: getCssVar(control-dataview, group-anchor-item-padding); + + @include when(active) { + color: getCssVar(control-dataview, active-text-color); + background-color: getCssVar(control-dataview, active-bg-color); + } + } +} + +// 分组锚点容器样式 +@include e('anchor-container') { + position: absolute; + right: getCssVar(control-dataview, group-anchor-right); + top: 45%; + transform: translateY(-50%); + border-radius: getCssVar(control-dataview, group-anchor-border-radius); + overflow: hidden; + display: flex; + flex-direction: column; + background-color: getCssVar(control-dataview, group-anchor-bg-color); + box-shadow: + getCssVar(control-dataview, item-shadow); +} + +// 分组锚点项样式 +@include e('anchor-item') { + width: 100%; + text-align: center; + padding: getCssVar(control-dataview, group-anchor-item-padding); + + @include when(active) { + color: getCssVar(control-dataview, active-text-color); + background-color: getCssVar(control-dataview, active-bg-color); + } +} + +// 快速工具栏样式 +@include b(control-dataview-quicktoolbar) { + width: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +@include b('control-dataview-add-btn'){ + width: 100%; + margin: getCssVar(control-dataview, button-padding); + border: getCssVar(control-dataview, add-border); + color: getCssVar(control-dataview, button-color); } \ No newline at end of file diff --git a/src/control/data-view/data-view.tsx b/src/control/data-view/data-view.tsx index bec253ee77b..98e0ff08f37 100644 --- a/src/control/data-view/data-view.tsx +++ b/src/control/data-view/data-view.tsx @@ -10,6 +10,7 @@ import { DataViewControlController, IControlProvider, } from '@ibiz-template/runtime'; +import { createUUID } from 'qx-util'; import { usePagination } from '../../util'; import './data-view.scss'; @@ -57,7 +58,10 @@ export const DataViewControl = defineComponent({ (...args) => new DataViewControlController(...args), ); const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`); - const active = ref([]); + + const isUpdating = ref(false); + + const scrollContainer = ref(); // 是否可以加载更多 const isLodeMoreDisabled = computed(() => { @@ -74,6 +78,29 @@ export const DataViewControl = defineComponent({ ); }); + const scrollKey = createUUID(); + const selectScrollKey = ref(); + + // 处理分组锚点项点击 + const handleGroupAnchorClick = (_id: string) => { + // 获取目标元素和滚动容器 + const targetElement = document.getElementById(_id); + const el = scrollContainer.value; + + if (targetElement && el) { + const targetTop = targetElement.offsetTop; + const containerTop = el.offsetTop; + const relativePosition = targetTop - containerTop; + + // 基于滚动容器进行滚动 + el.scrollTo({ + top: relativePosition, + behavior: 'smooth', + }); + selectScrollKey.value = _id; + } + }; + // 本地数据模式 const initSimpleData = (): void => { if (!props.data) { @@ -83,6 +110,15 @@ export const DataViewControl = defineComponent({ c.afterLoad({}, c.state.items); }; + // 添加动画帧,反正加载多次 + c.evt.on('onLoadSuccess', () => { + isUpdating.value = true; + window.requestAnimationFrame(() => { + isUpdating.value = false; + }); + selectScrollKey.value = ''; + }); + c.evt.on('onCreated', async () => { if (props.isSimple) { initSimpleData(); @@ -111,6 +147,21 @@ export const DataViewControl = defineComponent({ return !c.model.enableGroup && c.model.pagingMode === 3; }); + const renderAddBtn = (group?: IData) => { + if (!c.enableNew) { + return; + } + return ( + c.onClickNew(event, group?.key)} + > + 新增 + + ); + }; + // 绘制项布局面板 const renderPanelItem = (item: IData, modelData: ILayoutPanel): VNode => { const { context, params } = c; @@ -157,6 +208,19 @@ export const DataViewControl = defineComponent({ if (!isLoaded) { return; } + const ctrlModel = c.model.controls?.find(item => { + return item.name === `${c.model.name!}_quicktoolbar`; + }); + if (ctrlModel) { + return ( + + ); + } return ( isLoaded && ( + return [ + {items.map(item => { return ( @@ -237,55 +301,86 @@ export const DataViewControl = defineComponent({ ); })} - - ); + , + renderAddBtn(), + ]; } + return [ + ...items.map(item => { + return renderCard(item); + }), + renderAddBtn(), + ]; + }; + + const renderGroup = () => { + const showGroupAnchor = c.state.groups.length > 1 && c.showGroupAnchor; + return [ +
+
+ {c.state.groups.map((group, index) => { + const _id = `group-${scrollKey}-${index}`; + return [ +
+ {group.caption} +
, +
+ {renderContent(group.children)} +
, + ]; + })} +
+ {showGroupAnchor ? ( +
+ {c.state.groups.map((group, index) => { + const _id = `group-${scrollKey}-${index}`; + return ( +
handleGroupAnchorClick(_id)} + class={[ + ns.be('group', 'anchor-item'), + ns.is('active', selectScrollKey.value === _id), + ]} + > + {group.caption} +
+ ); + })} +
+ ) : null} +
, + ]; + }; + + // 绘制卡片内容 + const renderMDContent = () => { + const showGroupAnchor = c.state.groups.length > 1 && c.showGroupAnchor; return ( c.loadMore()} > - {c.state.items.map(item => { - return renderCard(item); - })} + {c.enableGroup ? renderGroup() : renderContent(c.state.items)} ); }; - // 绘制卡片内容 - const renderMDContent = () => { - const model: IDEDataView = c.model; - if (model.groupMode !== 'NONE') { - return ( - - {c.state.groups.map((group, index) => { - return ( - - {renderContent(group.children)} - - ); - })} - - ); - } - return renderContent(c.state.items); - }; - // 加载更多 const loadMoreIcon = () => { return ( -
c.loadMore()}> - {ibiz.i18n.t('control.common.loadMore')} +
+ c.loadMore()}> + {ibiz.i18n.t('control.common.loadMore')} +
); }; @@ -304,6 +399,7 @@ export const DataViewControl = defineComponent({ return { c, ns, + scrollContainer, showCollapseOrExpandIcon, onPageChange, renderNoData, @@ -321,11 +417,13 @@ export const DataViewControl = defineComponent({ 'enable-page', enablePagingBar || this.showCollapseOrExpandIcon, ), + this.ns.is('enable-pagination', enablePagingBar), ]} controller={this.c} >
{this.c.state.isCreated && this.renderMDContent()} + {this.renderLoadMore()}
{enablePagingBar ? ( ) : null} - {this.renderLoadMore()} ); }, diff --git a/src/panel-component/setting-container/setting-container.controller.ts b/src/panel-component/setting-container/setting-container.controller.ts index 62c58f38839..bbac9054faf 100644 --- a/src/panel-component/setting-container/setting-container.controller.ts +++ b/src/panel-component/setting-container/setting-container.controller.ts @@ -19,7 +19,9 @@ export class SettingContainerController extends PanelContainerController Date: Fri, 24 Oct 2025 20:17:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?style:=20=E4=BC=98=E5=8C=96=E5=A4=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=BD=BD=E6=9B=B4=E5=A4=9A=E3=80=81?= =?UTF-8?q?=E5=88=86=E7=BB=84=E9=94=9A=E7=82=B9=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/control/list/list-render-util.tsx | 6 ++- src/control/list/md-ctrl/md-ctrl.scss | 53 +++++++++++++-------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81003c5f4a9..19707d1896a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ - 日历部件样式变量抽取,并支持暗色主题 - 视图消息添加padding - 优化卡片加载更多样式 +- 优化多数据加载更多、分组锚点样式 ### Fixed diff --git a/src/control/list/list-render-util.tsx b/src/control/list/list-render-util.tsx index 146101e2b46..684e7c122d4 100644 --- a/src/control/list/list-render-util.tsx +++ b/src/control/list/list-render-util.tsx @@ -162,8 +162,10 @@ export function useListRender( // 加载更多 const loadMoreIcon = () => { return ( -
c.loadMore()}> - {ibiz.i18n.t('control.common.loadMore')} +
+ c.loadMore()}> + {ibiz.i18n.t('control.common.loadMore')} +
); }; diff --git a/src/control/list/md-ctrl/md-ctrl.scss b/src/control/list/md-ctrl/md-ctrl.scss index 7b8e5f0d927..6f335ce0ac5 100644 --- a/src/control/list/md-ctrl/md-ctrl.scss +++ b/src/control/list/md-ctrl/md-ctrl.scss @@ -2,8 +2,8 @@ $control-mobmdctrl: ( font-size: getCssVar(font-size, regular), text-color: getCssVar(color, text, 0), border-color: getCssVar(color, border), - active-text-color: getCssVar(color, white), - active-bg-color: getCssVar(color, primary), + active-text-color: getCssVar(color, primary), + active-bg-color: getCssVar(color, primary, light, default), padding: getCssVar(spacing, tight) getCssVar(spacing, base), overflow: getCssVar(control, overflow), box-shadow-inner: 0 0 0 rgba(0 0 0 / 30%), @@ -22,16 +22,16 @@ $control-mobmdctrl: ( group-text-color: getCssVar(color, text, 1), group-padding: getCssVar(spacing, base), group-anchor-bg-color: getCssVar(color, bg, 1), + group-anchor-active-bg-color: getCssVar(color, primary, light, default), + group-anchor-color: getCssVar(color, primary), group-anchor-border-radius: getCssVar(border, radius, small), group-anchor-right: getCssVar('spacing', 'tight'), - group-anchor-item-padding: getCssVar('spacing', 'extra-tight'), + group-anchor-item-padding: getCssVar(spacing, base-tight) getCssVar(spacing, base), group-anchor-max-width: 120px, - load-more-font-size: getCssVar(font-size, regular), - load-more-text-color: getCssVar(color, primary), - load-more-padding: getCssVar(spacing, tight), - load-more-btn-height: getCssVar('height-control', 'small'), - load-more-btn-padding: getCssVar('spacing', 'tight') getCssVar('spacing', 'base'), - load-more-btn-border-radius: getCssVar(border, radius, full), + more-padding: getCssVar(spacing, tight) getCssVar(spacing, base), + more-bg: getCssVar(color, fill, 0), + more-active-bg: getCssVar(color, fill, 2), + more-color: getCssVar(color, primary), pagination-height: getCssVar('height-control', 'large'), simplelist-height: 250px, ); @@ -88,6 +88,20 @@ $control-mobmdctrl: ( overflow-y: auto; } } + + // 加载更多样式 +@include e(load-more) { + padding: getCssVar(control-mobmdctrl, more-padding); + .van-button { + width: 100%; + border: none; + background-color: getCssVar(control-mobmdctrl, more-bg); + color: getCssVar(control-mobmdctrl, more-color); + &:active { + background-color: getCssVar(control-mobmdctrl, more-active-bg); + } + } +} } // 列表项样式 @@ -162,29 +176,12 @@ $control-mobmdctrl: ( padding: getCssVar(control-mobmdctrl, group-anchor-item-padding); @include when(active) { - color: getCssVar(control-mobmdctrl, active-text-color); - background-color: getCssVar(control-mobmdctrl, active-bg-color); + color: getCssVar(control-mobmdctrl, group-anchor-color); + background-color: getCssVar(control-mobmdctrl, group-anchor-active-bg-color); } } } -// 加载更多样式 -@include b(control-mobmdctrl-load-more) { - display: flex; - justify-content: center; - padding: getCssVar(control-mobmdctrl, load-more-padding); - font-size: getCssVar(control-mobmdctrl, load-more-font-size); - color: getCssVar(control-mobmdctrl, load-more-text-color); - - // 加载更多按钮样式 - span { - display: flex; - align-items: center; - min-height: getCssVar(control-mobmdctrl, load-more-btn-height); - cursor: pointer; - } -} - // 部件为选择模式并且项为布局面板时的列表项样式 @include b(control-mobmdctrl-select-item) { display: flex; -- Gitee