提交 ec40d9e1 编写于 作者: ibizdev's avatar ibizdev

lxm1993 发布系统代码 [TrainSys,网页端]

上级 47491de7
......@@ -11,14 +11,15 @@
"lint:style": "stylelint 'src/**/*.scss'"
},
"dependencies": {
"@ibiz-template/command": "^0.0.1-alpha.41",
"@ibiz-template/controller": "^0.0.1-alpha.41",
"@ibiz-template/core": "^0.0.1-alpha.41",
"@ibiz-template/model": "^0.0.1-alpha.41",
"@ibiz-template/runtime": "^0.0.1-alpha.41",
"@ibiz-template/service": "^0.0.1-alpha.41",
"@ibiz-template/theme": "^0.0.1-alpha.41",
"@ibiz-template/vue-util": "^0.0.1-alpha.41",
"@floating-ui/dom": "^1.0.4",
"@ibiz-template/command": "^0.0.1-alpha.43",
"@ibiz-template/controller": "^0.0.1-alpha.43",
"@ibiz-template/core": "^0.0.1-alpha.43",
"@ibiz-template/model": "^0.0.1-alpha.43",
"@ibiz-template/runtime": "^0.0.1-alpha.43",
"@ibiz-template/service": "^0.0.1-alpha.43",
"@ibiz-template/theme": "^0.0.1-alpha.43",
"@ibiz-template/vue-util": "^0.0.1-alpha.43",
"@ibiz/dynamic-model-api": "^2.1.5",
"dayjs": "^1.11.6",
"lodash-es": "^4.17.21",
......@@ -38,36 +39,36 @@
"@types/node": "^18.11.9",
"@types/path-browserify": "^1.0.0",
"@types/qs": "^6.9.7",
"@types/ramda": "^0.28.18",
"@types/ramda": "^0.28.19",
"@types/systemjs": "^6.1.1",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"@vitejs/plugin-legacy": "^2.3.0",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@vitejs/plugin-legacy": "^2.3.1",
"@vitejs/plugin-vue2": "^2.0.0",
"@vitejs/plugin-vue2-jsx": "^1.0.3",
"@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
"eslint": "^8.26.0",
"eslint": "^8.27.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.7.0",
"husky": "^8.0.1",
"husky": "^8.0.2",
"lint-staged": "^13.0.3",
"postcss": "^8.4.18",
"postcss-scss": "^4.0.5",
"prettier": "^2.7.1",
"rollup-plugin-visualizer": "^5.8.3",
"sass": "^1.55.0",
"stylelint": "^14.14.0",
"sass": "^1.56.0",
"stylelint": "^14.14.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recess-order": "^3.0.0",
"stylelint-config-standard": "^29.0.0",
"stylelint-config-standard-scss": "^6.0.0",
"stylelint-config-standard-scss": "^6.1.0",
"stylelint-scss": "^4.3.0",
"terser": "^5.15.1",
"typescript": "^4.8.4",
"vite": "^3.2.2",
"vite": "^3.2.3",
"vite-plugin-eslint": "^1.8.1",
"vue-eslint-parser": "^9.1.0",
"vue-tsc": "^1.0.9"
......
此差异已折叠。
<?xml version="1.0" encoding="UTF-8"?>
<svg width="41px" height="46px" viewBox="0 0 41 46" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>导入</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="列表-导入数据" transform="translate(-662.000000, -314.000000)" fill="#57A3FD" fill-rule="nonzero">
<g id="编组-20" transform="translate(411.000000, 200.000000)">
<g id="导入" transform="translate(251.000000, 114.000000)">
<path d="M28.0376544,3.76410323 L29.7766688,6.44368556 L13.239007,15.644894 L11.4999926,12.9647074 L28.0376544,3.76410323 Z M9.11219211,14.7380049 L12.3001824,14.7380049 L12.3001824,22.3302555 L9.11158406,20.5436659 L9.11219211,14.7380049 Z" id="形状"></path>
<path d="M0.00060804817,8.56257961 L21.8671937,19.2041768 L21.8671937,46 L0.00060804817,35.2816707 L0.00060804817,8.56257961 Z M2.27835205,12.0982991 L2.27835205,33.9010967 L19.5894497,42.3869442 L19.5894497,20.5841466 L2.277744,12.0982991 L2.27835205,12.0982991 Z" id="形状"></path>
<path d="M20.163446,0 L41,9.44953043 L21.7066692,19.2041768 L0,8.56257961 L20.163446,0 Z M20.1330436,2.44576083 L5.38912041,8.70758522 L21.69086,16.6992054 L35.8151834,9.55768043 L20.1336517,2.44636502 L20.1330436,2.44576083 Z" id="形状"></path>
<polygon id="路径" points="20.8207448 18.8332042 41 9.37884022 41 36.1746635 21.8671937 46"></polygon>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -74,6 +74,8 @@ import {
ExtendActionTimeLine,
ExtendActionGrid,
AppSelectTree,
DataImport,
DataExport,
} from './components/common';
// 编辑器组件
import {
......@@ -175,6 +177,8 @@ export const AppRegister = {
v.component('ExtendActionTimeLine', ExtendActionTimeLine);
v.component('ExtendActionGrid', ExtendActionGrid);
v.component('AppSelectTree', AppSelectTree);
v.component('DataImport', DataImport);
v.component('DataExport', DataExport);
// 注册编辑器组件
v.component('IBizSpan', IBizSpan);
v.component('IBizInput', IBizInput);
......
......@@ -37,26 +37,23 @@ export const ActionToolbar = defineComponent({
details.map(detail => {
const action = detail.getPSUIAction();
if (action && this.actionsState[detail.name].visible) {
return (
return [
detail.addSeparator && (
<div class={this.ns.e('separator')}></div>
),
<i-button
type='text'
size='small'
on-click={(e: MouseEvent) => this.handleClick(detail, e)}
disabled={this.actionsState[detail.name].disabled}
class={[
this.ns.e('item'),
detail.addSeparator
? this.ns.em('item', 'separated')
: undefined,
this.ns.is('disabled', false),
]}
class={[this.ns.e('item'), this.ns.is('disabled', false)]}
>
{detail.showIcon && action.getPSSysImage() && (
<app-icon icon={action.getPSSysImage()}></app-icon>
)}
{detail.showCaption ? action!.caption : ''}
</i-button>
);
</i-button>,
];
}
return null;
})}
......
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent, PropType, ref } from 'vue';
import '@ibiz-template/theme/style/components/common/data-export/data-export.scss';
export const DataExport = defineComponent({
name: 'DataExport',
props: {
dismiss: {
type: Function as PropType<(_result: IParams) => void>,
required: true,
},
maxRowCount: {
type: Number,
required: true,
},
pageSize: {
type: Number,
required: true,
},
},
setup(props) {
const ns = useNamespace('data-export');
const startPage = ref(1);
const endPage = ref(1);
const customExport = () => {
console.log(startPage.value);
console.log(endPage.value);
props.dismiss({
page: 0,
offset: (startPage.value - 1) * props.pageSize,
size: (endPage.value - startPage.value + 1) * props.pageSize,
});
};
const exportAll = () => {
props.dismiss({ page: 0, size: props.maxRowCount });
};
const exportCurrent = () => {
props.dismiss({});
};
return {
ns,
startPage,
endPage,
customExport,
exportAll,
exportCurrent,
};
},
render() {
return (
<div class={this.ns.b()}>
<i-button
class={this.ns.e('text-button')}
type='text'
onClick={this.exportAll}
>
导出全部(最大导出{this.maxRowCount}行)
</i-button>
<i-button
class={this.ns.e('text-button')}
type='text'
onClick={this.exportCurrent}
>
导出当前页
</i-button>
<div class={this.ns.e('custom-bar')}>
<i-input-number
class={this.ns.e('input-number')}
min={1}
v-model={this.startPage}
/>
<span class={this.ns.e('delimiter')}>~</span>
<i-input-number
class={this.ns.e('input-number')}
min={1}
v-model={this.endPage}
/>
<span class={this.ns.e('delimiter')}></span>
<i-button
type='primary'
disabled={!this.startPage || !this.endPage}
onClick={this.customExport}
>
导出
</i-button>
</div>
</div>
);
},
});
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent, ref } from 'vue';
import '@ibiz-template/theme/style/components/common/data-import/data-import.scss';
import { HttpError } from '@ibiz-template/core';
export const DataImport = defineComponent({
name: 'DataImport',
props: {
templateUrl: {
type: String,
required: true,
},
importUrl: {
type: String,
required: true,
},
},
setup(props, { emit }) {
const ns = useNamespace('data-import');
const inputUpLoad = ref();
const message = ref<{
state: 'ready' | 'success' | 'fail';
message: string;
rowError: Array<{ index: number; info: string }>;
}>({
state: 'ready',
message: '',
rowError: [],
});
// 上传数据
const uploadFile = async (file: Blob) => {
const data = new FormData();
data.append('file', file);
try {
const res = await ibiz.net.request(props.importUrl, {
method: 'post',
data,
headers: { 'Content-Type': 'multipart/form-data' },
});
message.value.state = 'success';
message.value.message = '导入成功';
const { errorinfo, success, total } = res.data;
const totalNum = total ? Number(total) : 0;
const successNum = success ? Number(success) : 0;
const errorNum = total - success;
message.value.message = `共计导入数据 ${totalNum} 条,错误[${errorNum}],成功[${successNum}]`;
if (errorinfo && Object.keys(errorinfo).length > 0) {
message.value.rowError = [];
Object.keys(errorinfo).forEach((key: string) => {
message.value.rowError.push({
index: Number(key) + 1,
info: errorinfo[key].errorInfo,
});
});
}
} catch (error) {
message.value.state = 'fail';
message.value.message = `导入失败!${(error as HttpError).message}`;
}
};
// 文件选择变更事件
const onFileChange = ($event: Event) => {
const obj = $event.target as IData;
if (!obj.files) {
return;
}
const selectedFile = obj.files[0];
obj.value = null; // 置空不然下次文件不变不触发
uploadFile(selectedFile);
};
// 下载模板文件
const onLinkClick = async () => {
const res = await ibiz.net.request(props.templateUrl, {
responseType: 'blob',
});
if (res.status === 200) {
let fileName =
res.headers['content-disposition']!.split(';')
.find((str: string) => str.indexOf('filename=') !== -1)
?.slice(9) || '';
fileName = decodeURIComponent(fileName);
const blob = new Blob([res.data as Blob], {
type: 'application/vnd.ms-excel',
});
const elink = document.createElement('a');
elink.download = fileName;
elink.style.display = 'none';
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
}
};
const selectFile = () => {
inputUpLoad.value.click();
};
const onCancelButtonClick = () => {
emit('close', { ok: false, data: {} });
};
return {
ns,
onLinkClick,
selectFile,
onCancelButtonClick,
onFileChange,
inputUpLoad,
message,
};
},
render() {
return (
<div class={this.ns.b()}>
<input
ref='inputUpLoad'
type='file'
style='display: none'
accept='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
onChange={this.onFileChange}
/>
<div class={this.ns.e('caption')}>导入数据</div>
{this.message.state === 'ready' ? (
<div class={this.ns.b('upload')} onClick={this.selectFile}>
<img
class={this.ns.be('upload', 'img')}
src='./assets/img/icon-import.svg'
></img>
<span class={this.ns.be('upload', 'text')}>单击此区域进行上传</span>
</div>
) : (
<div class={this.ns.b('message')}>
<div class={this.ns.be('message', 'title')}>导入结果</div>
<div class={this.ns.be('message', 'content')}>
{this.message.message}
</div>
{this.message.rowError.length > 0 && [
<div class={this.ns.be('message', 'title')}>错误信息</div>,
<div class={this.ns.be('message', 'content')}>
{this.message.rowError.map(item => {
return <div>{`第 ${item.index} 行:${item.info}`}</div>;
})}
</div>,
]}
</div>
)}
<div class={this.ns.e('template-container')}>
<div class={this.ns.e('template-description')}>
下载导入模版,并按要求填写:
</div>
<div class={this.ns.e('template-link')} onClick={this.onLinkClick}>
<i-icon type='ios-link' />
数据导入模板文件
</div>
</div>
<div class={this.ns.e('button-bar')}>
<i-button onClick={this.onCancelButtonClick}>取消</i-button>
{this.message.state !== 'ready' && (
<i-button onClick={this.selectFile}>重新上传</i-button>
)}
</div>
</div>
);
},
});
......@@ -13,6 +13,8 @@ import { WfVersionSelect } from './wf-version-select/wf-version-select';
import { ExtendActionTimeLine } from './extend-action-timeline/extend-action-timeline';
import { ExtendActionGrid } from './extend-action-grid/extend-action-grid';
export { DataImport } from './data-import/data-import';
export { DataExport } from './data-export/data-export';
export { AppSelectTree } from '../common/app-select-tree/app-select-tree';
export {
AppIcon,
......
......@@ -23,10 +23,10 @@ export const WfVersionSelect = defineComponent({
const curValue: Ref<string | number> = ref('');
const onOkButtonClick = () => {
emit('closeSelect', { ok: true, data: curValue.value });
emit('close', { ok: true, data: [curValue.value] });
};
const onCancelButtonClick = () => {
emit('closeSelect');
emit('close', { ok: false, data: [] });
};
return { ns, curValue, items, onOkButtonClick, onCancelButtonClick };
......
......@@ -57,7 +57,28 @@ export const IBizDatePicker = defineComponent({
const handleChange = (date: string, _dateType: IData) => {
emit('change', date);
};
return { ns, c, editorModel, type, format, formatValue, handleChange };
const inputRef = ref();
if (props.autoFocus) {
watch(inputRef, newVal => {
if (newVal) {
const input = newVal.$el.getElementsByTagName('input')[0];
input.click();
}
});
}
return {
ns,
c,
editorModel,
type,
format,
formatValue,
handleChange,
inputRef,
};
},
render() {
return (
......@@ -66,6 +87,7 @@ export const IBizDatePicker = defineComponent({
this.formatValue
) : (
<i-CalendarPicker
ref='inputRef'
type={this.type}
format={this.format}
placeholder={this.c!.placeHolder}
......
......@@ -35,6 +35,7 @@ export const IBizGridDatePicker = defineComponent({
props: {
...this.$props,
infoMode: this.isInfoMode,
autoFocus: true,
},
on: {
change: this.onChange,
......
import { ref, Ref, defineComponent, computed } from 'vue';
import { ref, Ref, defineComponent, computed, watch } from 'vue';
import {
getDropdownProps,
getEditorEmits,
......@@ -59,7 +59,17 @@ export const IBizDropdown = defineComponent({
.join(',');
});
return { ns, c, curValue, items, valueText, hasChildren };
const inputRef = ref();
if (props.autoFocus) {
watch(inputRef, newVal => {
if (newVal) {
newVal.toggleMenu();
}
});
}
return { ns, c, curValue, items, valueText, hasChildren, inputRef };
},
render() {
......@@ -73,6 +83,7 @@ export const IBizDropdown = defineComponent({
></app-select-tree>
) : (
<i-select
ref='inputRef'
v-model={this.curValue}
allow-clear
clearable
......
......@@ -35,6 +35,7 @@ export const IBizGridDropdown = defineComponent({
props: {
...this.$props,
infoMode: this.isInfoMode,
autoFocus: true,
},
on: {
change: this.onChange,
......
......@@ -35,6 +35,7 @@ export const IBizGridInputNumber = defineComponent({
props: {
...this.$props,
infoMode: this.isInfoMode,
autoFocus: true,
},
on: {
change: this.onChange,
......
......@@ -35,6 +35,7 @@ export const IBizGridInput = defineComponent({
props: {
...this.$props,
infoMode: this.isInfoMode,
autoFocus: true,
},
on: {
change: this.onChange,
......
......@@ -30,17 +30,30 @@ export const IBizInputNumber = defineComponent({
emit('change', e);
};
const inputRef = ref();
if (props.autoFocus) {
watch(inputRef, newVal => {
if (newVal) {
const input = newVal.$el.getElementsByTagName('input')[0];
input.focus();
}
});
}
return {
ns,
c,
currentVal,
handleChange,
inputRef,
};
},
render() {
return (
<div class={this.ns.b()}>
<i-input-number
ref='inputRef'
value={this.currentVal}
placeholder={this.c.placeHolder}
readonly={this.c.model.readOnly}
......
......@@ -58,12 +58,24 @@ export const IBizInput = defineComponent({
emit('change', e.target.value);
}, 500);
const inputRef = ref();
if (props.autoFocus) {
watch(inputRef, newVal => {
if (newVal) {
const input = newVal.$el.getElementsByTagName('input')[0];
input.focus();
}
});
}
return {
ns,
rows,
type,
currentVal,
handleChange,
inputRef,
};
},
render() {
......@@ -78,6 +90,7 @@ export const IBizInput = defineComponent({
this.currentVal
) : (
<i-input
ref='inputRef'
value={this.currentVal}
placeholder={this.controller.placeHolder}
readonly={this.controller.model.readOnly}
......
......@@ -2,7 +2,7 @@ import {
GridEditItemController,
GridRowController,
} from '@ibiz-template/controller';
import { defineComponent, getCurrentInstance } from 'vue';
import { computed, defineComponent, getCurrentInstance } from 'vue';
import '@ibiz-template/theme/style/components/widgets/grid/grid-edit-item.scss';
import { useForce, useNamespace } from '@ibiz-template/vue-util';
......@@ -37,7 +37,23 @@ export const GridEditItem = defineComponent({
e.stopPropagation();
};
return { ns, rowDataChange, rowSave, onStopPropagation };
const alignStyle = computed(() => {
let justContent = '';
switch (props.controller.model.align) {
case 'LEFT':
justContent = 'flex-start';
break;
case 'RIGHT':
justContent = 'flex-end';
break;
default:
justContent = 'center';
break;
}
return ns.cssVarBlock({ 'justify-content': justContent });
});
return { ns, alignStyle, rowDataChange, rowSave, onStopPropagation };
},
render(h) {
const codeName = this.controller.model.codeName;
......@@ -47,6 +63,7 @@ export const GridEditItem = defineComponent({
error={this.row.errors[codeName]}
nativeondblclick={this.onStopPropagation}
nativeonClick={this.onStopPropagation}
style={this.alignStyle}
>
{this.controller.editorProvider &&
h(this.controller.editorProvider.gridEditor, {
......
import {
formatToCodeListText,
GridFieldColumnController,
GridRowController,
} from '@ibiz-template/controller';
......@@ -21,12 +22,16 @@ export const GridFieldColumn = defineComponent({
setup(props) {
const ns = useNamespace('grid-field-column');
const codeListText = computed(() => {
if (props.controller.codeListItems?.length) {
const value = props.row.data[props.controller.model.codeName];
const findItem = props.controller.codeListItems.find(
item => item.value === value,
// 非前台处理,不做值转换
if (props.controller.model.source.cLConvertMode !== 'FRONT') {
return null;
}
const fieldValue = props.row.data[props.controller.model.codeName];
if (props.controller.codeListItems?.length && fieldValue) {
return formatToCodeListText(
fieldValue,
props.controller.codeListItems!,
);
return findItem?.text;
}
return null;
});
......@@ -44,7 +49,23 @@ export const GridFieldColumn = defineComponent({
}
};
return { ns, codeListText, onCellClick };
const alignStyle = computed(() => {
let justContent = '';
switch (props.controller.model.align) {
case 'LEFT':
justContent = 'flex-start';
break;
case 'RIGHT':
justContent = 'flex-end';
break;
default:
justContent = 'center';
break;
}
return ns.cssVarBlock({ 'justify-content': justContent });
});
return { ns, alignStyle, codeListText, onCellClick };
},
render() {
const c = this.controller;
......@@ -52,6 +73,7 @@ export const GridFieldColumn = defineComponent({
return (
<div
class={[this.ns.b(), c.isLinkColumn && this.ns.m('link-column')]}
style={this.alignStyle}
onClick={this.onCellClick}
>
<span class={this.ns.e('text')}>{this.codeListText || value}</span>
......
......@@ -4,7 +4,7 @@ import {
} from '@ibiz-template/controller';
import { IPSUIActionGroupDetail } from '@ibiz-template/model';
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent } from 'vue';
import { computed, defineComponent } from 'vue';
import '@ibiz-template/theme/style/components/widgets/grid/grid-ua-column.scss';
export const GridUAColumn = defineComponent({
......@@ -31,12 +31,29 @@ export const GridUAColumn = defineComponent({
await props.uaColumn.onActionClick(detail, props.row, event);
};
return { ns, onStopPropagation, onActionClick };
const alignStyle = computed(() => {
let justContent = '';
switch (props.uaColumn.model.align) {
case 'LEFT':
justContent = 'flex-start';
break;
case 'RIGHT':
justContent = 'flex-end';
break;
default:
justContent = 'center';
break;
}
return ns.cssVarBlock({ 'justify-content': justContent });
});
return { ns, alignStyle, onStopPropagation, onActionClick };
},
render() {
return (
<div
class={this.ns.b()}
style={this.alignStyle}
on-dblclick={this.onStopPropagation}
onClick={this.onStopPropagation}
>
......
......@@ -13,6 +13,7 @@ import {
NotificationUtil,
LoadingUtil,
ErrorHandler,
OverlayController,
} from './util';
import { piniaInstance } from './store';
import { attachEnvironmentConfig } from './attach-environment-config';
......@@ -59,6 +60,7 @@ async function createApp(): Promise<void> {
ibiz.modal = new ModalUtil();
ibiz.notification = new NotificationUtil();
ibiz.loading = new LoadingUtil();
ibiz.overlay = new OverlayController();
ibiz.plugin = new PluginFactory();
Vue.use(UserRegister);
},
......
......@@ -18,6 +18,15 @@ import { basename, dirname, join } from 'path-browserify';
* @class PluginFactory
*/
export class PluginFactory implements IPluginFactory {
/**
* 是否为 http || https 开头
*
* @author chitanda
* @date 2022-11-07 14:11:28
* @protected
*/
protected urlReg = /^http[s]?:\/\/[^\s]*/;
/**
* 是否已经加载过文件缓存
*
......@@ -134,6 +143,7 @@ export class PluginFactory implements IPluginFactory {
}
let data: IParams | null = null;
const url = this.parseUrl(scriptUrl);
// 本地开发模式下的包引用加载
if (this.devPackages.has(name)) {
const fn = this.devPackages.get(name)!;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
......@@ -184,7 +194,7 @@ export class PluginFactory implements IPluginFactory {
if (arr && arr.length > 0) {
const folder = dirname(rootJsPath);
const all = arr.map(styleUrl => {
const url = `${join(folder, basename(styleUrl))}`;
const url = `${folder}/${basename(styleUrl)}`;
if (this.cache.has(url)) {
return false;
}
......@@ -213,9 +223,15 @@ export class PluginFactory implements IPluginFactory {
* @return {*} {string}
*/
protected parseUrl(script: string): string {
if (script.startsWith('http://') || script.startsWith('https://')) {
if (this.urlReg.test(script)) {
return script;
}
if (this.urlReg.test(ibiz.env.pluginBaseUrl)) {
if (script.startsWith('/')) {
return ibiz.env.pluginBaseUrl + script;
}
return `${ibiz.env.pluginBaseUrl}/${script}`;
}
return `./${join(ibiz.env.pluginBaseUrl, script)}`;
}
}
import {
CreateElement,
defineComponent,
getCurrentInstance,
PropType,
reactive,
ref,
VNode,
} from 'vue';
import { useNamespace } from '@ibiz-template/vue-util';
import { isNumber } from 'lodash-es';
import { IDrawerOptions, IOverlayContainer } from '@ibiz-template/runtime';
import { useUIStore } from '@/store';
import '@ibiz-template/theme/style/components/util/drawer/drawer.scss';
import { OverlayContainer } from '../overlay-container/overlay-container';
export const AppDrawerComponent = defineComponent({
props: {
opts: {
type: Object as PropType<IDrawerOptions>,
default: () => ({}),
},
},
setup(props, ctx) {
const ns = useNamespace('drawer');
const { proxy } = getCurrentInstance()!;
const isShow = ref(false);
const { zIndex } = useUIStore();
const drawerZIndex = zIndex.increment();
// 处理自定义样式
const customStyle = reactive<IData>({});
const { width, height } = props.opts;
if (width) {
customStyle.width = isNumber(width) ? `${width}px` : width;
}
if (height) {
customStyle.height = isNumber(height) ? `${height}px` : height;
}
// 所有关闭方式最终都走这个
const onVisibleChange = (state: boolean) => {
if (!state) {
zIndex.decrement();
ctx.emit('dismiss');
document.body.removeChild(proxy.$el);
}
};
const dismiss = () => {
isShow.value = false;
};
const present = () => {
isShow.value = true;
};
return {
ns,
isShow,
drawerZIndex,
customStyle,
dismiss,
present,
onVisibleChange,
};
},
render() {
return (
<i-drawer
value={this.isShow}
on-input={(val: boolean) => {
this.isShow = val;
}}
width={this.opts.width}
height={this.opts.height}
class={[this.ns.b()]}
style={{ [this.ns.cssVarBlockName('z-index')]: this.drawerZIndex }}
styles={this.customStyle}
placement={this.opts.placement || 'right'}
on-on-visible-change={this.onVisibleChange}
>
{this.$slots.default}
</i-drawer>
);
},
});
/**
* 创建抽屉
*
* @author lxm
* @date 2022-11-09 18:11:57
* @export
* @param {(_h: CreateElement) => VNode} render
* @param {(IDrawerOptions | undefined)} [opts]
* @returns {*} {IOverlayContainer}
*/
export function createDrawer(
render: (_h: CreateElement) => VNode,
opts?: IDrawerOptions | undefined,
): IOverlayContainer {
return new OverlayContainer(AppDrawerComponent, render, opts);
}
import {
CreateElement,
defineComponent,
getCurrentInstance,
PropType,
reactive,
ref,
VNode,
} from 'vue';
import { useNamespace } from '@ibiz-template/vue-util';
import { isNumber } from 'lodash-es';
import { IModalOptions, IOverlayContainer } from '@ibiz-template/runtime';
import { useUIStore } from '@/store';
import '@ibiz-template/theme/style/components/util/modal/modal.scss';
import { OverlayContainer } from '../overlay-container/overlay-container';
export const AppModalComponent = defineComponent({
props: {
opts: {
type: Object as PropType<IModalOptions>,
default: () => ({}),
},
},
setup(props, ctx) {
const ns = useNamespace('modal');
const { proxy } = getCurrentInstance()!;
const isShow = ref(false);
const { zIndex } = useUIStore();
const modalZIndex = zIndex.increment();
// 处理自定义样式,添加z-index变量
const customStyle = reactive<IData>({});
const { width, height } = props.opts;
if (width) {
customStyle.width = isNumber(width) ? `${width}px` : width;
}
if (height) {
customStyle.height = isNumber(height) ? `${height}px` : height;
}
// 合并options
const options = ref<IModalOptions>({ footerHide: true });
if (props.opts) {
Object.assign(options.value, props.opts);
}
// 所有关闭方式最终都走这个
const onVisibleChange = (state: boolean) => {
if (!state) {
zIndex.decrement();
ctx.emit('dismiss');
document.body.removeChild(proxy.$el);
}
};
const dismiss = () => {
isShow.value = false;
};
const present = () => {
isShow.value = true;
};
return {
ns,
isShow,
options,
modalZIndex,
customStyle,
present,
dismiss,
onVisibleChange,
};
},
render() {
return (
<i-modal
value={this.isShow}
on-input={(val: boolean) => {
this.isShow = val;
}}
class={[
this.ns.b(),
this.options.placement && this.ns.m(this.options.placement),
]}
style={{ [this.ns.cssVarBlockName('z-index')]: this.modalZIndex }}
styles={this.customStyle}
footer-hide={this.options.footerHide}
on-on-visible-change={this.onVisibleChange}
>
{this.$slots.default}
</i-modal>
);
},
});
/**
* 创建模态框
*
* @author lxm
* @date 2022-11-09 18:11:57
* @export
* @param {(_h: CreateElement) => VNode} render
* @param {(IModalOptions | undefined)} [opts]
* @returns {*} {IOverlayContainer}
*/
export function createModal(
render: (_h: CreateElement) => VNode,
opts?: IModalOptions | undefined,
): IOverlayContainer {
return new OverlayContainer(AppModalComponent, render, opts);
}
/* eslint-disable @typescript-eslint/no-explicit-any */
import { arrow, computePosition, flip, offset, shift } from '@floating-ui/dom';
import { IPopoverOptions } from '@ibiz-template/runtime';
import { useNamespace } from '@ibiz-template/vue-util';
import {
computed,
CreateElement,
defineComponent,
onUnmounted,
PropType,
ref,
VNode,
} from 'vue';
import '@ibiz-template/theme/style/components/util/popover/popover.scss';
import { OverlayPopoverContainer } from '../overlay-popover-container/overlay-popover-container';
/**
* 计算飘窗显示
*
* @author chitanda
* @date 2022-11-08 21:11:18
* @param {HTMLElement} element
* @param {HTMLElement} el
* @param {HTMLElement} arrEl
* @param {IPopoverOptions} opts
* @return {*} {Promise<void>}
*/
async function computePos(
element: HTMLElement,
el: HTMLElement,
arrEl: HTMLElement,
opts: IPopoverOptions,
): Promise<void> {
const options = await computePosition(element, el, {
placement: opts.placement,
strategy: 'absolute',
middleware: [offset(6), flip(), shift(), arrow({ element: arrEl! })],
});
{
const { x, y, placement, middlewareData } = options;
const { style } = el;
style.left = `${x}px`;
style.top = `${y}px`;
// 箭头位置
const { x: arrowX, y: arrowY } = middlewareData.arrow!;
const staticSide: any = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right',
}[placement.split('-')[0]];
Object.assign(arrEl.style, {
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
right: '',
bottom: '',
[staticSide]: '-4px',
});
}
}
const AppPopoverComponent = defineComponent({
props: {
opts: {
type: Object as PropType<IPopoverOptions>,
default: () => ({}),
},
},
setup(props, ctx) {
// 样式命名空间
const ns = useNamespace('popover');
// 是否显示
const isShow = ref(false);
// 是否悬浮在内容区,当悬浮在内容区时 autoClose 禁用
const isHover = ref(false);
// 跟 dom 元素
const el = ref<HTMLDivElement>();
// arrow dom 元素
const arrEl = ref<HTMLDivElement>();
// 是否可以自动关闭
const autoClose = computed<boolean>(() => {
return props.opts.autoClose === true && isHover.value === false;
});
// 鼠标入飘窗内容区
function onMouseenter(e: MouseEvent): void {
e.stopPropagation();
isHover.value = true;
}
// 鼠标出飘窗内容区
function onMouseleave(e: MouseEvent): void {
e.stopPropagation();
isHover.value = false;
}
// 点击容器关闭飘窗
function dismiss(): void {
ctx.emit('dismiss');
}
// 组件销毁用于事件触发
function destroy(e: Event): void {
e.stopPropagation();
if (autoClose.value) {
dismiss();
}
}
function addEvents(): void {
window.addEventListener('mousedown', destroy, { capture: true });
window.addEventListener('blur', destroy, { capture: true });
window.addEventListener('resize', destroy, { capture: true });
}
function removeEvents(): void {
window.removeEventListener('mousedown', destroy, { capture: true });
window.removeEventListener('blur', destroy, { capture: true });
window.removeEventListener('resize', destroy, { capture: true });
}
addEvents();
onUnmounted(() => {
removeEvents();
});
/**
* 飘窗显示并计算位置
*
* @author chitanda
* @date 2022-11-09 12:11:04
* @param {HTMLElement} target
* @return {*} {Promise<void>}
*/
async function present(target: HTMLElement): Promise<void> {
isShow.value = true;
await computePos(target, el.value!, arrEl.value!, props.opts);
}
return {
ns,
el,
arrEl,
isShow,
isHover,
present,
dismiss,
onMouseenter,
onMouseleave,
};
},
render() {
return (
<div
class={[
this.ns.b(),
this.ns.is('show', this.isShow),
this.ns.is('hover', this.isHover),
]}
ref='el'
onMouseenter={this.onMouseenter}
onMouseleave={this.onMouseleave}
>
<div class={[this.ns.e('arrow')]} ref='arrEl'></div>
{this.$slots.default}
</div>
);
},
});
/**
* 创建飘窗
*
* @author chitanda
* @date 2022-11-09 15:11:08
* @export
* @param {(_h: CreateElement) => VNode} render
* @param {IPopoverOptions} [opts]
* @return {*} {OverlayPopoverContainer}
*/
export function createPopover(
render: (_h: CreateElement) => VNode,
opts?: IPopoverOptions,
): OverlayPopoverContainer {
return new OverlayPopoverContainer(AppPopoverComponent, render, opts);
}
......@@ -4,5 +4,6 @@ export { ModalUtil } from './model-util/model-util';
export { NotificationUtil } from './notification-util/notification-util';
export { OpenViewUtil } from './open-view-util/open-view-util';
export { ErrorHandler } from './error-handler/error-handler';
export { AppModal } from './open-view-util/app-modal/app-modal';
export { AppDrawer } from './open-view-util/app-drawer/app-drawer';
export { OverlayContainer } from './overlay-container/overlay-container';
export { OverlayController } from './overlay-controller/overlay-controller';
export { OverlayPopoverContainer } from './overlay-popover-container/overlay-popover-container';
import { IBizContext } from '@ibiz-template/core';
import { IPSAppView } from '@ibiz-template/model';
import { IModalData, IOpenViewUtil } from '@ibiz-template/runtime';
import {
IModal,
IModalData,
IOpenViewUtil,
ViewMode,
} from '@ibiz-template/runtime';
import { generateRoutePath } from '@ibiz-template/vue-util';
import router from '@/router';
import { AppModal } from './app-modal/app-modal';
import { AppDrawer } from './app-drawer/app-drawer';
import {
getDrawerPlacement,
openViewDrawer,
openViewModal,
openViewPopover,
} from '../overlay-view-util/overlay-view-util';
/**
* 打开视图方式工具类
......@@ -47,7 +56,7 @@ export class OpenViewUtil implements IOpenViewUtil {
context?: IBizContext | undefined,
params?: IParams | undefined,
): Promise<IModalData> {
// 获取视图组件名和path
// 获取视图path
const modelPath = appView.modelPath!;
// 设置默认的modal参数
......@@ -57,25 +66,38 @@ export class OpenViewUtil implements IOpenViewUtil {
footerHide: true,
};
const res = await AppModal.openModal(
'ViewShell',
const modal: IModal = { mode: ViewMode.MODAL };
return openViewModal(
{
context,
params,
modelPath,
modal,
},
opts,
);
return res;
}
async popover(
appView: IPSAppView,
event: MouseEvent,
context?: IBizContext | undefined,
params?: IParams | undefined,
): Promise<IModalData> {
ibiz.log.warn('openPopover', appView, context, params);
throw new Error();
// 获取视图path
const modelPath = appView.modelPath!;
const modal: IModal = { mode: ViewMode.POPOVER };
return openViewPopover(
event,
{
context,
params,
modelPath,
modal,
},
{ autoClose: true, placement: 'bottom' },
);
}
/**
......@@ -93,9 +115,9 @@ export class OpenViewUtil implements IOpenViewUtil {
context?: IBizContext | undefined,
params?: IParams | undefined,
): Promise<IModalData> {
// 获取视图组件名和path
// 获取视图path
const modelPath = appView.modelPath!;
const placement = AppDrawer.getPlacement(appView.openMode);
const placement = getDrawerPlacement(appView.openMode);
// 设置默认的modal参数
const opts = {
......@@ -104,16 +126,16 @@ export class OpenViewUtil implements IOpenViewUtil {
placement,
};
const res = await AppDrawer.openDrawer(
'ViewShell',
const modal: IModal = { mode: ViewMode.DRAWER };
return openViewDrawer(
{
context,
params,
modelPath,
modal,
},
opts,
);
return res;
}
async custom(
......
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-unused-vars */
import Vue, { CreateElement, VNode } from 'vue';
import { QXEvent } from 'qx-util';
import { IOverlayContainer } from '@ibiz-template/runtime';
import router from '@/router';
import { piniaInstance } from '@/store';
/**
* 全局弹出承载组件
*
* @author chitanda
* @date 2022-11-09 12:11:09
* @export
* @class OverlayContainer
*/
export class OverlayContainer<O> implements IOverlayContainer {
/**
* vue 飘窗呈现实例
*
* @author chitanda
* @date 2022-11-09 12:11:09
* @protected
* @type {Vue}
*/
protected vm?: Vue;
/**
* 具体模态组件
*
* @author chitanda
* @date 2022-11-09 12:11:34
* @protected
* @type {*}
*/
protected modal: any;
/**
* 外面调用dismiss时传的result结果
*
* @author lxm
* @date 2022-11-09 20:11:06
* @protected
* @type {unknown}
*/
protected result?: unknown;
/**
* 内部事件
*
* @author chitanda
* @date 2022-11-09 12:11:42
* @protected
*/
protected evt: QXEvent<{ dismiss: (data?: unknown) => void }> = new QXEvent();
/**
* 创建全局呈现
*
* @author chitanda
* @date 2022-11-09 14:11:52
* @param {unknown} component
* @param {(h: CreateElement) => VNode} render
* @param {IPopoverOptions} [opts]
*/
constructor(
protected component: unknown,
protected render: (h: CreateElement) => VNode,
protected opts?: O,
) {
this.init();
}
/**
* 初始化飘窗
*
* @author chitanda
* @date 2022-11-09 12:11:55
* @protected
* @return {*} {void}
*/
protected init(): void {
const self = this;
const { render, opts } = this;
const container = document.createElement('div');
document.body.appendChild(container);
const vm = new Vue({
el: container,
pinia: piniaInstance,
router,
beforeDestroy() {
vm!.$el.remove();
},
mounted() {
self.modal = this.$refs.root;
},
destroyed() {
self.evt.emit('dismiss', self.result);
},
render(h) {
return h(
self.component as string,
{
ref: 'root',
props: { opts },
on: {
dismiss() {
vm!.$destroy();
},
},
},
[render(h)],
);
},
});
this.vm = vm;
}
/**
* 打开飘窗
*
* @author chitanda
* @date 2022-11-09 12:11:52
* @param {HTMLElement} target
* @return {*} {Promise<void>}
*/
async present(): Promise<void> {
return this.modal.present();
}
/**
* 手动调用关闭飘窗
*
* @author chitanda
* @date 2022-11-09 12:11:39
* @param {unknown} [data]
* @return {*} {Promise<void>}
*/
async dismiss(data?: unknown): Promise<void> {
this.result = data;
this.modal.dismiss();
}
/**
* 订阅窗口关闭
*
* @author chitanda
* @date 2022-11-09 12:11:20
* @template T
* @return {*} {Promise<T>}
*/
async onWillDismiss<T = unknown>(): Promise<T> {
return new Promise<T>(resolve => {
const callback = (data: unknown) => {
resolve(data as T);
this.evt.off('dismiss', callback);
};
this.evt.on('dismiss', callback);
});
}
}
import {
IOverlayController,
IDrawerOptions,
IPopoverOptions,
IModalOptions,
IOverlayContainer,
IOverlayPopoverContainer,
} from '@ibiz-template/runtime';
import { isFunction } from 'lodash-es';
import { createPopover } from '../app-popover/app-popover-component';
import { createModal } from '../app-modal/app-modal-component';
import { createDrawer } from '../app-drawer/app-drawer-component';
/**
* 用不同呈现方式绘制组件的通用工具类
*
* @author lxm
* @date 2022-11-08 16:11:09
* @export
* @class OverlayController
* @implements {IOverlayController}
*/
export class OverlayController implements IOverlayController {
popover<T = void>(
element: HTMLElement,
component: unknown,
props?: IParams | undefined,
opts?: IPopoverOptions | undefined,
): Promise<T> {
const popover = this.createPopover(component, props, opts);
popover.present(element);
return popover.onWillDismiss();
}
createPopover(
component: unknown,
props?: IParams | undefined,
opts?: IPopoverOptions | undefined,
): IOverlayPopoverContainer {
return createPopover(
isFunction(component)
? component
: h => h(component as string, { props }),
opts,
);
}
drawer<T = void>(
component: unknown,
props?: IParams | undefined,
opts?: IDrawerOptions | undefined,
): Promise<T> {
const drawer = this.createDrawer(component, props, opts);
drawer.present();
return drawer.onWillDismiss();
}
createDrawer(
component: unknown,
props?: IParams | undefined,
opts?: IDrawerOptions | undefined,
): IOverlayContainer {
return createDrawer(
isFunction(component)
? component
: h => h(component as string, { props }),
opts,
);
}
async modal<T = void>(
component: unknown,
props?: IParams | undefined,
opts?: IModalOptions | undefined,
): Promise<T> {
const modal = this.createModal(component, props, opts);
modal.present();
return modal.onWillDismiss();
}
createModal(
component: unknown,
props?: IParams | undefined,
opts?: IModalOptions | undefined,
): IOverlayContainer {
return createModal(
isFunction(component)
? component
: h => h(component as string, { props }),
opts,
);
}
}
/* eslint-disable no-unused-vars */
/* eslint-disable no-dupe-class-members */
import {
IPopoverOptions,
IOverlayPopoverContainer,
} from '@ibiz-template/runtime';
import { OverlayContainer } from '../overlay-container/overlay-container';
/**
* 飘窗组件呈现容器
*
* @author chitanda
* @date 2022-11-09 14:11:46
* @export
* @class OverlayPopoverContainer
* @extends {OverlayContainer<IPopoverOptions>}
* @implements {IOverlayPopoverContainer}
*/
export class OverlayPopoverContainer
extends OverlayContainer<IPopoverOptions>
implements IOverlayPopoverContainer
{
present(): Promise<void>;
present(target: HTMLElement): Promise<void>;
present(target?: HTMLElement): Promise<void> {
return this.modal.present(target);
}
}
import { ViewNeuron } from '@ibiz-template/controller';
import {
IDrawerOptions,
IModal,
IModalData,
IModalOptions,
IPopoverOptions,
ViewMode,
} from '@ibiz-template/runtime';
import { CreateElement, VNode } from 'vue';
export function createOverlayView(
close: (_res: IModalData) => void,
props?: IParams | undefined,
): (_h: CreateElement) => VNode {
return (h: CreateElement) =>
h('ViewShell', {
props,
on: {
neuronInit: (neuron: ViewNeuron) => {
neuron.evt.on('closeView', (res: IModalData) => {
close(res);
});
},
},
});
}
export function openViewModal(
props?: IParams | undefined,
opts?: IModalOptions | undefined,
): Promise<IModalData> {
const modal: IModal = { mode: ViewMode.MODAL };
const overlay = ibiz.overlay.createModal(
createOverlayView(res => overlay.dismiss(res), { ...props, modal }),
undefined,
opts,
);
overlay.present();
return overlay.onWillDismiss();
}
export function openViewDrawer(
props?: IParams | undefined,
opts?: IDrawerOptions | undefined,
): Promise<IModalData> {
const modal: IModal = { mode: ViewMode.DRAWER };
const overlay = ibiz.overlay.createDrawer(
createOverlayView(res => overlay.dismiss(res), { ...props, modal }),
undefined,
opts,
);
overlay.present();
return overlay.onWillDismiss();
}
export function openViewPopover(
event: MouseEvent,
props?: IParams | undefined,
opts?: IPopoverOptions | undefined,
): Promise<IModalData> {
const modal: IModal = { mode: ViewMode.DRAWER };
const overlay = ibiz.overlay.createPopover(
createOverlayView(res => overlay.dismiss(res), { ...props, modal }),
undefined,
opts,
);
overlay.present(event.target as HTMLElement);
return overlay.onWillDismiss();
}
const PlacementMap: IData = {
DRAWER_LEFT: 'left',
DRAWER_RIGHT: 'right',
DRAWER_TOP: 'top',
DRAWER_BOTTOM: 'bottom',
};
export function getDrawerPlacement(
openMode: string,
): IDrawerOptions['placement'] {
return PlacementMap[openMode] || 'right';
}
......@@ -2,6 +2,7 @@
"compilerOptions": {
"composite": true,
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
......
......@@ -6,6 +6,7 @@ import { join } from 'path';
function IBizVitePlugin(): Plugin[] {
const p: Plugin = {
name: 'iBizSys:System',
apply: 'build',
closeBundle() {
// 其他第三方依赖包
const map = {
......
此差异已折叠。
......@@ -25,7 +25,7 @@
</modules>
<properties>
<ibiz.cloud.version>8.1.0.241</ibiz.cloud.version>
<ibiz.cloud.version>8.1.0.243</ibiz.cloud.version>
</properties>
......
......@@ -50,7 +50,7 @@
</changeSet>
<!--输出实体[BOOK]数据结构 -->
<changeSet author="root" id="tab-book-341-3">
<changeSet author="root" id="tab-book-342-3">
<createTable tableName="T_BOOK">
<column name="BOOKNAME" remarks="" type="VARCHAR(200)">
</column>
......@@ -121,7 +121,7 @@
</changeSet>
<!--输出实体[BOOKTYPE]数据结构 -->
<changeSet author="root" id="tab-booktype-13-4">
<changeSet author="root" id="tab-booktype-15-4">
<createTable tableName="T_BOOKTYPE">
<column name="UPDATEDATE" remarks="" type="DATETIME">
</column>
......@@ -169,7 +169,7 @@
</changeSet>
<!--输出实体[PHONE]数据结构 -->
<changeSet author="root" id="tab-phone-158-6">
<changeSet author="root" id="tab-phone-160-6">
<createTable tableName="T_PHONE">
<column name="PHONEID" remarks="" type="VARCHAR(100)">
<constraints primaryKey="true" primaryKeyName="PK_PHONE"/>
......
......@@ -289,6 +289,71 @@
},
"tableType" : "MAIN"
} ],
"getAllPSDEDataExports" : [ {
"codeName" : "DataExport",
"dynaModelFilePath" : "PSMODULES/common/PSDATAENTITIES/Book/PSDEDATAEXPS/DataExport.json",
"maxRowCount" : 1000,
"name" : "数据导出",
"getPSDEDataExportItems" : [ {
"caption" : "属性9",
"format" : "%1$s",
"name" : "name",
"getPSDEField" : {
"name" : "FIELD9",
"codeName" : "Field9"
}
}, {
"caption" : "更新人",
"format" : "%1$s",
"name" : "updateman",
"getPSCodeList" : {
"modelref" : true,
"path" : "PSCODELISTS/SysOperator.json"
},
"getPSDEField" : {
"name" : "UPDATEMAN",
"codeName" : "UpdateMan"
}
}, {
"caption" : "更新时间",
"format" : "%1$s",
"name" : "updatedate",
"getPSDEField" : {
"name" : "UPDATEDATE",
"codeName" : "UpdateDate"
}
}, {
"caption" : "类型",
"format" : "%1$s",
"name" : "type",
"getPSDEField" : {
"name" : "TYPE",
"codeName" : "Type"
}
} ],
"defaultMode" : true,
"enableBackend" : true,
"enableFront" : false
} ],
"getAllPSDEDataImports" : [ {
"batchSize" : 1000,
"codeName" : "DataImport",
"createDataAccessAction" : "CREATE",
"getCreatePSDEAction" : {
"modelref" : true,
"path" : "PSMODULES/common/PSDATAENTITIES/Book/PSDEACTIONS/Create.json"
},
"name" : "数据导入",
"updateDataAccessAction" : "UPDATE",
"getUpdatePSDEAction" : {
"modelref" : true,
"path" : "PSMODULES/common/PSDATAENTITIES/Book/PSDEACTIONS/Update.json"
},
"enableBackend" : true,
"enableFront" : true,
"ignoreError" : true,
"id" : "PSMODULES/common/PSDATAENTITIES/Book/PSDEDATAIMPS/DataImport.json"
} ],
"getAllPSDEDataQueries" : [ {
"getAllPSDEDataQueryCodes" : [ {
"modelref" : true,
......
......@@ -1231,6 +1231,35 @@
"valueFormat" : "%1$s"
} ],
"getAllPSDELogics" : [ {
"codeName" : "PhoneNumber",
"defaultParamName" : "Default",
"dynaModelFilePath" : "PSMODULES/common/PSDATAENTITIES/Phone/PSDELOGICS/PhoneNumber.json",
"logicName" : "PhoneNumber",
"name" : "PhoneNumber",
"getPSDELogicNodes" : [ {
"codeName" : "Begin",
"logicNodeType" : "BEGIN",
"name" : "开始",
"parallelOutput" : true
} ],
"getPSDELogicParams" : [ {
"codeName" : "Default",
"logicName" : "传入变量",
"name" : "传入变量",
"getParamPSDataEntity" : {
"modelref" : true,
"path" : "PSMODULES/common/PSDATAENTITIES/Phone.json"
},
"default" : true,
"entityParam" : true
} ],
"getStartPSDELogicNode" : {
"modelref" : true,
"id" : "Begin"
},
"enableBackend" : true,
"enableFront" : false
}, {
"codeName" : "xxx",
"defaultParamName" : "Default",
"dynaModelFilePath" : "PSMODULES/common/PSDATAENTITIES/Phone/PSDELOGICS/xxx.json",
......
{
"codeName" : "PhoneNumber",
"defaultParamName" : "Default",
"dynaModelFilePath" : "PSMODULES/common/PSDATAENTITIES/Phone/PSDELOGICS/PhoneNumber.json",
"logicName" : "PhoneNumber",
"name" : "PhoneNumber",
"getPSDELogicNodes" : [ {
"codeName" : "Begin",
"logicNodeType" : "BEGIN",
"name" : "开始",
"parallelOutput" : true
} ],
"getPSDELogicParams" : [ {
"codeName" : "Default",
"logicName" : "传入变量",
"name" : "传入变量",
"getParamPSDataEntity" : {
"modelref" : true,
"path" : "PSMODULES/common/PSDATAENTITIES/Phone.json"
},
"default" : true,
"entityParam" : true
} ],
"getStartPSDELogicNode" : {
"modelref" : true,
"id" : "Begin"
},
"enableBackend" : true,
"enableFront" : false
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:g="http://www.jboss.org/drools/flow/gpd" xmlns:tns="http://www.jboss.org/drools" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.mvel.org/2.0" id="Definition" name="" targetNamespace="http://www.jboss.org/drools" typeLanguage="http://www.java.com/javaTypes">
<process id="cn.ibizlab.trainsys.core.common.service.logic.phonephonenumber" isClosed="false" isExecutable="true" name="common_phone_phonenumber_ruleFlow" processType="Private" tns:packageName="cn.ibizlab.trainsys.core.common.service.logic.phonephonenumber">
<extensionElements>
<tns:import name="java.util.Map" />
<tns:import name="org.springframework.util.StringUtils"/>
<tns:import name="cn.ibizlab.trainsys.util.helper.RuleUtils"/>
<tns:metaData express="" name="phonephonenumberdefault" type="entity"/>
<tns:metaData express="T(cn.ibizlab.trainsys.util.security.SpringContextHolder).getBean(T(cn.ibizlab.trainsys.core.common.service.IPhoneService))" name="iBzSysPhoneDefaultService" type="service"/>
<tns:metaData express="T(cn.ibizlab.trainsys.util.security.AuthenticationUser).getAuthenticationUser()" name="curuser" type="session"/>
<tns:global identifier="phonephonenumberdefault" type="cn.ibizlab.trainsys.core.common.domain.Phone" />
</extensionElements>
<startEvent id="begin" isInterrupting="true"/>
<endEvent id="begin_end" name="end"/>
<sequenceFlow id="begin_end_line" sourceRef="begin" targetRef="begin_end"/>
</process>
</definitions>
\ No newline at end of file
package cn.ibizlab.trainsys.common.logic.phonelogic.phonenumber;
import java.util.Map;
import java.util.HashMap;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.StringUtils;
import org.springframework.util.ObjectUtils;
import cn.ibizlab.trainsys.util.errors.BadRequestAlertException;
global cn.ibizlab.trainsys.core.common.domain.Phone phonephonenumberdefault;
global cn.ibizlab.trainsys.core.common.service.IPhoneService iBzSysPhoneDefaultService;
global cn.ibizlab.trainsys.util.security.AuthenticationUser curuser;
no-loop
//逻辑处理节点[开始]
rule "begin"
ruleflow-group "phonephonenumberbegin"
when
then
end
\ No newline at end of file
......@@ -205,6 +205,69 @@
"needResourceKey" : true,
"noServiceCodeName" : true
} ],
"getAllPSAppDEDataExports" : [ {
"codeName" : "DataExport",
"maxRowCount" : 1000,
"name" : "数据导出",
"getPSDEDataExportItems" : [ {
"caption" : "属性9",
"format" : "%1$s",
"name" : "name",
"getPSAppDEField" : {
"name" : "FIELD9",
"codeName" : "Field9"
}
}, {
"caption" : "更新人",
"format" : "%1$s",
"name" : "updateman",
"getPSAppDEField" : {
"name" : "UPDATEMAN",
"codeName" : "UpdateMan"
},
"getPSCodeList" : {
"modelref" : true,
"path" : "PSSYSAPPS/Web/PSAPPCODELISTS/SysOperator.json"
}
}, {
"caption" : "更新时间",
"format" : "%1$s",
"name" : "updatedate",
"getPSAppDEField" : {
"name" : "UPDATEDATE",
"codeName" : "UpdateDate"
}
}, {
"caption" : "类型",
"format" : "%1$s",
"name" : "type",
"getPSAppDEField" : {
"name" : "TYPE",
"codeName" : "Type"
}
} ],
"defaultMode" : true,
"enableBackend" : true,
"enableFront" : false
} ],
"getAllPSAppDEDataImports" : [ {
"batchSize" : 1000,
"codeName" : "DataImport",
"createDataAccessAction" : "CREATE",
"getCreatePSAppDEAction" : {
"modelref" : true,
"id" : "Create"
},
"name" : "数据导入",
"updateDataAccessAction" : "UPDATE",
"getUpdatePSAppDEAction" : {
"modelref" : true,
"id" : "Update"
},
"enableBackend" : true,
"enableFront" : true,
"ignoreError" : true
} ],
"getAllPSAppDEDataSets" : [ {
"codeName" : "FetchDefault",
"methodType" : "FETCH",
......@@ -1448,6 +1511,10 @@
"dEAPITag" : "BOOK",
"dataAccCtrlArch" : 1,
"dataAccCtrlMode" : 1,
"getDefaultPSAppDEDataExport" : {
"modelref" : true,
"id" : "DataExport"
},
"dynaModelFilePath" : "PSSYSAPPS/Web/PSAPPDATAENTITIES/Book.json",
"enableUIActions" : 15,
"getKeyPSAppDEField" : {
......
......@@ -6,6 +6,7 @@
"funcViewMode" : "MDATAVIEW",
"gridRowActiveMode" : 2,
"name" : "BookTypeGridView",
"openMode" : "DRAWER_BOTTOM",
"getPSAppDataEntity" : {
"modelref" : true,
"path" : "PSSYSAPPS/Web/PSAPPDATAENTITIES/BookType.json"
......
......@@ -21378,6 +21378,69 @@
"needResourceKey" : true,
"noServiceCodeName" : true
} ],
"getAllPSAppDEDataExports" : [ {
"codeName" : "DataExport",
"maxRowCount" : 1000,
"name" : "数据导出",
"getPSDEDataExportItems" : [ {
"caption" : "属性9",
"format" : "%1$s",
"name" : "name",
"getPSAppDEField" : {
"name" : "FIELD9",
"codeName" : "Field9"
}
}, {
"caption" : "更新人",
"format" : "%1$s",
"name" : "updateman",
"getPSAppDEField" : {
"name" : "UPDATEMAN",
"codeName" : "UpdateMan"
},
"getPSCodeList" : {
"modelref" : true,
"path" : "PSSYSAPPS/Web/PSAPPCODELISTS/SysOperator.json"
}
}, {
"caption" : "更新时间",
"format" : "%1$s",
"name" : "updatedate",
"getPSAppDEField" : {
"name" : "UPDATEDATE",
"codeName" : "UpdateDate"
}
}, {
"caption" : "类型",
"format" : "%1$s",
"name" : "type",
"getPSAppDEField" : {
"name" : "TYPE",
"codeName" : "Type"
}
} ],
"defaultMode" : true,
"enableBackend" : true,
"enableFront" : false
} ],
"getAllPSAppDEDataImports" : [ {
"batchSize" : 1000,
"codeName" : "DataImport",
"createDataAccessAction" : "CREATE",
"getCreatePSAppDEAction" : {
"modelref" : true,
"id" : "Create"
},
"name" : "数据导入",
"updateDataAccessAction" : "UPDATE",
"getUpdatePSAppDEAction" : {
"modelref" : true,
"id" : "Update"
},
"enableBackend" : true,
"enableFront" : true,
"ignoreError" : true
} ],
"getAllPSAppDEDataSets" : [ {
"codeName" : "FetchDefault",
"methodType" : "FETCH",
......@@ -22621,6 +22684,10 @@
"dEAPITag" : "BOOK",
"dataAccCtrlArch" : 1,
"dataAccCtrlMode" : 1,
"getDefaultPSAppDEDataExport" : {
"modelref" : true,
"id" : "DataExport"
},
"dynaModelFilePath" : "PSSYSAPPS/Web/PSAPPDATAENTITIES/Book.json",
"enableUIActions" : 15,
"getKeyPSAppDEField" : {
......
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册