Browse Source

update

main
wangshaoping 1 year ago
parent
commit
8ad7b3c1ff
  1. 2
      io.sc.engine.mv.frontend/package.json
  2. 14
      io.sc.engine.mv.frontend/src/views/result/Result.vue
  3. 26
      io.sc.engine.mv.frontend/src/views/result/ResultDetailDialog.vue
  4. 2
      io.sc.platform.core.frontend/package.json
  5. 27
      io.sc.platform.core.frontend/src/platform/components-ext/formater/DictionaryFormater.ts
  6. 15
      io.sc.platform.core.frontend/src/platform/components-ext/formater/index.ts
  7. 26
      io.sc.platform.core.frontend/src/platform/components-ext/options/DictionaryOptions.ts
  8. 19
      io.sc.platform.core.frontend/src/platform/components-ext/options/index.ts
  9. 1
      io.sc.platform.core.frontend/src/platform/index.ts
  10. 6
      io.sc.platform.core.frontend/src/platform/types/DictionaryType.ts
  11. 1
      io.sc.platform.core.frontend/src/platform/types/index.ts
  12. 21
      io.sc.platform.core.frontend/src/platform/utils/DictionaryTools.ts
  13. 2
      io.sc.platform.core.frontend/src/platform/utils/EnumTools.ts
  14. 1
      io.sc.platform.core.frontend/src/platform/utils/index.ts
  15. 4
      io.sc.platform.core.frontend/template-project/package.json
  16. 12
      io.sc.platform.core/src/main/java/io/sc/platform/core/controller/EnumWebController.java
  17. 1
      io.sc.platform.developer.doc/asciidoc/9999-appendix/appendix.adoc
  18. 33
      io.sc.platform.developer.doc/asciidoc/9999-appendix/icaap/icaap.adoc
  19. 3
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/SampleWorkFlowSystemDictionaryInitializer.java
  20. 12
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/jpa/entity/ProcessEntity.java
  21. 1
      io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessEntityServiceImpl.java
  22. 3
      io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/messages.json
  23. 1
      io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary.properties
  24. 1
      io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary_tw_CN.properties
  25. 1
      io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary_zh_CN.properties
  26. 1
      io.sc.platform.flowable/src/main/resources/liquibase/PF_1.0.0_20221228__Process Manager Database Schema DDL.xml
  27. 2
      io.sc.platform.lcdp.frontend/package.json
  28. 2
      io.sc.platform.lcdp.frontend/src/components/index.ts
  29. 6
      io.sc.platform.lcdp.frontend/src/i18n/messages.json
  30. 7
      io.sc.platform.lcdp.frontend/src/i18n/messages_tw_CN.json
  31. 6
      io.sc.platform.lcdp.frontend/src/i18n/messages_zh_CN.json
  32. 2
      io.sc.platform.lcdp.frontend/src/routes/routes.json
  33. 24
      io.sc.platform.lcdp.frontend/src/views/Bpm.vue
  34. 279
      io.sc.platform.lcdp.frontend/src/views/bpm/Bpm.vue
  35. 22
      io.sc.platform.lcdp.frontend/src/views/bpm/CreateProcessInstanceDialog.vue
  36. 175
      io.sc.platform.lcdp.frontend/src/views/bpm/ProcessDefine.vue
  37. 61
      io.sc.platform.lcdp.frontend/src/views/bpm/ProcessDesigner.vue
  38. 2
      io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/controller/support/RestCrudController.java
  39. 4
      io.sc.platform.system.frontend/src/views/dictionary/Dictionary.vue
  40. 38
      io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/controller/DictionaryApiWebController.java
  41. 12
      io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/controller/DictionaryWebController.java
  42. 5
      io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/jpa/repository/DictionaryRepository.java
  43. 13
      io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/service/DictionaryService.java
  44. 79
      io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/service/impl/DictionaryServiceImpl.java

2
io.sc.engine.mv.frontend/package.json

@ -80,7 +80,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.114",
"platform-core": "8.1.118",
"quasar": "2.14.2",
"tailwindcss": "3.4.0",
"vue": "3.4.3",

14
io.sc.engine.mv.frontend/src/views/result/Result.vue

@ -12,6 +12,7 @@
ref="gridRef"
:title="$t('menu.engine.mv.result')"
:config-button="true"
dense-header
selection="multiple"
:checkbox-selection="false"
:data-url="Environment.apiContextPath('/api/mv/viewer/result')"
@ -76,6 +77,11 @@
{ width: 100, name: 'executeMode', label: $t('io.sc.engine.mv.result.grid.entity.executeMode') },
{ width: 100, name: 'totalSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.totalSampleCount'), align: 'right' },
{ width: 100, name: 'defaultSampleCount', label: $t('io.sc.engine.mv.result.grid.entity.defaultSampleCount'), align: 'right' },
{
width: 900,
name: 'discrimination',
label: $t('io.sc.engine.mv.result.grid.entity.discrimination'),
columns: [
{
name: 'total',
label: $t('io.sc.engine.mv.result.grid.entity.total'),
@ -103,14 +109,8 @@
{ width: 100, name: 'ksQualitative', label: $t('io.sc.engine.mv.result.grid.entity.ks'), align: 'right' },
],
},
/*{
width: 900,
name: 'discrimination',
label: $t('io.sc.engine.mv.result.grid.entity.discrimination'),
columns: [
],
},*/
},
{
width: 200,
name: 'stability',

26
io.sc.engine.mv.frontend/src/views/result/ResultDetailDialog.vue

@ -256,6 +256,19 @@ const open = (detail: any) => {
tabChanged();
};
const close = () => {
dialogRef.value.hide();
if (rocEchart) {
rocEchart.dispose();
}
if (capEchart) {
capEchart.dispose();
}
if (ksEchart) {
ksEchart.dispose();
}
};
const tabChanged = () => {
nextTick(() => {
if ('discrimination' === selectedTabRef.value) {
@ -318,19 +331,6 @@ const tabChanged = () => {
});
};
const close = () => {
dialogRef.value.hide();
if (rocEchart) {
rocEchart.dispose();
}
if (capEchart) {
capEchart.dispose();
}
if (ksEchart) {
ksEchart.dispose();
}
};
const valueInRange = (value, config) => {
if (value >= config.from && value < config.to) {
return true;

2
io.sc.platform.core.frontend/package.json

@ -1,6 +1,6 @@
{
"name": "platform-core",
"version": "8.1.114",
"version": "8.1.118",
"description": "前端核心包,用于快速构建前端的脚手架",
"//main": "库的主文件",
"main": "dist/platform-core.js",

27
io.sc.platform.core.frontend/src/platform/components-ext/formater/DictionaryFormater.ts

@ -0,0 +1,27 @@
import type { OptionItemType } from '@/platform/types';
import { i18n } from '@/platform/plugin';
import { Tools } from '@/platform/utils';
class DictionaryFormater {
#dictionaryMap = {};
constructor(options: OptionItemType[]) {
for (const option of options) {
if (!Tools.isUndefinedOrNull(option.value)) {
this.#dictionaryMap[option.value] = option.label;
}
}
}
public formater() {
const dictionaryMap = this.#dictionaryMap;
return (value) => {
if (!Tools.isUndefinedOrNull(value)) {
return i18n.global.t(dictionaryMap[value]);
}
return '';
};
}
}
export { DictionaryFormater };

15
io.sc.platform.core.frontend/src/platform/components-ext/formater/index.ts

@ -1,8 +1,9 @@
import type { EnumType } from '@/platform/types';
import type { EnumType, DictionaryType } from '@/platform/types';
import { yesNoFormater, trueFalseFormater, enableTagFormater, successFailedTagFormater } from './BooleanFormater';
import { dateOnlyFormater } from './DatetimeFormater';
import { menuTypeFormater } from './MenuTypeFormater';
import { EnumFormater } from './EnumFormater';
import { DictionaryFormater } from './DictionaryFormater';
import { simpleClassNameFormater } from './SimpleClassNameFormater';
import { SplitFormater } from './SplitFormater';
import { ReplaceFormater } from './ReplaceFormater';
@ -10,6 +11,7 @@ import { i18nFormater } from './I18nFormater';
class Formater {
static #enumFormaterMap = {};
static #dictionaryFormaterMap = {};
public static none() {
return (value) => {
@ -67,6 +69,17 @@ class Formater {
return enumFormater.formater();
}
}
public static dictionary(dictionaryType: DictionaryType) {
if (dictionaryType) {
let dictionaryFormater = Formater.#dictionaryFormaterMap[dictionaryType.name];
if (!dictionaryFormater) {
dictionaryFormater = new DictionaryFormater(dictionaryType.items);
Formater.#dictionaryFormaterMap[dictionaryType.name] = dictionaryFormater;
}
return dictionaryFormater.formater();
}
}
}
export { Formater };

26
io.sc.platform.core.frontend/src/platform/components-ext/options/DictionaryOptions.ts

@ -0,0 +1,26 @@
import type { OptionItemType } from '@/platform/types';
import { i18n } from '@/platform/plugin';
class DictionaryOptions {
#options;
constructor(options: OptionItemType[]) {
this.#options = options;
}
public options() {
if (this.#options) {
const result = [];
for (const option of this.#options) {
result.push({
value: option.value,
label: i18n.global.t(option.label),
});
}
return result;
}
return [];
}
}
export { DictionaryOptions };

19
io.sc.platform.core.frontend/src/platform/components-ext/options/index.ts

@ -1,9 +1,11 @@
import type { EnumType } from '@/platform/types';
import type { EnumType, DictionaryType } from '@/platform/types';
import { yesNo, trueFalse, successFailed } from './BooleanOptions';
import { EnumOptions } from './EnumOptions';
import { DictionaryOptions } from './DictionaryOptions';
class Options {
static #enumOptionsMap = {};
static #dictionaryOptionsMap = {};
public static yesNo() {
return yesNo();
@ -17,14 +19,25 @@ class Options {
return successFailed();
}
public static enum(enumType: EnumType, includeEmpty: boolean = true) {
public static enum(enumType: EnumType) {
if (enumType) {
let enumOptions = Options.#enumOptionsMap[enumType.name];
if (!enumOptions) {
enumOptions = new EnumOptions(enumType.items);
Options.#enumOptionsMap[enumType.name] = enumOptions;
}
return enumOptions.options(includeEmpty);
return enumOptions.options();
}
}
public static dictionary(dictionaryType: DictionaryType) {
if (dictionaryType) {
let dictionaryOptions = Options.#dictionaryOptionsMap[dictionaryType.name];
if (!dictionaryOptions) {
dictionaryOptions = new DictionaryOptions(dictionaryType.items);
Options.#dictionaryOptionsMap[dictionaryType.name] = dictionaryOptions;
}
return dictionaryOptions.options();
}
}
}

1
io.sc.platform.core.frontend/src/platform/index.ts

@ -87,6 +87,7 @@ export { TagViewManager } from './plugin';
/**
*
*/
export { DictionaryTools } from './utils';
export { EnumTools } from './utils';
export { DateTools } from './utils';
export { JavascriptLoader } from './utils';

6
io.sc.platform.core.frontend/src/platform/types/DictionaryType.ts

@ -0,0 +1,6 @@
import type {OptionItemType} from './OptionItemType';
export type DictionaryType = {
name: string;
items: OptionItemType[];
};

1
io.sc.platform.core.frontend/src/platform/types/index.ts

@ -3,6 +3,7 @@ export type { AnyValueMapType } from './AnyValueMapType';
export type { AppType } from './AppType';
export type { ConfigureType } from './ConfigureType';
export type { DialogOptionsType } from './DialogOptionsType';
export type { DictionaryType } from './DictionaryType';
export type { EnumType } from './EnumType';
export type { FrontEndRouteType, FrontEndRouteMetaType, FrontEndRouteMetaActionType } from './FrontEndRouteType';
export type { GlobalReactiveType } from './GlobalReactiveType';

21
io.sc.platform.core.frontend/src/platform/utils/DictionaryTools.ts

@ -0,0 +1,21 @@
import type { DictionaryType } from '@/platform/types';
import { axios, Environment } from '@/platform/plugin';
class DictionaryTools {
public static async fetch(code: string): DictionaryType {
const response = await axios.get(Environment.apiContextPath('/api/dictionary/list/') + code);
if (response) {
return {
name: code,
items: response.data,
};
} else {
return {
name: code,
items: [],
};
}
}
}
export { DictionaryTools };

2
io.sc.platform.core.frontend/src/platform/utils/EnumTools.ts

@ -3,7 +3,7 @@ import { axios, Environment } from '@/platform/plugin';
class EnumTools {
public static async fetch(type: string): EnumType {
const response = await axios.get(Environment.apiContextPath('/api/enums/list/') + type);
const response = await axios.get(Environment.apiContextPath('/api/enum/list/') + type);
if (response) {
return {
name: type,

1
io.sc.platform.core.frontend/src/platform/utils/index.ts

@ -1,4 +1,5 @@
export { DateTools } from './DateTools';
export { DictionaryTools } from './DictionaryTools';
export { EnumTools } from './EnumTools';
export { JavascriptLoader } from './JavascriptLoader';
export { QuasarTools } from './QuasarTools';

4
io.sc.platform.core.frontend/template-project/package.json

@ -1,6 +1,6 @@
{
"name": "platform-core",
"version": "8.1.114",
"version": "8.1.118",
"description": "前端核心包,用于快速构建前端的脚手架",
"private": false,
"keywords": [],
@ -92,7 +92,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.114",
"platform-core": "8.1.118",
"quasar": "2.14.2",
"tailwindcss": "3.4.0",
"vue": "3.4.3",

12
io.sc.platform.core/src/main/java/io/sc/platform/core/controller/EnumsWebController.java → io.sc.platform.core/src/main/java/io/sc/platform/core/controller/EnumWebController.java

@ -14,12 +14,12 @@ import java.lang.reflect.Method;
* 当系统检测到需要重启时, 所有的请求都将被重定向到本控制器
*/
@RestController
@RequestMapping("/api/enums")
public class EnumsWebController {
@GetMapping("list/{lang}")
public Option[] list(@PathVariable(name = "lang",required = false) String type) throws Exception{
if(StringUtils.hasText(type)){
Class<?> clazz =Class.forName(type);
@RequestMapping("/api/enum")
public class EnumWebController {
@GetMapping("list/{enumType}")
public Option[] list(@PathVariable(name = "enumType",required = false) String enumType) throws Exception{
if(StringUtils.hasText(enumType)){
Class<?> clazz =Class.forName(enumType);
if(clazz.isEnum()){
Method method =clazz.getDeclaredMethod("values");
Enum<?>[] result =(Enum<?>[])method.invoke(null);

1
io.sc.platform.developer.doc/asciidoc/9999-appendix/appendix.adoc

@ -13,5 +13,6 @@ include::linux/linux.adoc[]
include::oauth2/oauth2.adoc[]
include::java/java.adoc[]
include::rwa/rwa.adoc[]
include::icaap/icaap.adoc[]

33
io.sc.platform.developer.doc/asciidoc/9999-appendix/icaap/icaap.adoc

@ -0,0 +1,33 @@
[appendix]
= ICCAP
ICAAP(Internal Capital Adequacy Assessment Process) 即内部资本充足率评估程序。
== 资本充足率(CAR: Capital adequacy ratio)
资本充足率是一个银行的资本总额对其风险加权资产的比率, 资本充足率反映商业银行在存款人和债权人的资产遭到损失之前,
该银行能以自有资本承担损失的程度。规定该项指标的目的在于抑制风险资产的过度膨胀,保护存款人和其他债权人的利益、
保证银行等金融机构正常运营和发展。各国金融管理当局一般都有对商业银行资本充足率的管制,目的是监测银行抵御风险的能力。
资本充足率有不同的口径,主要比率有资本对存款的比率、资本对负债的比率、资本对总资产的比率、资本对风险资产的比率等。
资本充足率 =(资本-资本扣除项)/(信用风险加权资产+(操作风险资本+市场风险资本)*12.5)
. 资本 =核心资本 + 附属资本(二级资本)
--
核心资本包括: 实收资本或普通股股本、资本公积、盈余公积、未分配利润和少数股权。
附属资本包括: 重估储备、未公开储备、普通呆账准备、混合债务工具和长期次级债务。
--
. 资本扣除项包括:(一)商誉;(二)商业银行对未并表金融机构的资本投资;(三)商业银行对非自用不动产和企业的资本投资。
. 风险加权资产为对应资产负债表上的资产乘以相应风险系数求和所得到的带有风险的资产额。商业银行计算各项贷款的风险加权资产时,应首先从贷款账面价值中扣除专项准备;其他各类资产的减值准备,也应从相应资产的账面价值中扣除。
资产包含:
. 第一类资产(实际贡献的所有者权益),即银行不用停止交易即可以化解风险的资产;
. 第二类资产(优先股加50%的附属债务),停业清理可以化解风险的资产,对储户提供相对较少额度的保护。
规定现金和政府债券没有风险,居民抵押贷款 50% 风险,其他所有类型资产 100% 风险。
== 所有者权益(Owners' Equity)
所有者权益 =资产 - 负债

3
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/initializer/SampleWorkFlowSystemDictionaryInitializer.java

@ -5,11 +5,12 @@ import io.sc.platform.core.initializer.ApplicationInitializerExecuteException;
import io.sc.platform.core.util.BeanUtil;
import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import io.sc.platform.system.dictionary.service.DictionaryService;
import io.sc.platform.system.i18n.jpa.entity.I18nEntity;
import io.sc.platform.system.i18n.service.I18nService;
import org.springframework.context.ApplicationContext;
public class SampleWorkFlowSystemDictionaryInitializer implements ApplicationInitializer {
private DictionaryService dictionaryService;
@Override
public void init(ApplicationContext applicationContext) {
this.dictionaryService = BeanUtil.getBean(applicationContext,DictionaryService.class);

12
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/jpa/entity/ProcessEntity.java

@ -81,7 +81,17 @@ public class ProcessEntity extends CorporationAuditorEntity<ProcessVo> {
@Override
public ProcessVo toVo() {
ProcessVo vo =new ProcessVo();
CorporationAuditorEntity.toVo(vo,this);
super.toVo(vo);
vo.setId(this.getId());
vo.setCategory(this.getCategory());
vo.setKey(this.getKey());
vo.setName(this.getName());
vo.setDescription(this.getDescription());
vo.setDeployedId(this.getDeployedId());
vo.setVersion(this.getVersion());
vo.setXml(this.getXml());
vo.setStatus(this.getStatus());
vo.setCanClaimTask(this.getCanClaimTask());
return vo;
}

1
io.sc.platform.flowable/src/main/java/io/sc/platform/flowable/service/impl/ProcessEntityServiceImpl.java

@ -48,6 +48,7 @@ public class ProcessEntityServiceImpl extends DaoServiceImpl<ProcessEntity, Stri
if(entity==null){
throw exceptionProvider.getCreateNullObjectException();
}
entity.setKey(entity.getCategory());
//如果流程定义 xml 文件为空,产生一个示例流程定义 xml
if(!StringUtils.hasText(entity.getXml())){
Resource rs =getSampleResource(entity.getCategory());

3
io.sc.platform.flowable/src/main/resources/META-INF/platform/plugins/messages.json

@ -1,6 +1,7 @@
{
"includes":[
"io/sc/platform/flowable/i18n/initializer",
"io/sc/platform/flowable/i18n/enums"
"io/sc/platform/flowable/i18n/enums",
"io/sc/platform/flowable/i18n/dictionary"
]
}

1
io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary.properties

@ -0,0 +1 @@
WORK_FLOW.SAMPLE=Example Workflow

1
io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary_tw_CN.properties

@ -0,0 +1 @@
WORK_FLOW.SAMPLE=\u793A\u4F8B\u6D41\u7A0B

1
io.sc.platform.flowable/src/main/resources/io/sc/platform/flowable/i18n/dictionary_zh_CN.properties

@ -0,0 +1 @@
WORK_FLOW.SAMPLE=\u793A\u4F8B\u6D41\u7A0B

1
io.sc.platform.flowable/src/main/resources/liquibase/PF_1.0.0_20221228__Process Manager Database Schema DDL.xml

@ -33,7 +33,6 @@
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"/>
<column name="CORP_CODE_" type="NVARCHAR(255)" remarks="所属法人代码"/>
</createTable>
<addUniqueConstraint tableName="SYS_PROCESS" columnNames="CATEGORY_,KEY_,CORP_CODE_"></addUniqueConstraint>
<addNotNullConstraint columnName="CATEGORY_" columnDataType="NVARCHAR(255)" tableName="SYS_PROCESS" constraintName="CONST_SYS_PROCESS_CATEGORY"/>
<addNotNullConstraint columnName="KEY_" columnDataType="NVARCHAR(255)" tableName="SYS_PROCESS" constraintName="CONST_SYS_PROCESS_KEY"/>
<addNotNullConstraint columnName="NAME_" columnDataType="NVARCHAR(255)" tableName="SYS_PROCESS" constraintName="CONST_SYS_PROCESS_NAME"/>

2
io.sc.platform.lcdp.frontend/package.json

@ -93,7 +93,7 @@
"luckyexcel": "1.0.1",
"mockjs": "1.1.0",
"pinia": "2.1.7",
"platform-core": "8.1.114",
"platform-core": "8.1.118",
"quasar": "2.14.2",
"tailwindcss": "3.4.0",
"vue": "3.4.3",

2
io.sc.platform.lcdp.frontend/src/components/index.ts

@ -4,7 +4,7 @@
import Frontend from '@/views/Frontend.vue';
import Theme from '@/views/Theme.vue';
import bpm from '@/views/Bpm.vue';
import bpm from '@/views/bpm/Bpm.vue';
const localComponents = {
'component.lcdp.Frontend': Frontend,

6
io.sc.platform.lcdp.frontend/src/i18n/messages.json

@ -145,11 +145,7 @@
"lcdp.frontend.export":"Export Frontend Package",
"lcdp.frontend.export.frontendWebContextPath":"Frontend Web Context Path",
"lcdp.frontend.export.backendApiWebContextPath":"Backend API Web Context Path",
"":"",
"":"",
"":"",
"":""
"lcdp.frontend.export.backendApiWebContextPath":"Backend API Web Context Path"
}

7
io.sc.platform.lcdp.frontend/src/i18n/messages_tw_CN.json

@ -145,10 +145,5 @@
"lcdp.frontend.export":"一鍵導出前端包",
"lcdp.frontend.export.frontendWebContextPath":"前端應用上下文路徑",
"lcdp.frontend.export.backendApiWebContextPath":"後端應用上下文路徑",
"":"",
"":"",
"":"",
"":"",
"":""
"lcdp.frontend.export.backendApiWebContextPath":"後端應用上下文路徑"
}

6
io.sc.platform.lcdp.frontend/src/i18n/messages_zh_CN.json

@ -145,10 +145,6 @@
"lcdp.frontend.export":"一键导出前端包",
"lcdp.frontend.export.frontendWebContextPath":"前端应用上下文路径",
"lcdp.frontend.export.backendApiWebContextPath":"后端应用上下文路径",
"":"",
"":"",
"":"",
"":""
"lcdp.frontend.export.backendApiWebContextPath":"后端应用上下文路径"
}

2
io.sc.platform.lcdp.frontend/src/routes/routes.json

@ -29,7 +29,7 @@
"parent": "/",
"priority": 0,
"component": "component.lcdp.bpm",
"componentPath": "@/views/Bpm.vue",
"componentPath": "@/views/bpm/Bpm.vue",
"redirect": null,
"meta": {
"permissions": ["/lcdp/bpm/**/*"]

24
io.sc.platform.lcdp.frontend/src/views/Bpm.vue

@ -1,24 +0,0 @@
<template>
<q-splitter :model-value="100" unit="px" class="w-full h-full">
<template #before>
<q-tabs v-model="selectedTabRef" vertical>
<q-tab name="processDefine" icon="mail" label="流程定义" />
<q-tab name="processInstance" icon="mail" label="流程实例" />
<q-tab name="task" icon="mail" label="工作任务" />
</q-tabs>
</template>
<template #after>
<q-tab-panels v-model="selectedTabRef" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up">
<q-tab-panel name="processDefine">
<ProcessDefine></ProcessDefine>
</q-tab-panel>
</q-tab-panels>
</template>
</q-splitter>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ProcessDefine from './bpm/ProcessDefine.vue';
const selectedTabRef = ref('processDefine');
</script>

279
io.sc.platform.lcdp.frontend/src/views/bpm/Bpm.vue

@ -0,0 +1,279 @@
<template>
<div>
<q-splitter :model-value="100" unit="px" class="w-full h-full">
<template #before>
<q-tabs v-model="selectedTabRef" vertical>
<q-tab name="processDefine" icon="mail" label="流程定义" />
<q-tab name="processInstance" icon="mail" label="流程实例" />
<q-tab name="task" icon="mail" label="工作任务" />
</q-tabs>
</template>
<template #after>
<q-tab-panels v-model="selectedTabRef" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up">
<q-tab-panel name="processDefine">
<w-grid
ref="processDefineGridRef"
title="流程定义列表"
:checkbox-selection="true"
:data-url="Environment.apiContextPath('/api/flowable/process')"
:pageable="true"
:pagination="{ sortBy: 'lastModifyDate', descending: true }"
:query-form-cols-num="3"
:query-form-fields="[
{ name: 'key', label: $t('code'), type: 'text' },
{ name: 'name', label: $t('name'), type: 'text' },
{ name: 'status', label: $t('status'), queryOperator: 'equals', type: 'select', clearable: true, options: Options.enum(ProcessStatusEnum) },
]"
:toolbar-actions="[
'query',
'separator',
'refresh',
'separator',
'add',
'clone',
{
extend: 'edit',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('SKETCH' === selected.status) {
return true;
}
}
return false;
},
},
{
extend: 'remove',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('SKETCH' === selected.status) {
return true;
}
}
return false;
},
},
'separator',
{
name: 'design',
label: '设计',
icon: 'bi-brush',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('SKETCH' === selected.status) {
return true;
}
}
return false;
},
click: (selecteds: object[]) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
const title = '流程设计器 - ' + selected.name + (selected.version ? ' (' + selected.version + ')' : '');
processDesignerDialogRef.open(title, selected.id);
}
},
},
{
name: 'deployment',
label: '发布',
icon: 'bi-arrow-up-circle',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('SKETCH' === selected.status) {
return true;
}
}
return false;
},
click: (selecteds: object[]) => {
DialogManager.confirm('您确定要发布流程吗?', () => {
axios.post(Environment.apiContextPath('api/flowable/process/deploy/') + selecteds[0].id).then(() => {
processDefineGridRef.refresh();
NotifyManager.success();
});
});
},
},
{
name: 'queryProcessInstance',
label: '查询流程实例',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('SKETCH' != selected.status) {
return true;
}
}
return false;
},
click: (selecteds: object[]) => {},
},
{
name: 'createProcessInstance',
label: '创建流程实例',
enableIf: (selecteds) => {
if (selecteds && selecteds.length > 0) {
const selected = selecteds[0];
if ('RELEASE' === selected.status) {
return true;
}
}
return false;
},
click: (selecteds) => {
createProcessInstanceDialogRef.open();
},
},
'separator',
'view',
'separator',
'export',
]"
:columns="[
{ width: 150, name: 'key', label: $t('code') },
{
width: '100%',
name: 'name',
label: $t('name'),
format: (value, row) => {
return Formater.dictionary(ProcessCategoryDictionaries)(row.key);
},
},
{ width: 60, name: 'version', label: $t('version') },
{ width: 60, name: 'status', label: $t('status'), format: Formater.enum(ProcessStatusEnum) },
{ width: 300, name: 'deployedId', label: $t('lcdp.bpm.deployId') },
{
width: 80,
name: 'canClaimTask',
label: $t('lcdp.bpm.canClaimTask'),
format: Formater.yesNo(),
},
{ width: 80, name: 'lastModifier', label: $t('lastModifier') },
{ width: 100, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() },
]"
:editor="{
dialog: {
width: '600px',
height: '610px',
},
form: {
colsNum: 1,
fields: [
{
name: 'category',
label: $t('category'),
type: 'select',
defaultValue: 'SAMPLE',
options: Options.dictionary(ProcessCategoryDictionaries),
'onUpdate:modelValue': (value) => {
const form = processDefineGridRef.getEditorForm();
form.setFieldValue('key', value);
form.setFieldValue('name', Formater.dictionary(ProcessCategoryDictionaries)(value));
},
},
{
name: 'key',
label: $t('code'),
type: 'text',
defaultValue: 'SAMPLE',
readonlyIf: () => {
return true;
},
},
{
name: 'name',
label: $t('name'),
type: 'text',
required: true,
defaultValue: Formater.dictionary(ProcessCategoryDictionaries)('SAMPLE'),
readonlyIf: () => {
return true;
},
},
{ name: 'description', label: $t('description'), type: 'textarea', rows: 1 },
{ name: 'xml', label: $t('xml'), type: 'textarea' },
{ name: 'status', label: $t('status'), type: 'text', defaultValue: 'SKETCH', hidden: true },
{ name: 'canClaimTask', label: $t('lcdp.bpm.canClaimTask'), type: 'checkbox', defaultValue: true, rule: [] },
],
},
}"
:viewer="{
panel: {
columnNum: 1,
fields: [
{ name: 'key', label: $t('code') },
{ name: 'name', label: $t('name'), format: Formater.none() },
{ name: 'version', label: $t('version') },
{ name: 'status', label: $t('status'), format: Formater.enum(ProcessStatusEnum) },
{ name: 'deployedId', label: $t('lcdp.bpm.deployId') },
{ name: 'canClaimTask', label: $t('lcdp.bpm.canClaimTask'), format: Formater.none() },
{ name: 'lastModifier', label: $t('lastModifier') },
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() },
],
},
}"
></w-grid>
</q-tab-panel>
<q-tab-panel name="processInstance">
<w-grid
ref="processInstanceGridRef"
title="流程实例列表"
:checkbox-selection="true"
:data-url="Environment.apiContextPath('/api/flowable/process')"
:pageable="true"
:pagination="{ sortBy: 'lastModifyDate', descending: true }"
:query-form-cols-num="3"
:query-form-fields="[]"
:toolbar-actions="['query', 'separator', 'refresh', 'separator', 'add', 'clone', 'separator', 'view', 'separator', 'export']"
:columns="[]"
:editor="{
dialog: {
width: '600px',
height: '610px',
},
form: {
colsNum: 1,
fields: [],
},
}"
:viewer="{
panel: {
columnNum: 1,
fields: [],
},
}"
></w-grid>
</q-tab-panel>
<q-tab-panel name="task"></q-tab-panel>
</q-tab-panels>
</template>
</q-splitter>
<ProcessDesigner ref="processDesignerDialogRef">
<iframe ref="processDesignerIframeRef" src="#" style="width: 100%; height: 100%"></iframe>
</ProcessDesigner>
<CreateProcessInstanceDialog ref="createProcessInstanceDialogRef"></CreateProcessInstanceDialog>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Environment, DialogManager, NotifyManager, axios, EnumTools, DictionaryTools, Formater, Options } from 'platform-core';
import ProcessDesigner from './ProcessDesigner.vue';
import CreateProcessInstanceDialog from './CreateProcessInstanceDialog.vue';
const selectedTabRef = ref('processDefine');
const processDefineGridRef = ref();
const processDesignerDialogRef = ref();
const processDesignerIframeRef = ref();
const createProcessInstanceDialogRef = ref();
const show = ref(true);
const ProcessStatusEnum = await EnumTools.fetch('io.sc.platform.flowable.enums.ProcessStatus');
const ProcessCategoryDictionaries = await DictionaryTools.fetch('WORK_FLOW');
</script>

22
io.sc.platform.lcdp.frontend/src/views/bpm/CreateProcessInstanceDialog.vue

@ -0,0 +1,22 @@
<template>
<q-dialog ref="dialogRef" title="ok" allow-focus-outside width="500px" height="230px" :can-maximize="false"> </q-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const dialogRef = ref();
const open = () => {
dialogRef.value.show();
};
const close = () => {
dialogRef.value.hide();
};
defineExpose({
open,
close,
});
</script>

175
io.sc.platform.lcdp.frontend/src/views/bpm/ProcessDefine.vue

@ -1,175 +0,0 @@
<template>
<platform-grid
ref="dataSupplementTypeGridRef"
:table-props="{ borderded: false, flat: true }"
:query-form-cols-number="dataSupplementTypeGrid.queryFormColsNumber"
:query-form-cols-auto="dataSupplementTypeGrid.queryFormColsAuto"
:table-title="dataSupplementTypeGrid.tableTitle"
:table-row-key="dataSupplementTypeGrid.tableRowKey"
:table-init-load-data="dataSupplementTypeGrid.tableInitLoadData"
:table-data-url="dataSupplementTypeGrid.tableDataUrl"
:table-show-sort-no="false"
:table-columns="dataSupplementTypeGrid.tableColumns"
:table-left-column-sticky-number="dataSupplementTypeGrid.tableLeftColumnStickyNumber"
:table-buttons="dataSupplementTypeGrid.tableButtons"
:query-form-fields="dataSupplementTypeGrid.queryFormFields"
:table-pagination="dataSupplementTypeGrid.tablePagination"
:add-form-props="dataSupplementTypeGrid.addFormProps"
:table-dense="true"
>
</platform-grid>
<ProcessDesigner ref="processDesignerDialogRef" :title="processDesignerDialogTitleRef" :maximized="true" @show="afterShow">
<iframe ref="processDesignerIframeRef" src="#" style="width: 100%; height: 100%"></iframe>
</ProcessDesigner>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { Environment, DialogManager, axios, BackendTools } from 'platform-core';
import ProcessDesigner from './ProcessDesigner.vue';
const { t } = useI18n();
const dataSupplementTypeGridRef = ref();
const processDesignerDialogRef = ref();
const processDesignerDialogTitleRef = ref();
const processDesignerIframeRef = ref();
const processStatus = await BackendTools.enums('io.sc.platform.flowable.enums.ProcessStatus', t);
const ProcessStatusSelectOptions = processStatus.list;
const ProcessStatusMap = processStatus.map;
const dataSupplementTypeGrid = {
queryFormColsNumber: 2,
queryFormColsAuto: false,
queryFormFields: [
{ label: '流程定义代码', modelName: 'key', type: 'text' },
{ label: '流程定义名称', modelName: 'name', type: 'text' },
],
hideBottom: false,
tableInitLoadData: true,
tableLeftColumnStickyNumber: 0,
tableTitle: '流程定义列表',
tableRowKey: 'id',
tableDataUrl: Environment.apiContextPath('/api/flowable/process'),
tablePagination: {
sortBy: 'lastModifyDate',
descending: true,
reqPageStart: 0,
rowsPerPage: 10,
},
tableButtons: [
'query',
'reset',
'separator',
'refresh',
'add',
{
name: 'clone',
label: '复制',
icon: 'bi-copy',
click: () => {},
},
'edit',
'delete',
'separator',
'view',
'separator',
{
name: '',
label: '设计',
icon: 'bi-brush',
click: (selectedRows: object[]) => {
const process = dataSupplementTypeGridRef.value.getSelectedRows()[0];
processDesignerDialogTitleRef.value = '流程设计器 - ' + process.name + (process.version ? ' (' + process.version + ')' : '');
processDesignerDialogRef.value.show();
},
},
{
name: '',
label: '发布',
icon: 'bi-arrow-up-circle',
enableIf: (selectedRow: object[]) => {
return selectedRow && selectedRow.length > 0;
},
click: (selectedRow: object[]) => {
DialogManager.confirm('您确定要发布流程吗?', () => {
axios.post(Environment.apiContextPath('api/flowable/process/deploy/') + selectedRow[0].id).then(() => {
dataSupplementTypeGridRef.value.refreshTable();
});
});
},
},
{
name: '',
label: '查询流程实例',
icon: '',
click: (selectedRow: object[]) => {},
},
{
name: '',
label: '创建流程实例',
icon: '',
click: (selectedRow: object[]) => {},
},
'inFullscreen',
],
tableColumns: [
{ name: 'key', label: t('code'), width: 100 },
{
name: 'name',
label: t('name'),
width: '100px',
},
{ name: 'version', label: t('version'), width: 80 },
{
name: 'status',
label: t('status'),
width: 80,
format: (val, row) => {
return ProcessStatusMap[val];
},
},
{ name: 'deployedId', label: t('lcdp.bpm.deployId'), width: 150 },
{
name: 'canClaimTask',
label: t('lcdp.bpm.canClaimTask'),
width: 80,
format: (val, row) => {
if (val === true) {
return '允许';
} else {
return '不允许';
}
},
},
{ name: 'lastModifier', label: t('lastModifier'), width: 100 },
{ name: 'lastModifyDate', label: t('lastModifyDate'), width: 120 },
],
addFormProps: {
dialogInitWidth: '60%',
dialogInitHeight: '50%',
formColsNumber: 1,
formColsAuto: false,
formFields: [
{ modelName: 'key', label: t('code'), type: 'text', required: true },
{ modelName: 'name', label: t('name'), type: 'text', required: true },
{ modelName: 'description', label: t('description'), type: 'textarea' },
{ modelName: 'xml', label: t('xml'), type: 'textarea' },
{ modelName: 'status', label: t('status'), type: 'text', defaultValue: 'SKETCH', hide: true },
{ modelName: 'category', label: t('category'), type: 'text', defaultValue: 'Sample', hide: true },
{ modelName: 'canClaimTask', label: t('lcdp.bpm.canClaimTask'), type: 'checkbox', defaultValue: true, rule: [] },
],
},
};
const afterShow = () => {
const url =
Environment.getWebContextPath() +
'io.sc.platform.lcdp.frontend/flowable/modeler/index.html#/editor/' +
dataSupplementTypeGridRef.value.getSelectedRows()[0].id;
processDesignerIframeRef.value.src = url;
};
</script>

61
io.sc.platform.lcdp.frontend/src/views/bpm/ProcessDesigner.vue

@ -1,21 +1,28 @@
<template>
<div>
<q-dialog ref="dialogRef" allow-focus-outside v-bind="attrs">
<q-dialog ref="dialogRef" title="ok" allow-focus-outside maximized>
<q-card
:style="{
width: attrs.maximized ? '100vw' : width,
width: '100vw',
'max-width': '100vw',
height: attrs.maximized ? '100vh' : height,
height: '100vh',
'max-height': '100vh',
}"
>
<q-card-section class="q-pt-none" :style="bodyStyle">
<slot></slot>
<q-card-section class="q-pt-none" style="padding: 0px 0px 0px 0px; height: calc(100%)">
<iframe ref="processDesignerIframeRef" src="#" style="width: 100%; height: 100%"></iframe>
</q-card-section>
<q-card-section class="fixed top-0 left-0" :style="headerStyle">
<q-card-section
class="fixed top-0 left-0"
:style="{
width: '100%',
padding: '4px 8px 4px 16px',
color: $gc.theme.topper.color,
'background-color': $gc.theme.topper.bgColor,
}"
>
<div class="flex justify-between">
<div class="text-h6">{{ title }}</div>
<div class="text-h6">{{ dialogTitle }}</div>
<div class="flex justify-end">
<q-btn v-close-popup dense flat icon="close" :title="$t('close')"> </q-btn>
</div>
@ -23,40 +30,32 @@
</q-card-section>
</q-card>
</q-dialog>
</div>
</template>
<script setup lang="ts">
import { useAttrs, ref } from 'vue';
const attrs = useAttrs();
const props = defineProps({
headerStyle: { type: String, default: 'width:100%;padding: 4px 8px 4px 16px' },
bodyStyle: { type: String, default: 'padding: 0px 8px 0px 8px;height:calc(100%)' },
title: { type: String, default: '' },
width: { type: String, default: '70%' },
height: { type: String, default: '70%' },
});
const emit = defineEmits<{
(
e: 'maximize', //
maximized: boolean, // true:,false:退
): void;
}>();
import { ref, nextTick } from 'vue';
import { Environment } from 'platform-core';
const dialogRef = ref();
const processDesignerIframeRef = ref();
let dialogTitle = '';
let processId = '';
const show = () => {
const open = (title: string, id: string) => {
dialogTitle = title;
processId = id;
dialogRef.value.show();
nextTick(() => {
const url = Environment.getWebContextPath() + 'io.sc.platform.lcdp.frontend/flowable/modeler/index.html#/editor/' + processId;
processDesignerIframeRef.value.src = url;
});
};
const hide = () => {
const close = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
open,
close,
});
</script>

2
io.sc.platform.mvc/src/main/java/io/sc/platform/mvc/controller/support/RestCrudController.java

@ -181,7 +181,7 @@ public abstract class RestCrudController<V extends BaseVo, E extends BaseEntity<
@AuditLog(action=AuditLogAction.RESET_DEFAULT_VALUES)
@PostMapping("resetDefaultValues")
@ResponseBody
public void resetDefaultValues() throws Exception{
public void resetDefaultValues(HttpServletRequest request,HttpServletResponse response) throws Exception{
service.resetDefaultValues();
}
}

4
io.sc.platform.system.frontend/src/views/dictionary/Dictionary.vue

@ -8,7 +8,7 @@
:data-url="Environment.apiContextPath('/api/system/dictionary')"
:query-form-fields="[{ name: 'code', label: $t('code'), type: 'text' }]"
:toolbar-configure="{ noIcon: false }"
:toolbar-actions="['refresh', 'separator', 'add', 'edit', 'remove', 'separator', 'view', 'separator', 'export']"
:toolbar-actions="['refresh', 'separator', 'add', 'clone','edit', 'remove', 'separator', 'view', 'separator', 'export']"
:columns="[
{ width: 200, name: 'code', label: $t('code') },
{ width: 200, name: 'value', label: $t('value') },
@ -27,7 +27,7 @@
fields: [
{ name: 'code', label: $t('code'), type: 'text', required: true },
{ name: 'value', label: $t('value'), type: 'text', required: true },
{ name: 'order', label: $t('order') },
{ name: 'order', label: $t('order'), type:'text', required: true },
],
},
}"

38
io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/controller/DictionaryApiWebController.java

@ -0,0 +1,38 @@
package io.sc.platform.system.dictionary.controller;
import io.sc.platform.core.support.Option;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.system.api.dictionary.DictionaryVo;
import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import io.sc.platform.system.dictionary.jpa.repository.DictionaryRepository;
import io.sc.platform.system.dictionary.service.DictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("api/dictionary")
public class DictionaryApiWebController extends RestCrudController<DictionaryVo,DictionaryEntity,String,DictionaryRepository, DictionaryService> {
@Autowired private DictionaryService dictionaryService;
@GetMapping("list/{dictionaryCode}")
public Option[] list(@PathVariable(name = "dictionaryCode",required = false) String dictionaryCode) throws Exception{
if(StringUtils.hasText(dictionaryCode)){
List<String> values =dictionaryService.getValuesByCode(dictionaryCode);
if(values!=null && !values.isEmpty()){
Option<String>[] result =new Option[values.size()];
for(int i=0;i<values.size();i++){
String value =values.get(i);
result[i] =new Option(value, dictionaryCode + "." + value);
}
return result;
}
}
return new Option[]{};
}
}

12
io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/controller/DictionaryWebController.java

@ -1,17 +1,16 @@
package io.sc.platform.system.dictionary.controller;
import io.sc.platform.core.support.KeyValue;
import io.sc.platform.mvc.controller.support.RestCrudController;
import io.sc.platform.mvc.support.OrderItem;
import io.sc.platform.system.api.dictionary.DictionaryVo;
import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import io.sc.platform.system.dictionary.jpa.repository.DictionaryRepository;
import io.sc.platform.system.dictionary.service.DictionaryService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Locale;
@RestController
@RequestMapping("api/system/dictionary")
@ -21,4 +20,9 @@ public class DictionaryWebController extends RestCrudController<DictionaryVo,Dic
public void updateDictionariesOrder(@RequestBody List<OrderItem<String,Integer>> orderItems) throws Exception{
service.updateDictionariesOrder(orderItems);
}
@GetMapping("getValuesByCodeWithMessage/{code}")
public List<KeyValue<String,String>> getValuesByCodeWithMessage(@PathVariable("code") String code, Locale locale) throws Exception{
return service.getValuesByCodeWithMessage(code,locale);
}
}

5
io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/jpa/repository/DictionaryRepository.java

@ -9,7 +9,10 @@ import java.util.List;
import java.util.Set;
public interface DictionaryRepository extends DaoRepository<DictionaryEntity,String> {
public List<DictionaryEntity> findByCodeOrderByOrder(String code);
public List<DictionaryEntity> findByCodeOrderByOrder(@Param("code")String code);
@Query("select entity from DictionaryEntity entity where entity.code in (:codes) order by entity.order")
public List<DictionaryEntity> findByCodesOrderByOrder(@Param("codes") Set<String> codes);
@Query("select entity from DictionaryEntity entity where entity.id in (:ids)")
public List<DictionaryEntity> findByIds(@Param("ids") Set<String> ids);

13
io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/service/DictionaryService.java

@ -1,13 +1,24 @@
package io.sc.platform.system.dictionary.service;
import io.sc.platform.core.support.KeyValue;
import io.sc.platform.mvc.support.OrderItem;
import io.sc.platform.orm.service.DaoService;
import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import io.sc.platform.system.dictionary.jpa.repository.DictionaryRepository;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public interface DictionaryService extends DaoService<DictionaryEntity, String, DictionaryRepository> {
public void updateDictionariesOrder(List<OrderItem<String,Integer>> orderItems) throws Exception;
public List<String> getValuesByCode(String code) throws Exception;
public Map<String, Set<String>> getValuesByCodes(Set<String> codes) throws Exception;
public List<KeyValue<String,String>> getValuesByCodeWithMessage(String code, Locale locale) throws Exception;
public Map<String, Set<KeyValue<String,String>>> getValuesByCodesWithMessage(Set<String> codes,Locale locale) throws Exception;
}

79
io.sc.platform.system/src/main/java/io/sc/platform/system/dictionary/service/impl/DictionaryServiceImpl.java

@ -1,5 +1,6 @@
package io.sc.platform.system.dictionary.service.impl;
import io.sc.platform.core.support.KeyValue;
import io.sc.platform.jdbc.util.SqlBatcher;
import io.sc.platform.mvc.support.OrderItem;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
@ -7,15 +8,17 @@ import io.sc.platform.system.dictionary.jpa.entity.DictionaryEntity;
import io.sc.platform.system.dictionary.jpa.repository.DictionaryRepository;
import io.sc.platform.system.dictionary.service.DictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
import java.util.*;
@Service
public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, String, DictionaryRepository> implements DictionaryService {
@Autowired private JdbcTemplate jdbcTemplate;
@Autowired private MessageSource messageSource;
@Override
@Transactional
@ -30,4 +33,78 @@ public class DictionaryServiceImpl extends DaoServiceImpl<DictionaryEntity, Stri
}
sqlBatcher.execute(jdbcTemplate);
}
@Override
public List<String> getValuesByCode(String code) throws Exception {
List<DictionaryEntity> entities =repository.findByCodeOrderByOrder(code);
if(entities!=null && !entities.isEmpty()){
List<String> result =new ArrayList<>();
for(DictionaryEntity entity : entities){
result.add(entity.getValue());
}
return result;
}
return Collections.emptyList();
}
@Override
public Map<String, Set<String>> getValuesByCodes(Set<String> codes) throws Exception {
List<DictionaryEntity> entities =repository.findByCodesOrderByOrder(codes);
if(entities!=null && !entities.isEmpty()){
Map<String, Set<String>> result =new LinkedHashMap<>();
for(DictionaryEntity entity : entities){
String code =entity.getCode();
String value =entity.getValue();
Set<String> values =result.get(code);
if(values==null){
values =new LinkedHashSet<>();
values.add(value);
result.put(code,values);
}else{
values.add(value);
}
}
return result;
}
return Collections.emptyMap();
}
@Override
public List<KeyValue<String, String>> getValuesByCodeWithMessage(String code, Locale locale) throws Exception {
List<DictionaryEntity> entities =repository.findByCodeOrderByOrder(code);
if(entities!=null && !entities.isEmpty()){
List<KeyValue<String, String>> result =new ArrayList<>();
for(DictionaryEntity entity : entities){
String _code =entity.getCode();
String _value =entity.getValue();
String _message =messageSource.getMessage(_code + "." + _value,null,locale);
result.add(new KeyValue<String,String>(_value,_message));
}
return result;
}
return Collections.emptyList();
}
@Override
public Map<String, Set<KeyValue<String, String>>> getValuesByCodesWithMessage(Set<String> codes, Locale locale) throws Exception {
List<DictionaryEntity> entities =repository.findByCodesOrderByOrder(codes);
if(entities!=null && !entities.isEmpty()){
Map<String, Set<KeyValue<String, String>>> result =new LinkedHashMap<>();
for(DictionaryEntity entity : entities){
String _code =entity.getCode();
String _value =entity.getValue();
String _message =messageSource.getMessage(_code + "." + _value,null,locale);
Set<KeyValue<String, String>> values =result.get(_code);
if(values==null){
values =new LinkedHashSet<KeyValue<String, String>>();
values.add(new KeyValue<>(_value,_message));
result.put(_code,values);
}else{
values.add(new KeyValue<>(_value,_message));
}
}
return result;
}
return Collections.emptyMap();
}
}

Loading…
Cancel
Save