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

update:更新表单保存逻辑

上级 24440741
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
{{/if}} {{/if}}
paramItem="{{#if item.paramItem}}{{item.paramItem}}{{else}}srfkey{{/if}}" paramItem="{{#if item.paramItem}}{{item.paramItem}}{{else}}srfkey{{/if}}"
deCodeName="{{lowerCase ctrl.appEntity.codeName}}" deCodeName="{{lowerCase ctrl.appEntity.codeName}}"
{{#if item.refreshItems}}
refreshItems="{{item.refreshItems}}"
{{/if}}
:context="context" :context="context"
:viewParams="viewParams" :viewParams="viewParams"
{{#if item.psNavigateContexts}} {{#if item.psNavigateContexts}}
......
<script setup lang="ts"> <script setup lang="ts">
import { deepCopy, IActionParam, ILayoutOpts, IParam, RouteUtil, UIUtil } from '@core'; import { deepCopy, IActionParam, ILayoutOpts, IParam, isExistAndNotEmpty, RouteUtil, UIUtil } from '@core';
import { context } from 'ant-design-vue/lib/vc-image/src/PreviewGroup';
import { Subject, Subscription } from 'rxjs'; import { Subject, Subscription } from 'rxjs';
import { Ref } from 'vue'; import { Ref } from 'vue';
interface FormDruipartProps { interface FormDruipartProps {
...@@ -36,8 +35,6 @@ interface FormDruipartProps { ...@@ -36,8 +35,6 @@ interface FormDruipartProps {
formSubject: Subject<any>; formSubject: Subject<any>;
// 视图路由参数 // 视图路由参数
parameters: any[]; parameters: any[];
// 是否忽略表单项值变化
ignoreFieldValueChange?: boolean;
// 是否显示 // 是否显示
visible?: boolean; visible?: boolean;
// 关系视图标识 // 关系视图标识
...@@ -68,17 +65,28 @@ let druipartContext: Ref<any> = ref({}); ...@@ -68,17 +65,28 @@ let druipartContext: Ref<any> = ref({});
// 关秀界面视图参数 // 关秀界面视图参数
let druipartViewParams: Ref<any> = ref({}); let druipartViewParams: Ref<any> = ref({});
// 是否是刷新状态
let isRefreshStatus: boolean = false;
onBeforeMount(() => { onBeforeMount(() => {
watch( watch(
() => props.data, () => props.data,
(newVal: any, oldVal: any) => { (newVal: any, oldVal: any) => {
if (props.ignoreFieldValueChange) {
return;
}
if (Object.is(newVal, oldVal)) { if (Object.is(newVal, oldVal)) {
return; return;
} }
refreshDRUIPart(); let refreshFlag: boolean = false;
// 存在刷新项时刷新
if (isExistAndNotEmpty(props.refreshItems)) {
props.refreshItems?.split(';').some((item: string) => {
if (!Object.is(newVal[item], oldVal[item])) {
refreshFlag = true;
}
})
}
if (refreshFlag && !isRefreshStatus) {
refreshDRUIPart();
}
}, },
); );
druipartInit(); druipartInit();
...@@ -92,16 +100,17 @@ const druipartInit = () => { ...@@ -92,16 +100,17 @@ const druipartInit = () => {
// 视图事件 // 视图事件
}); });
// formSubjectEvent = props.formSubject.subscribe(({ type, data }) => { formSubjectEvent = props.formSubject.subscribe(({ type, data }) => {
// // 表单加载完成 // 表单加载完成
// if (type && Object.is(type, 'load')) { if (type && Object.is(type, 'load')) {
// refreshDRUIPart(data); refreshDRUIPart(data);
// } }
// }) })
}; };
// 刷新关系界面 // 刷新关系界面
const refreshDRUIPart = (data?: any) => { const refreshDRUIPart = (data?: any) => {
isRefreshStatus = true;
const formData: any = data ? data : props.data; const formData: any = data ? data : props.data;
const paramItem = formData[props.paramItem]; const paramItem = formData[props.paramItem];
// 应用上下文 // 应用上下文
...@@ -147,11 +156,12 @@ const refreshDRUIPart = (data?: any) => { ...@@ -147,11 +156,12 @@ const refreshDRUIPart = (data?: any) => {
Object.assign(druipartContext.value, tempContext); Object.assign(druipartContext.value, tempContext);
Object.assign(druipartViewParams.value, tempParams); Object.assign(druipartViewParams.value, tempParams);
nextTick(() => { nextTick(() => {
isRefreshStatus = false;
// 设置局部上下文 // 设置局部上下文
if (props.viewSubject) { if (props.viewSubject) {
props.viewSubject.next({ tag: props.viewCodeName, action: 'viewRefresh', data: [] }); props.viewSubject.next({ tag: props.viewCodeName, action: 'viewRefresh', data: [] });
} }
}) });
}; };
const viewEvent = (action:any) => { const viewEvent = (action:any) => {
...@@ -163,7 +173,7 @@ const viewEvent = (action:any) => { ...@@ -163,7 +173,7 @@ const viewEvent = (action:any) => {
<AppCol noRoot :visible="visible" :layoutOpts="layoutOpts" :class="['app-form-druipart', `app-form-druipart-${name}`]"> <AppCol noRoot :visible="visible" :layoutOpts="layoutOpts" :class="['app-form-druipart', `app-form-druipart-${name}`]">
<template #default="{slotStyle, slotClass}"> <template #default="{slotStyle, slotClass}">
<a-card :class="slotClass" :style="slotStyle" :bordered="false"> <a-card :class="slotClass" :style="slotStyle" :bordered="false">
<template #title> <template v-if="title" #title>
<p :class="['app-form-druipart-title']"> <p :class="['app-form-druipart-title']">
<AppIconText :text="title" /> <AppIconText :text="title" />
</p> </p>
......
...@@ -37,6 +37,13 @@ export interface FormControlState extends MainControlState { ...@@ -37,6 +37,13 @@ export interface FormControlState extends MainControlState {
*/ */
detailsModel: IParam; detailsModel: IParam;
/**
* @description 错误信息
* @type {string[]}
* @memberof FormControlState
*/
errorMessage: string[];
/** /**
* @description 表单通讯对象 * @description 表单通讯对象
* @type {Subject<any>} * @type {Subject<any>}
......
...@@ -5,6 +5,7 @@ import { ...@@ -5,6 +5,7 @@ import {
deepCopy, deepCopy,
FormControlProps, FormControlProps,
FormControlState, FormControlState,
hasFunction,
IActionParam, IActionParam,
IParam, IParam,
MainControl, MainControl,
...@@ -536,28 +537,30 @@ export class FormControl extends MainControl { ...@@ -536,28 +537,30 @@ export class FormControl extends MainControl {
const save = async (opt: any = {}) => { const save = async (opt: any = {}) => {
try { try {
// 获取需要的状态变量 // 获取需要的状态变量
const { controlService, context, viewParams, showBusyIndicator, data } = this.state; const { controlService, context, viewParams, showBusyIndicator, data, formSubject } = this.state;
if (!(await this.formValidateStatus())) {
// TODO 值规则校验处理 this.showErrorMessage();
// 判断实体行为
const { updateAction, createAction } = this.state.controlAction;
const saveAction: any = data.srfuf == '1' ? updateAction : createAction;
const saveFunName = data.srfuf == '1' ? 'update' : 'create';
if (!saveAction) {
return; return;
} }
// 处理请求参数 // 处理请求参数
let _context = deepCopy(context); let _context = deepCopy(context);
let _viewParams = deepCopy(viewParams); let _viewParams = deepCopy(viewParams);
const arg: any = { ...opt }; const arg: any = { ...opt };
Object.assign(arg, data.getDo()); Object.assign(arg, data.getDo());
Object.assign(arg, _viewParams); Object.assign(arg, _viewParams);
// 拷贝模式
if (_viewParams && _viewParams.copyMode) {
data.srfuf = '0';
}
// TODO 关系界面保存通知处理,做成异步。 // TODO 关系界面保存通知处理,做成异步。
// TODO 拷贝相关。 // 判断实体行为
const { updateAction, createAction } = this.state.controlAction;
const saveAction: any = data.srfuf == '1' ? updateAction : createAction;
const saveFunName = data.srfuf == '1' ? 'update' : 'create';
if (!saveAction) {
App.getNotificationService().warning({ message: '', description: '未配置SaveAction' });
return;
}
// 发起请求处理与解析请求 // 发起请求处理与解析请求
const response = await controlService[saveFunName](_context, arg, { const response = await controlService[saveFunName](_context, arg, {
action: saveAction, action: saveAction,
...@@ -567,14 +570,19 @@ export class FormControl extends MainControl { ...@@ -567,14 +570,19 @@ export class FormControl extends MainControl {
// TODO 统一Error格式 // TODO 统一Error格式
return; return;
} }
// TODO 取消拷贝模式
const { data: _data } = toRefs(this.state);
// 请求后处理 // 请求后处理
this.state.data = response.data; _data.value = response.data;
this.emit('ctrlEvent', { tag: this.props.name, action: 'save', data: [response.data] });
// TODO 表单onFormLoad this.afterFormAction('save');
} catch (error) { nextTick(() => {
formSubject.next({ type: 'save', data: _data.value });
})
} catch (error: any) {
App.getNotificationService().error({ message: '保存失败', description: error?.message || '' });
// TODO 错误异常处理 // TODO 错误异常处理
console.log(error);
} }
}; };
...@@ -800,6 +808,53 @@ export class FormControl extends MainControl { ...@@ -800,6 +808,53 @@ export class FormControl extends MainControl {
App.getAppActionService().execute(data, inputParam); App.getAppActionService().execute(data, inputParam);
} }
/**
* @description 表单值规则校验状态
* @private
* @return {*} {Promise<boolean>}
* @memberof FormControl
*/
private async formValidateStatus(): Promise<boolean> {
const form = this.getXDataCtrl()?.value;
let result: boolean = true;
if (form && hasFunction(form, 'validate')) {
try {
await form.validate();
} catch (error: any) {
result = false;
if (error.errorFields && error.errorFields.length) {
const { detailsModel } = this.state;
this.state.errorMessage = [];
error.errorFields.forEach((field: IParam) => {
const caption = detailsModel[field.name[0]]?.caption;
this.state.errorMessage.push(`${caption}: ${field.errors?.join('、')}`);
});
}
}
}
return result;
}
/**
* @description 展示错误信息
* @private
* @memberof FormControl
*/
private showErrorMessage() {
const errorMessage = this.state.errorMessage;
if (errorMessage && errorMessage.length) {
const getMessage = () => {
const messages: any[] = [];
errorMessage.forEach((message: string) => {
messages.push(h('span', {}, message));
});
return messages;
}
const content = h('div', { class: 'error-messages', style: { 'display': 'flex', 'flex-direction': 'column' } }, getMessage());
App.getNotificationService().error({ message: '值规则错误', description: content });
}
}
/** /**
* @description 安装部件所有功能模块的方法 * @description 安装部件所有功能模块的方法
* @return {*} * @return {*}
......
import { ControlBase, IParam, MainControlProps, MainControlState, UIUtil } from '@core'; import { ControlBase, IParam, MainControlState } from '@core';
/** /**
* @description 实体部件 * @description 实体部件
...@@ -15,6 +15,14 @@ export class MainControl extends ControlBase { ...@@ -15,6 +15,14 @@ export class MainControl extends ControlBase {
*/ */
public declare state: MainControlState; public declare state: MainControlState;
/**
* @description 数据部件组件
* @private
* @type {IParam}
* @memberof MainControl
*/
private declare xData: IParam;
/** /**
* 界面行为服务 * 界面行为服务
* *
...@@ -47,6 +55,27 @@ export class MainControl extends ControlBase { ...@@ -47,6 +55,27 @@ export class MainControl extends ControlBase {
} }
} }
/**
* @description 使用设置数据部件模块
* @private
* @return {*}
* @memberof MainControl
*/
private useSetXDataCtrl() {
const xData = ref(null);
this.xData = xData;
return xData;
}
/**
* @description 获取数据部件
* @return {*}
* @memberof MainControl
*/
public getXDataCtrl() {
return this.xData;
}
/** /**
* @description 安装部件所有功能模块的方法 * @description 安装部件所有功能模块的方法
* @return {*} * @return {*}
...@@ -57,7 +86,8 @@ export class MainControl extends ControlBase { ...@@ -57,7 +86,8 @@ export class MainControl extends ControlBase {
// 使用UI服务 // 使用UI服务
this.useUIService(); this.useUIService();
return { return {
...superParams ...superParams,
xDataCtrl: this.useSetXDataCtrl()
}; };
} }
} }
...@@ -69,7 +69,7 @@ const { state, grid, searchForm, quickSearchForm, onCtrlEvent, onToolbarEvent, o ...@@ -69,7 +69,7 @@ const { state, grid, searchForm, quickSearchForm, onCtrlEvent, onToolbarEvent, o
<template v-slot:quickSearch> <template v-slot:quickSearch>
<div class='app-quick-search'> <div class='app-quick-search'>
<a-input-search v-if="state.enableQuickSearch" @search="onQuickSearchEvent" allowClear/> <a-input-search v-if="state.enableQuickSearch" @search="onQuickSearchEvent" allowClear/>
<a-popover v-if="state.expandSearchForm" trigger="click" :overlayStyle="{width: '50%'}" placement="bottom"> <a-popover v-show="state.expandSearchForm" trigger="click" :overlayStyle="{width: '50%'}" placement="bottom">
<template #content> <template #content>
<{{codeName}}SearchForm <{{codeName}}SearchForm
ref="searchForm" ref="searchForm"
...@@ -88,15 +88,15 @@ const { state, grid, searchForm, quickSearchForm, onCtrlEvent, onToolbarEvent, o ...@@ -88,15 +88,15 @@ const { state, grid, searchForm, quickSearchForm, onCtrlEvent, onToolbarEvent, o
{{else}} {{else}}
<template v-slot:searchForm> <template v-slot:searchForm>
<{{codeName}}SearchForm <{{codeName}}SearchForm
v-if="state.expandSearchForm" v-show="state.expandSearchForm"
ref="searchForm" ref="searchForm"
name="{{name}}" name="{{name}}"
:context="state.context" :context="state.context"
:viewParams="state.viewParams" :viewParams="state.viewParams"
:controlAction="state.{{camelCase name}}.action" :controlAction="state.{{camelCase name}}.action"
:viewSubject="state.viewSubject" :viewSubject="state.viewSubject"
@ctrlEvent="onCtrlEvent" @ctrlEvent="onCtrlEvent"
></{{codeName}}SearchForm> ></{{codeName}}SearchForm>
</template> </template>
{{/if}} {{/if}}
{{/if}} {{/if}}
......
...@@ -57,6 +57,7 @@ export const ctrlState = { ...@@ -57,6 +57,7 @@ export const ctrlState = {
appDeKeyFieldName: '{{#if ctrl.appEntity.keyPSAppDEField}}{{ctrl.appEntity.keyPSAppDEField.codeName}}{{/if}}', appDeKeyFieldName: '{{#if ctrl.appEntity.keyPSAppDEField}}{{ctrl.appEntity.keyPSAppDEField.codeName}}{{/if}}',
appDeMajorFieldName: '{{#if ctrl.appEntity.majorPSAppDEField}}{{ctrl.appEntity.majorPSAppDEField.codeName}}{{/if}}', appDeMajorFieldName: '{{#if ctrl.appEntity.majorPSAppDEField}}{{ctrl.appEntity.majorPSAppDEField.codeName}}{{/if}}',
enableAutoSave: {{ctrl.enableAutoSave}}, enableAutoSave: {{ctrl.enableAutoSave}},
errorMessage: [],
// 新建默认值 // 新建默认值
createDefaultItems: [ createDefaultItems: [
{{#each ctrl.psDEFormItems as | formItem |}} {{#each ctrl.psDEFormItems as | formItem |}}
......
...@@ -40,13 +40,20 @@ interface CtrlEmit { ...@@ -40,13 +40,20 @@ interface CtrlEmit {
const emit = defineEmits <CtrlEmit> (); const emit = defineEmits <CtrlEmit> ();
// 安装功能模块,提供状态和能力方法 // 安装功能模块,提供状态和能力方法
const { name, state, load, loadDraft, save, remove, refresh, onEditorEvent, onComponentEvent, getData } = new FormControl(ctrlState, props, emit).moduleInstall(); const { name, state, load, loadDraft, save, remove, refresh, onEditorEvent, onComponentEvent, getData, xDataCtrl } = new FormControl(ctrlState, props, emit).moduleInstall();
// 暴露内部状态及能力 // 暴露内部状态及能力
defineExpose({ name, state, load, loadDraft, save, remove, refresh, getData }); defineExpose({ name, state, load, loadDraft, save, remove, refresh, getData });
</script> </script>
<template> <template>
<a-form name="{{ctrl.codeName}}" class="app-form{{#if ctrl.psSysCss}} {{ctrl.psSysCss.cssName}}{{/if}}{{#if ctrl.infoFormMode}} app-info-form{{/if}}" style="{{#if ctrl.formWidth}}width: {{ctrl.formWidth}}px;{{/if}}" :model="state.data" :rules="state.rules"> <a-form
name="{{ctrl.codeName}}"
class="app-form{{#if ctrl.psSysCss}} {{ctrl.psSysCss.cssName}}{{/if}}{{#if ctrl.infoFormMode}} app-info-form{{/if}}"
style="{{#if ctrl.formWidth}}width: {{ctrl.formWidth}}px;{{/if}}"
:model="state.data"
:rules="state.rules"
ref="xDataCtrl"
>
{{#if ctrl.noTabHeader}} {{#if ctrl.noTabHeader}}
{{#each ctrl.psDEFormPages as | ctrlPage | }} {{#each ctrl.psDEFormPages as | ctrlPage | }}
{{#each ctrlPage.psDEFormDetails as | formDetail | }} {{#each ctrlPage.psDEFormDetails as | formDetail | }}
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册