提交 cad9386e 编写于 作者: Mosher's avatar Mosher

add:新增列表视图、列表部件支持

上级 ccdc5137
{{#eq ctrl.controlType "FORM"}}{{> @macro/front-end/views/view-control/view-form/view-control-form.hbs}}{{/eq~}}
{{#eq ctrl.controlType "SEARCHFORM"}}{{> @macro/front-end/views/view-control/view-search-form/view-control-search-form.hbs}}{{/eq~}}
{{#eq ctrl.controlType "GRID"}}{{> @macro/front-end/views/view-control/view-grid/view-control-grid.hbs}}{{/eq~}}
{{#eq ctrl.controlType "LIST"}}{{> @macro/front-end/views/view-control/view-list/view-control-list.hbs}}{{/eq~}}
{{#eq ctrl.controlType "APPMENU"}}{{> @macro/front-end/views/view-control/view-menu/view-control-menu.hbs}}{{/eq~}}
{{#eq ctrl.controlType "PICKUPVIEWPANEL"}}{{> @macro/front-end/views/view-control/view-pickup-panel/view-pickup-panel.hbs}}{{/eq~}}
{{#eq ctrl.controlType "TREEVIEW"}}{{> @macro/front-end/views/view-control/view-tree/view-control-tree.hbs}}{{/eq~}}
\ No newline at end of file
{{ctrl.name}}:{
action:{
loadAction: '{{ctrl.getPSControlAction.psAppDEMethod.codeName}}',
removeAction: '{{ctrl.removePSControlAction.psAppDEMethod.codeName}}',
updateAction: '{{ctrl.updatePSControlAction.psAppDEMethod.codeName}}',
loadDraftAction: '{{ctrl.getDraftPSControlAction.psAppDEMethod.codeName}}',
createAction: '{{ctrl.createPSControlAction.psAppDEMethod.codeName}}',
fetchAction:'{{ctrl.fetchPSControlAction.psAppDEMethod.codeName}}'
}
},
\ No newline at end of file
<script setup lang="ts">
</script>
<template>
<AppViewBaseLayout class="app-list-view-layout">
<template v-slot:header-top>
<slot name="topMessage" />
</template>
<template v-slot:header-left>
<slot name="caption" />
</template>
<template v-slot:header-content>
</template>
<template v-slot:header-right>
<div class="list-view__header-right">
<slot name="quickGroupSearch" />
<slot name="quickSearch" />
<slot name="toolbar" />
</div>
</template>
<template v-slot:header-bottom>
<div>
<slot name="quickSearchForm" />
<slot name="searchForm" />
<slot name="searchBar" />
</div>
</template>
<template v-slot:body-top>
<slot name="bodyMessage" />
</template>
<slot />
<template v-slot:footer-content>
<slot name="bottomMessage" />
</template>
</AppViewBaseLayout>
</template>
<style lang="scss">
.app-list-view-layout {
.list-view__header-right {
display: flex;
flex-wrap: nowrap;
}
}
</style>
\ No newline at end of file
......@@ -12,3 +12,4 @@ export * from './tree-exp-view'
export * from './tree-view'
export * from './portal-view'
export * from './tab-exp-view'
export * from './list-view'
export * from './list-view-prop'
export * from './list-view-state'
export * from './list-view'
\ No newline at end of file
import { MDViewProps } from "../md-view";
/**
* @description 列表视图输入参数
* @export
* @interface ListViewProps
* @extends {MDViewProps}
*/
export interface ListViewProps extends MDViewProps {
}
\ No newline at end of file
import { MDViewState } from "../md-view";
/**
* @description 列表视图状态
* @export
* @interface ListViewState
* @extends {MDViewState}
*/
export interface ListViewState extends MDViewState {
}
\ No newline at end of file
import { IParam } from "@core";
import { MDView } from "../md-view";
/**
* @description 列表视图
* @export
* @class ListView
* @extends {MDView}
*/
export class ListView extends MDView {
/**
* @description 列表部件
* @type {IParam}
* @memberof ListView
*/
public declare list: IParam;
/**
* @description 处理视图初始化
* @memberof ListView
*/
public useViewInit(): void {
super.useViewInit();
this.list = ref(null);
}
/**
* @description 获取多数据部件
* @return {*}
* @memberof ListView
*/
public getMDCtrl() {
return unref(this.list);
}
/**
* @description 安装视图所有功能模块的方法
* @return {*}
* @memberof GridView
*/
public moduleInstall() {
const superParams = super.moduleInstall();
return {
...superParams,
list: this.list
};
}
}
\ No newline at end of file
......@@ -15,3 +15,4 @@ export * from './dashboard-control'
export * from './portlet-control'
export * from './tab-exp-panel-control'
export * from './tab-view-panel-control'
export * from './list-control'
export * from './list-control-prop'
export * from './list-control-state'
export * from './list-control'
\ No newline at end of file
import { MDControlProps } from "../md-control";
/**
* @description 列表部件
* @export
* @interface ListControlProps
* @extends {MDControlProps}
*/
export interface ListControlProps extends MDControlProps {
}
\ No newline at end of file
import { MDControlState } from "../md-control";
/**
* @description 列表部件状态
* @export
* @interface ListControlState
* @extends {MDControl}
*/
export interface ListControlState extends MDControlState {
}
\ No newline at end of file
import { MDControl } from "../md-control";
/**
* @description 列表部件
* @export
* @class ListControl
* @extends {MDControl}
*/
export class ListControl extends MDControl {
/**
* @description 安装部件所有功能模块的方法
* @return {*}
* @memberof ListControl
*/
public moduleInstall() {
const superParams = super.moduleInstall();
return {
...superParams,
}
}
}
\ No newline at end of file
export * from './control-service-base'
export * from './edit-form-service'
export * from './grid-service'
export * from './tree-service'
\ No newline at end of file
export * from './tree-service'
export * from './list-service'
\ No newline at end of file
import { ControlServiceBase, ControlVOBase, hasFunction, IParam } from '@core';
/**
* @deprecated 列表部件服务
* @export
* @class ListService
* @extends {ControlServiceBase<T>}
* @template T
*/
export class ListService<T extends ControlVOBase> extends ControlServiceBase<T> {
/**
* @description 加载草稿
* @param {IParam} context 上下文
* @param {IParam} data 行为数据
* @param { action: string; isLoading?: boolean } opts 行为参数
* @return {*} {Promise<any>}
* @memberof ListService
*/
public async loadDraft(context: IParam, data: IParam, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
// todo主键
const action = hasFunction(_entityService, opts.action) ? opts.action : 'GetDraft';
const response = await _entityService[action](Context, Data, opts.isLoading);
response.data = this.newControlVO(response.data);
response.data.srfuf = '0';
return this.handleResponse(response, opts);
}
/**
* @description 加载数据
* @param {IParam} context 上下文
* @param {IParam} data 行为数据
* @param { action: string; isLoading?: boolean } opts 行为参数
* @return {*} {Promise<any>}
* @memberof ListService
*/
public async search(context: IParam, data: IParam, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
const action = hasFunction(_entityService, opts.action) ? opts.action : 'GET';
const response = await _entityService[action](Context, Data, opts.isLoading);
let resData: any[] = response.data;
for (let index = 0; index < resData.length; index++) {
resData[index] = this.newControlVO(resData[index]);
}
return this.handleResponse(response, opts);
}
/**
* @description 新建数据
* @param {IParam} context 上下文
* @param {IParam} data 行为数据
* @param { action: string; isLoading?: boolean } opts 行为参数
* @return {*} {Promise<any>}
* @memberof ListService
*/
public async create(context: IParam, data: IParam, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
const action = hasFunction(_entityService, opts.action) ? opts.action : 'Create';
const response = await _entityService[action](Context, Data, opts.isLoading);
response.data = this.newControlVO(response.data);
return this.handleResponse(response, opts);
}
/**
* @description 删除数据
* @param {IParam} context 上下文
* @param {IParam} data 行为数据
* @param { action: string; isLoading?: boolean } opts 行为参数
* @return {*} {Promise<any>}
* @memberof ListService
*/
public async remove(context: IParam, data: IParam, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
const action = hasFunction(_entityService, opts.action) ? opts.action : 'Remove';
const response = await _entityService[action](Context, Data, opts.isLoading);
response.data = this.newControlVO(response.data);
return this.handleResponse(response, opts);
}
/**
* @description 更新
* @param {*} context 上下文
* @param {*} data 行为数据
* @param { action: string; isLoading?: boolean } opts 行为参数
* @return {*} {Promise<any>}
* @memberof ListService
*/
public async update(context: any, data: any, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
const action = hasFunction(_entityService, opts.action) ? opts.action : 'Update';
const response = await _entityService[action](Context, Data, opts.isLoading);
response.data = this.newControlVO(response.data);
return this.handleResponse(response, opts);
}
/**
* 前台逻辑
*
* @param [context={}] 上下文参数
* @param [data={}] 视图参数
* @param opts
* @return {*}
*/
public async frontLogic(context: any, data: any, opts: { action: string; isLoading?: boolean }): Promise<any> {
let _entityService: any = this.entityService;
const { context: Context, data: Data } = this.handleRequestData(context, data, opts);
if (hasFunction(_entityService, opts.action)) {
const response = await _entityService[opts.action](Context, Data, opts.isLoading);
response.data = this.newControlVO(response.data);
return this.handleResponse(response, opts);
} else {
return null;
}
}
}
\ No newline at end of file
import {{page.codeName}} from "./{{spinalCase page.codeName}}.vue";
export default {{page.codeName}};
export const viewState = {
enableQuickSearch: {{#if page.enableQuickSearch}}{{page.enableQuickSearch}}{{else}}false{{/if}},
expandSearchForm: {{#if page.expandSearchForm}}{{page.expandSearchForm}}{{else}}false{{/if}},
{{> @macro/front-end/views/view-base-config.hbs}}
};
\ No newline at end of file
<script setup lang="ts">
import { Subject } from 'rxjs';
import { FilterOutlined } from '@ant-design/icons-vue';
import { ListView, IActionParam, IParam, IContext } from '@core';
import { viewState } from './{{spinalCase page.codeName}}-state';
{{#page.ctrls}}
{{#eq controlType "LIST"}}
import { {{codeName}}List } from '@widgets/{{spinalCase psAppDataEntity.codeName}}/{{spinalCase codeName}}-list';
{{/eq}}
{{#if (and (eq controlType "SEARCHFORM") (eq name 'searchform'))}}
import { {{codeName}}SearchForm } from '@widgets/{{spinalCase psAppDataEntity.codeName}}/{{spinalCase codeName}}-search-form';
{{/if}}
{{#if (and (eq controlType "SEARCHFORM") (eq name 'quicksearchform'))}}
import { {{codeName}}QuickSearchForm } from '@widgets/{{spinalCase psAppDataEntity.codeName}}/{{spinalCase codeName}}-quick-search-form';
{{/if}}
{{#eq controlType "SEARCHBAR"}}
import { {{codeName}}SearchBar } from '@widgets/{{spinalCase psAppDataEntity.codeName}}/{{spinalCase codeName}}-searchBar';
{{/eq}}
{{/page.ctrls}}
// props声明和默认值处理
interface Props {
context?: IContext;
viewParams?: IParam;
openType?: "ROUTE" | "MODAL" | "EMBED";
viewSubject?: Subject<IActionParam>;
}
const props = withDefaults(defineProps<Props>(), {
openType:'ROUTE',
viewSubject: () => new Subject<IActionParam>()
})
// emit声明
interface ViewEmit {
(name: "viewEvent", value: IActionParam): void;
}
const emit = defineEmits<ViewEmit>();
// 安装功能模块,提供状态和能力方法
const listView = new ListView(viewState, props, emit).moduleInstall();
const { state, list, searchForm, quickSearchForm, onCtrlEvent, onToolbarEvent, onQuickGroupEvent, onQuickSearchEvent } = listView;
{{#if page.psAppCounterRefs}}
// 计数器数据
const counterData = computed(() => {
const { counterServices } = toRefs(state);
if (counterServices && counterServices.value && counterServices.value.length) {
return counterServices.value[0].data;
}
return {};
})
{{/if}}
</script>
<template>
<AppListViewLayout :class="['app-list-view', state.viewSysCss]" :showCaptionBar="state.showCaptionBar">
<template v-slot:caption>
<AppIconText class="app-view__caption" size="large" :text="state.viewCaption" />
</template>
{{#if page.enableQuickGroup}}
<template v-slot:quickGroupSearch>
<AppQuickGroup v-if="state.enableQuickGroup" :quickGroupModel="state.quickGroupPSCodeList" @onQuickGroupEvent="onQuickGroupEvent" />
</template>
{{/if}}
{{#page.ctrls}}
{{#eq controlType "TOOLBAR"}}
<template v-slot:toolbar>
<AppToolbar
mode="button"
name="{{lowerCase codeName}}"
:actionModel="state.toolbar"
{{#if page.psAppCounterRefs}}
:counterData="counterData"
{{/if}}
@onToolbarEvent="onToolbarEvent"/>
</template>
{{/eq}}
{{#if (and (eq controlType "SEARCHFORM") (eq name 'searchform'))}}
{{#if page.enableFilter}}
<template v-slot:quickSearch>
<div class='app-quick-search'>
<a-input-search v-if="state.enableQuickSearch" @search="onQuickSearchEvent" allowClear/>
<a-popover v-show="state.expandSearchForm" trigger="click" :overlayStyle="{width: '50%'}" placement="bottom">
<template #content>
<{{codeName}}SearchForm
ref="searchForm"
name="{{name}}"
:context="state.context"
:viewParams="state.viewParams"
:controlAction="state.{{camelCase name}}.action"
:viewSubject="state.viewSubject"
@ctrlEvent="onCtrlEvent"
></{{codeName}}SearchForm>
</template>
<a-button><filter-outlined /></a-button>
</a-popover>
</div>
</template>
{{else}}
<template v-slot:searchForm>
<{{codeName}}SearchForm
v-show="state.expandSearchForm"
ref="searchForm"
name="{{name}}"
:context="state.context"
:viewParams="state.viewParams"
:controlAction="state.{{camelCase name}}.action"
:viewSubject="state.viewSubject"
@ctrlEvent="onCtrlEvent"
></{{codeName}}SearchForm>
</template>
{{/if}}
{{/if}}
{{#if (and (eq controlType "SEARCHFORM") (eq name 'quicksearchform'))}}
<template v-slot:quickSearchForm>
<{{codeName}}QuickSearchForm
ref="quickSearchForm"
name="{{name}}"
:context="state.context"
:viewParams="state.viewParams"
:controlAction="state.{{camelCase name}}.action"
:viewSubject="state.viewSubject"
@ctrlEvent="onCtrlEvent"
></{{codeName}}QuickSearchForm>
</template>
{{/if}}
{{#eq controlType "SEARCHBAR"}}
<template v-slot:searchBar>
<{{codeName}}SearchBar
:controlAction="state.{{camelCase name}}.action"
:viewSubject="state.viewSubject"/>
</template>
{{/eq}}
{{#eq controlType "LIST"}}
<{{codeName}}List
ref="list"
name="{{name}}"
:context="state.context"
:showBusyIndicator="true"
:viewParams="state.viewParams"
:controlAction="state.{{name}}.action"
:viewSubject="state.viewSubject"
:parent="listView"
@ctrlEvent="onCtrlEvent"
></{{codeName}}List>
{{/eq}}
{{/page.ctrls}}
</AppListViewLayout>
</template>
<style lang="scss">
.app-list-view {
height: 100%;
width: 100%;
}
</style>
\ No newline at end of file
import {{ctrl.codeName}}List from "./{{spinalCase ctrl.codeName}}-list.vue";
export { {{ctrl.codeName}}List };
import { ControlVOBase, IParam, ListService, isEmpty, Verify } from '@core';
import { {{pascalCase ctrl.psAppDataEntity.codeName}}Service } from '@api/{{spinalCase
ctrl.psAppDataEntity.codeName}}/{{spinalCase ctrl.psAppDataEntity.codeName}}-service';
export class ControlVO extends ControlVOBase {
}
export const ctrlState = {
controlCodeName: '{{ctrl.codeName}}',
controlName: '{{ctrl.name}}',
appEntityCodeName: '{{ctrl.psAppDataEntity.codeName}}',
appDeCodeName:'{{ctrl.psAppDataEntity.codeName}}',
appDeLogicName: '{{ctrl.psAppDataEntity.logicName}}',
appDeKeyFieldName: '{{#if ctrl.psAppDataEntity.keyPSAppDEField}}{{ctrl.psAppDataEntity.keyPSAppDEField.codeName}}{{/if}}',
appDeMajorFieldName: '{{#if ctrl.psAppDataEntity.majorPSAppDEField}}{{ctrl.psAppDataEntity.majorPSAppDEField.codeName}}{{/if}}',
controlService: new ListService<ControlVO>(ControlVO, new {{pascalCase ctrl.psAppDataEntity.codeName}}Service() ),
// 多数据部件分组
mdCtrlGroup: {
enableGroup: {{ctrl.enableGroup}},
groupMode: "{{ctrl.groupMode}}",
groupField: "{{lowerCase ctrl.groupPSAppDEField.codeName}}",
{{#if ctrl.groupPSCodeList}}
groupCodeList: {
codeListTag: "{{ctrl.groupPSCodeList.codeListTag}}",
codeListType: "{{ctrl.groupPSCodeList.codeListType}}",
},
{{/if}}
},
// 多数据部件排序
mdCtrlSort: {
noSort: {{ctrl.noSort}},
minorSortDir: "{{#if ctrl.minorSortDir}}{{ctrl.minorSortDir}}{{/if}}",
minorSortPSDEF: "{{ctrl.minorSortPSAppDEField.codeName}}",
},
// 多数据部件分页
mdCtrlPaging: {
enablePagingBar: true,
current: 1,
pageSize: {{#if ctrl.pagingSize}}{{ctrl.pagingSize}}{{else}}20{{/if}}
},
}
\ No newline at end of file
<script setup lang="ts">
import { Subject } from 'rxjs';
import { ctrlState } from './{{spinalCase ctrl.codeName}}-list-state';
import { ListControl, IActionParam, IParam, IContext, ControlAction, deepCopy } from '@core';
{{#if ctrl.batchToolBarItems}}
import AppToolbar from '@components/common/app-toolbar.vue';
{{/if}}
interface Props {
name:string,
parent: IParam;
context: IContext;
viewParams: IParam;
multiple?: boolean;
selectedData?: IParam[];
selectFirstDefault?: boolean;
controlAction: ControlAction;
showBusyIndicator?: boolean;
viewSubject: Subject<IActionParam>;
}
const props = withDefaults(defineProps < Props > (), {
viewSubject: () => new Subject < IActionParam > (),
showBusyIndicator: true,
multiple: false,
selectFirstDefault: false,
})
// emit声明
interface CtrlEmit {
(name: "ctrlEvent", value: IActionParam): void;
}
// emit声明
const emit = defineEmits<CtrlEmit>();
// 安装功能模块,提供状态和能力
const { name, state, useCustom, onEditorEvent, onToolbarEvent, onActionColEvent, newRow, remove, save, load, refresh, getData, exportExcel } = new ListControl(ctrlState, props, emit).moduleInstall();
// 暴露内部状态及能力
defineExpose({ name, state, newRow, remove, save, load, refresh, getData, exportExcel });
</script>
<template>
<a-list
item-layout="horizontal"
:data-source="state.items">
<template #renderItem="{ item }">
<a-list-item>
<template #title>
2321
</template>
</a-list-item>
</template>
</a-list>
</template>
<style lang="scss">
.app-list {
}
</style>
\ No newline at end of file
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册