1821349743@qq.com
2023-04-06 83abc7eff92a6f448758a3aad615a8606348592a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
版本控制:
    当前产品版本1.0.0
    衍生项目版本
        1.1.0       picc(绵阳人保)
        1.2.0       xn
    详细解释
        (1)目前的版本号共有3级,标准版按照1.0.0
        (2)第一位作为产品大版本
        (3)第二位作为对应项目的版本
        (4)第三位作为小版本升级
        (5)例如,当前版本为1.0.0,由该版本衍生的A项目,则A项目版本为1.1.0;继续衍生的B项目,版本为1.2.0;若是A项目升级,则可以将版本更新为1.1.1。
        (6)但凡项目占用之后,该数字就一直归该项目使用
        (7)当产品版本升级到2.0.0之后,衍生的项目版本则为2.x.0
 
1.数据源
    必须配置默认的数据源,名称必须为default,见application.properties
    sourceName=default
2.表设计
    id字段: 类型=bigint ,长度11    
    uuid字段、uuid引用字段:,长度都是80
    字段类型除了通用String...外,还有一个类型:parentuuid,用此字段表示主子表的关系,
    同时还必须配关联的父表名称,同一个关联父表,只能配一个parentuuid类型的字段,如果是普通主外键关联,就不用parentuuid
    比如:button表 的字段定义,父表function
    字段名                                             字段类型                           关联主表
    id
    uuid
    ......
    function_uuid      parentuuid     mrbase_sys_datamodel_table(保存表的uuid,显示表的名称,默认关联主表的uuid)
    字段的长度为下拉选择,根据不同的数据类型,定义不同的长度选项,如:10、20、50、100等
    
    字段类型:
    除标准的string datetime int double ,还有特殊:parentuuid(主子表关系,记录父表uuid)、code(编码字段 000-000-002)、serialNumber(GXD201209020001)
    字段类型=parentuuid时,必须field_relation_table字段填写父表的uuid否则也不能作为主子表保存
    
    所有类型:string、int、number(小数)、datetime、parentuuid、code、serialNumber、idcard、url、ip、mac、email、userid、orgUuid、file、flowStatus、table_name
    
3.缓存数据
 *     缓存配置表:SYS_CACHE_CONFIG
 *     字段:ID、uuid、cache_name、TABLENAME(S200)、CACHEFIELD(分级缓存字段,逗号分隔),FIELDS(S4000,字段名,逗号分隔)、filter(S4000)、备注说明....
 *  cache_name:唯一
 *     常用数据、基础数据缓存
 *     通用缓存:通过配置表、字段(多个)、查询条件来指定要缓存的数据内容,采用Map封装,key=cache_name,值=DataTableEntity
 *     特殊缓存:单独写方法加载数据并处理数据,封装同通用缓存一样
 *     支持分组缓存,无限级,分组字段必须在缓存字段里面
     支持加载子表数据
 *     缓存数据,存在数据不一致问题,当两个进程同时对一个表的缓存进行读和写时---------------
 *    新增、修改、删除缓存表时,要更新缓存-------------------------------------
 *     初始数据
    table_name=mrbase_sys_datamodel_table
    table_name=mrbase_sys_datamodel_field |  cache_fields=*  |  group_field=table_uuid
    table_name=mrbase_sys_datamodel_field        |  cache_fields=*  |  filter=field_type='parentUuid'
    table_name=mrbase_function_permission |  cache_fields=role_uuid,function_uuid,button_uuid | group_field=role_uuid
    
*缓存刷新,数据新增、修改、删除时都会刷新对应的该表的所有缓存配置,还可以调自定义的代码进行刷新(bean_name、bean_method(String uuid) 参数是操作数据的uuid ,bean_method() 启动时会调此方法,必须定义两个方法       )
*缓存的使用查询方法:
    有分组,分组字段,对应值 
     对应缓存中对应的分组字段,整个参数为这,表示没有分组,只能后面不为空,不能前面为空,例如:
    缓存的分组字段:field1、field2、field3 ,获取时参数值,只能三种情况:{value1,null,null}、{value1,value2,null}、{value1,value2,value2},
    不能出现 {value1,null,value3} 、{null,null,value3}  、{null,value2,value3} 等情况
    如:
    DataTableEntity dt=DataPoolCacheImpl.getInstance().getCacheData("所有字段信息并按表分组",new String[] {tableUuid});
    未分组:
    DataTableEntity table=DataPoolCacheImpl.getInstance().getCacheData("所有表信息");
 
    (1)redis工具类
    配置文件:lx-base-server\lx-base-server-cache\src\main\resource\cache.properties
    类:com.lx.base.cache.util.RedisUtil
    介绍:
        全部为静态方法,无需注入,包含了对key以及5种基本类型(string,hash,list,set,zset)的操作,方法名称经过简化和归一化,与原生命令稍有不同;
        按照key,string,hash,list,set,zset的顺序排列方法,不同类型间存在注释分割,若是后续有新增,应当写在对应的范围内;
        新增/修改类的方法以add/set开头,后面紧跟类型,最后跟方法特性;
        获取类方法以get开头,后面紧跟类型,最后跟方法特性;(特殊的,求取交差并集并存储返回的是个数);
        判定是否存在为exists开头,后面紧跟类型;
        删除类方法以del开头,后面紧跟类型,最后跟方法特性;
        相对特殊的命名-clearOutTime(移除超时时间),replaceListAimValue(list-替换指定下标的值),moveSet(set-移动值到指定key的set中)
    测试类:com.lx.base.cache.TestRedisUtil
    介绍:
        除第一个为获取数据方法外,后面均为单元测试,可以在这里找到对应的示例代码;
        除部分类转换的重载方法没有写单元测试,有些重载的方法放在一个单元测试内,基础的获取类方法没有单独写单元测试;
        每一个单元测试均已通过,但是一次性全开时,本地卡在约一半处;
        单元测试的方法名为test + 实际方法名(首字母转大写);
        除RedisUtil新增方法或者测试方法存在错误,尽量不更新该类,更新时,需要注释所有单元测试方法;
 
4.json数据中,字段~type~,不是字段名,是子表数据在修改时候的操作类型,新增、修改、删除
    新增,uuid没有值, 可能不写~type~=xxx
    修改,uuid有值, 可能不写~type~=xxx
    只有删除时用这个字段来区分,即~type~=del
    修改主子表数据 主表必须有uuid字段,子表数据中三个种情况:新增 ~type~="",uuid="",修改:~type~="",uuid="不为空",删除:~type~="del",uuid="不为空"
    子表列数要一致
    
5.所有实体类型,都必须有个字段 table_name,存表名称 ,可以实体类中定义成常量
 
6.API请求参数
    API请求json的参数名称:formData,   Token参数封装在json中,名称:accessToken
    RequestParameterEntity 封装所有参数请求,详细见该类
    Object bean=request.getAttribute("requestPara");
    String accessToken = null;
    if(bean !=null)    {    
        RequestParameterEntity reqp=(RequestParameterEntity)bean;
        accessToken=reqp.getToken();
    }
    -----获取表单数据------
    public FieldSetEntity getFormData() {
        return formData;
    }
 
7.所有controller 必须继承  AbstractBaseController
    修改、删除 返回
    OK()
    登录返回
    OK_login
    新增返回
    OK_Add(String uuid)
    查询返回
    OK_List(FieldSetEntity fs)
    OK_List(DataTableEntity dt)
    
    通用错误返回, 新增、修改、删除、查询失败
    public String error(String code,String msg )
 
9.所有service 必须继承  AbstractBaseService
    /**
     * 数据查询 ,spring 注入
     */
    @Autowired
    public BaseDao baseDao = null;
    
10.~table~ 参数在新增、修改接口时必须放到数据的前面,以此来首先获取到    
 
13.高级参照下拉框接口数据
{
    "code":200,
    "~table~":"xxxxx",
    "data":[{"value_field":"xxxx","view_fields":"xxxx","f1":"xxx","f2":"xxxx","f3":"xxx","code":"xxx"}
    ,{"value_field":"xxxx","view_fields":"xxxx","f1":"xxx","f2":"xxxx","f3":"xxx","code":"xxx"}],
    "pagesize":20,
    "cpage":4,
    "totalCount":343,
    "status":"success",
    "msg":"成功"
}
普通下拉框接口
{
    "code":200,
    "~table~":"mrbase_sys_dict",
    "data":[{"dict_value":"xxxx","dict_label":"xxxx"}
    ,{"dict_value":"xxxx","dict_label":"xxxx"}],
    "pagesize":0,
    "cpage":0,
    "totalCount":0,
    "status":"success",
    "msg":"成功"
}
 
14.下拉参照配置,保存时select_fields必须处理生成,value_field+" value_field,"+view_fields+" view_fields "+prompt_fieldxxxxx
    prompt_fieldxxxxx,是由prompt_field字段处理而成,如:field1,field2,field3 ,处理后变成    ,field1 f1,field2 f2,field3 f3,org_level_code code
    最后select_fields=xxxx value_field,xxxx view_fields,field1 f1,field2 f2,field3 f3,其中 value_field、view_fields、f1、f2、f3 是固定字段
    其中filter字段,是配置人员手写的sql条件,字符串中可能配置动态参数,格式为:~参数名称~,前端调用此参照时,也必须传对应的参数值 ,例如:
    配置filter: uuid=~cust_uuid~ and name like '%~cust_name~%'
    前端参数:{cust_uuid="sdgeasge",cust_name="中国"}
    
    filter字段中还可以配置系统变量,如:is_used=1 and uuid in (select  language_uuid from mrbase_sys_company_language where org_level_uuid='{{COMPANY_UUID}}') 
    {{COMPANY_UUID}}:当前登录人员的公司UUID.
    
    display_type: 1:列表  2:树结构,当等于2表示此参照数据显示树型,同时  code_field、parent_code_field 、delay_load要必填,
    code_field:上下级关系表中的 编码字段:001,此字段也处理后放到select_fields字段中去:生成   xxxxx  code,此前端在点击一个节点时,取code的值传给接口,接返回其下面的子数据
    parent_code_field:父编码字段:001
    org_filter_field:根据表中的公司字段进行数据过滤,多个以逗号分隔
    usr_filter_field:人员数据过滤条件字段,必须是数据源表中的人员字段,可以多个,逗号分隔,
    
14.1 下拉参照(高级参照、数据字典)在列表中显示:
    配置mrbase_sys_datamodel_field.field_reference字段,配参照名称或数据字典名称,如果是数据字典名称加书名号括起来,如:《gender》
    在列表的查询方法,对列表数据进行封装一次:baseDao.loadPromptData(dt);
 
15.token参数  token=xxxxxxxx,放到json数据中,整个json作为一个参数 formData={"token"="xxxxxxxx",xxxxxxxxx}
 
16.创建单位管理员,使用mrbase_sys_user表,is_manamger默认为是
    创建管理员时,分配,只能给下级管理员分配自已范围内的权限,初始一个超级管理员,初始一个超级管理员角色。分给超级管员
    创建单位管理员,只能创建下级单位的管理员,可以关联多个下级单位,对每个单位进行单独的权限设置,必须先选角色权限,
    功能中标识是否是后台管理功能 ,管理员自身的权限必须是后台功能,为普通人员分配权限时,必须是非后台管理功能
17.功能与按钮api合成一个,采用主子表方式操作
18.开发功能参照system工程中的代码
19.获取application中的配置参数,使用:
    String path = Global.getSystemConfig("upload.file.path", "d:");
20.开发模式
    一个负责一个功能模块的开发,包括接口层、服务层
20.包名规则,以com.lx.+模块名称+.controller(service、entity)
 
21.全部在lx__Server下面创建maven模块,不是maven工程
   <groupId>com.lx</groupId>   不用改
    <artifactId>-server</artifactId> 以开头,后面是模块名称
    <version>1.0.0-SNAPSHOT</version> 不用改
22.如果要引用jar,单独在pom中添加依赖,内部工程 也是这么相引
23.spring bean引用
private static MenuService menuService = SpringContextHolder.getBean(MenuService.class);
 
24.获取当前登录用户
    SystemUser user = SpringMVCContextHolder.getCurrentUser();
25.获取当前request、reponse、session等
    SpringMVCContextHolder.getHttpxxxx()
    
26.对数据的操作,可以参考代码:JsonUtil,如何生成的 FieldSetEnttiy,如何在fs中获取子表(DataTableEntity),如何获取fs中的字段值,如何在DataTableEntity中获取一条记录,和一条记录中的字段值 
 
27.对一条记录的读写操作
 
28.对数据集的读写操作
    从缓存中获取到数据集
    DataTableEntity dt=DataPoolCacheImpl.getInstance().getCacheData("所有字段信息并按表分组");
 
        DataTableEntity table=DataPoolCacheImpl.getInstance().getCacheData("mrbase_sys_datamodel_table");
        String tableUuid=null;
        String subTableUUid=null;
        循环每一条数据
        for(int i=0;i<table.getRows();i++) {
            if(tableUuid != null && subTableUUid != null )
                break;
                获取一条记录中的一个字段值
            if(tableName.equals(table.getString(i,"table_name"))){
                tableUuid=table.getString(i, "uuid");
            }
            if(subTableName.equals(table.getString(i,"table_name"))){
                subTableUUid=table.getString(i, "uuid");
            }
        }
29.事务操作
       所有新增、修改、删除都要做事务
       理论上事务建立在Service层,不在controller层
        实现方式:
       ----------------------------------------------------------------
       service类中要做事务的方法添加注解:@Transactional,如下:
       /***
         * 新增客户数据事务处理(并且在组织架构中新增一条最顶级的数据)
     * @param fse 客户单位数据
     * @return
     * @throws BaseException
     */
    @Transactional
    public String addClient(FieldSetEntity fse) throws BaseException{
       -----------------------------------------------------------------
       添加service类的接口类,接口类必须定义要做事务的方法
       controller必须继承AbstractBaseController
       -----------------------------------------------------------------
       controller中的具体调用:
       把 systemClientsService.addClient(fse); 改成以下代码
       
        /**事务处理实现**/
        ISystemClientsService service=(ISystemClientsService)getProxyInstance(systemClientsService);
        String uuid = service.addClient(fse);
        
      ISystemClientsService :service类的接口类
      systemClientsService:spring注入的service类
    -------------------------------------------------------------------   
        
30.查询列表中包含子表数据
    /**
     * 
     * @param tableName
     * @param filter
     * @param para
     * @param fields
     * @param orderby
     * @param psize
     * @param pindex
     * @param isMoreSubData 是否同时查询所有子表的对应数据
     * @return
     * @throws BaseException
     */
    public  DataTableEntity listTable(String tableName,String filter,Object para[],String fields[],String orderby, int psize,int pindex,boolean isMoreSubData)
 
 
    /**
     * @ 查询列表数据的所有子表数据 String 1=每条记录uuid,String 2= 子表名称 
     * @param uuids 逗号分隔 父列表uuids
     * @param table_name
     * @return
     */
    public Map <String,Map<String,DataTableEntity>> listSubData(String uuids,String tableName ) throws BaseException;
31.关于附件获取操作
    RequestParameterEntity.getFormData().getString(附件字段);//上传的原始文件名,多个以逗号分隔
    RequestParameterEntity.getFiles().get(原始文件名); //对应的文件,文件名:uuid+"_"+文件的原始名称  ,一次只能获取一个
    
32.关于手写sql语句查询和分页的要求
     select TIMESTAMPDIFF(YEAR,aciwe.start_datetime,aciwe.end_datetime) AS start_datetime from a,b where f1=f2 或 a left join b on f1=f2
         字段别名必须是表中的字段,否则无法获取到对应字段的表名和字段信息定义,如:
   start_datetime 必须是 a表或b表中的一个字段
   
         多表关联查询,表定义:a,b 或 a left join b on f1=f2 整个做为表
                                    条件定义,where 后面 : f1=f2 
 33.如查sql语句中没有uuid字段,无法查询出子表         
 
 34.系统错误说明
                               
       系统错误分为两种:主动抛出错误、捕获错误
       主动抛出:
       /**
     * 构造函数---主动抛出的错误
     * @param code  错误码代码
     * @param error 错误信息
     * @param c     错误发生的类
     * @param method 错误发生方法
     */
    public  BaseException(String code,String error,Class c,String method);
    
       捕获错误:
       /**
     * 构造函数,记录错误到库---捕获的错误
     * @param code  错误码代码
     * @param exc   捕获的错误
     */
    public  BaseException(String code,String error,Class c,String method,Exception sysExc)
    
35.licese支持
      硬件信息读取库文件,下载地址:http://sigar.hyperic.com/
        windows版                                                                  mac版                                                            linux版
      sigar-x86-winnt.dll                 xxxxx                  xxxxxxxxxx
      sigar-amd64-winnt.dll               xxxxxx                 xxxxxxxxx
    同时将对应的dll文件或者so文件添加到系统目录。例如:windows下把sigar-x86-winnt.dll添加到c:\WINDOWS\system32或者jdk的bin目录。
 
36.关于通用编码 001-002-003
    表中存放编码的字段,必须在mrbase_sys_datamodel_field表中该字段的field_type=code
    界面调用接口获取编码:/api/common/createCode,见测试类CodeTest
    如果界面没有调用接口生成编码,则可以在业务controller中可调以下代码获取
    String code=codeService.createCode(fse.getString("table_name"), fse.getString("field_name"), fse.getString("parentCode")==null?"":fse.getString("parentCode"));
    在新增的controller中调用,在底层Dao中的保存方法中获取获取的临时编码去验证是否被占用,占用则重新生成,保证唯一性
    返回json值中code的值即为生成的编码值
    
37.通用参数验证、数据保存验证
    参数验证:com.lx..module.sys.config.RegistValidate类
    在registValidateParameter方法中添加验证代码,如:
    DataValidateInterceptor.registValidatPara("/api/prompt/findPrompt","client_uuid",VerifyRegularUtil.VALIDATE_REQUIRED);
    参数1:接口
    参数2:验证字段
    参数3:验证类型
    数据保存验证,在core包中的dao中自动根据数据表字段的配置验证,通常不用配,但如果有其它验证,也可以在保存和修改接口中配置,否则保存和修改接口不用配
    根据字段类型进行验证,如:字段是mail,mrbase_sys_datamodel_field.field_type=email,现只支持:
    int、number(小数)、idcard、url、ip、mac、datetime、length、email
    
38.properties配置文件参数获取
    调用:
    Global.getPropertyToBoolean("druid.datasource.testOnBorrow", "false")
    方法:
    /**
     * 获取配置,如果获取不到配置,则传默认值
     * @key key值
     * @defaultValue 为空时的默认值
     */
    public static String getSystemConfig(String key,String defaultValue)
    public static Integer getPropertyToInteger(String key, String defValue)
    public static Long getPropertyToLong(String key, String defValue)
    public static Boolean getPropertyToBoolean(String key, String defValue)
39.数据权限
    在列表中添加数据权限条件的获取,添加到列表查询方法中。
    /**
     * 获取人员的数据权限,总入口 ,不过滤人员,只过滤公司
     * 指定要过滤的 公司字段  使用默认公司字段进行过滤-org_level_uuid
     * @return
     */
    public  String getDataFilter();
    /**
     * 获取人员的数据权限,总入口 ,不过滤人员,只过滤公司
     * @param org_fields   指定要过滤的公司字段,为空则,使用默认公司字段进行过滤-org_level_uuid
     * @return
     */
    public  String getDataFilter(String org_fields)
    /**
     * 获取人员的数据权限,总入口 ,过滤指定人员字段,使用默认公司字段进行过滤-org_level_uuid
     * @tableName 人员过滤的表
     * @param staff_fields  
     * @return
     */
    public  String getDataFilter(String tableName,String staff_fields)
    /**
     * 获取人员的数据权限,总入口 ,人员 公司同时过滤
     * @param tableName   指定是哪张表的数据 权限过滤
     * @param staff_fields 指定要过滤的人员字段 ,为空则,不用人员过滤
     * @param org_fields   指定要过滤的 公司字段,为空则,使用默认公司字段进行过滤-org_level_uuid
     * @return
     */
    public  String getDataFilter(String tableName,String staff_fields,String org_fields)
    
 40.关于流水号  
     只需要在配置中配置流水号,见表mrbase_sys_swift_config
    表中存放流水号的字段,必须在mrbase_sys_datamodel_field表中该字段的field_type=serialNumber ,示例见test表
    界面调用接口获取编码:/api/common/createSerialNumber,见测试类CodeTest,必传参数:serialNumberName,对应表流水号配置表中的swift_config_name字段值
    返回json值中serialNumber的值即为生成的流水号
    如果界面没有调用接口生成编码,则可以在业务controller中可调以下代码获取
    String serialNumber=serialNumberService.createSerialNumber(serialNumberName);
    在新增的controller中调用,在底层Dao中的保存方法中获取获取的临时编码去验证是否被占用,占用则重新生成,保证唯一性
    接
     配置支持格式:
      [YYYY]:年
      [MM] :月
      [DD] :日
      [COMPANY_NAME]:公司名称,对应org_level_name
      [COMPANY_CODE]:公司编码  org_level_code
      [DEPT_NAME]:部门名称org_level_name
      [DEPT_CODE]:部门编码org_level_code
41.接口签名认证
       系统参数文件中可配置:
    #是否启用接口签名认证
    signature.isEnable=false
    #在启用接口签名认证时,排除指定接口无需签名认证
    signature.exclude.path=/login,/logout,/relogin
    #接口签名认证有效期,单位秒,签名认证有效期=空或0,则表示不验证
    signature.expire=10
    -------------
    使用MD5加密,加密内容:参数formData的值+KEY(单独指定)
    前端加密后的字符串要大写:sign=GEGSTLLSEGEL
    formData中要包含timestamp时间戳的值,格式为:yyyyMMddHHmmss
42.通用删除验证
    调用:
        模块 system
        类     SystemDeleteValidationService
        方法 public  boolean  deleteValidation(String tableName, String uuids,String delete_filter) throws BaseException {
    参数说明:
         tableName删除数据表表名
         uuids要删除数据的uuid,多个用逗号分隔
         delete_filter删除条件  fields='name'
    返回说明:
        验证通过没有关联任何数据返回true
        参数缺失返回false
        验证没通过关联了其他表数据抛出异常,异常信息中提示关联数据表,多个用逗号分隔
43.国际化
    label:
        用户登录成功后,调接口:
        /api/language/load-international-info/{version}
        加载指定客户端、版本号、默认语言的所有国际化数据
        客户端、版本号、默认语言接口参数上传
        
    value:
        1、首先配置表、字段为国际化字段
        2、前端调接口获取哪些表有哪些国际化字段,在界面的中对应元素后面添加地球图标,点图标弹出国际化录入
               接口:/api/language/list-international-fields-info/{version}
        3、新增保存数据json格式:
        {
            "token":"11111-新增提交数据",
            "system_language_code":"ZH",
            "system_client_type":"PC",
            "system_client_version":"iphome X 13.1.3",
            "app_version":"V2.0.0",
            "time_zone_offset":"240",
            "sign":"eyJhbGciOiJIUzI1N",
            "~table~":"mrbase_sys_users",
            "name":[
                {
                    "en":"internationalization"
                },
                {
                    "zh":"国际化"
                }
            ],
            "address":[
                {
                    "en":"zhuhai"
                },
                {
                    "zh":"珠海"
                }
            ],
            "phone":"18123938722",
            "sub_table_name":[
                {
                    "filed1":"value1",
                    "filed2":"value2",
                    "name":[
                        {
                            "en":"internationalization"
                        },
                        {
                            "zh":"国际化"
                        }
                    ],
                    "address":[
                        {
                            "en":"zhuhai"
                        },
                        {
                            "zh":"珠海"
                        }
                    ]
                }
            ]
        }
        4、查询列表数据
        首先查询出所有业务数据,再调
        /**
         * 业务代码层调用
         * 获取业务对应字段的国际化数据,如果language_code不为空,表明是手机端
         * @param dt 业务表数据 
         * @param language_code 不为空则为手机端
         * @return
         */
        DataTableEntity baseDao.listInternationDataTable(DataTableEntity dt,String language_code ) 封装国际化数据到每条记录的每个国际化字段。
        FieldSetEntity  baseDao.listInternationDataTable(FieldSetEntity fs,String language_code )  封装国际化数据到单条记录的每个国际化字段。
        
        //baseDao.processInternationDataTable(DataTableEntity dt,String language_code ),国际化字段不是数组格式
        //baseDao.processInternationDataTable(FieldSetEntity fs,String language_code ) 国际化字段不是数组格式
        返回json格式:
        
        {
            "code":"200",
            "data":[
                {
                    "uuid":"100001",
                    "name":[
                        {
                            "uuid":"xxxxx",
                            "en":"internat"
                        },
                        {
                            "uuid":"xxxxx",
                            "zh":"国际化"
                        }
                    ],
                    "address":[
                        {
                            "uuid":"xxxxx",
                            "en":"zhuhai"
                        },
                        {
                            "uuid":"xxxxx",
                            "zh":"珠海"
                        }
                    ],
                    "phone":"18123938729"
                }
            ],
            "msg":"成功",
            "status":"success"
        }
        
        5、修改保存数据json格式:
        {
            "token":"11111-新增提交数据",
            "language_code":"zh",
            "client_type":"PC",
            "client_version":"iphome X 13.1.3",
            "app_version":"V2.0.0",
            "time_zone_offset":"240",
            "sign":"eyJhbGciOiJIUzI1N",
            "~table~":"mrbase_sys_users",
            "uuid":"100001",
            "name":[
                {
                    "uuid":"xxxxx",
                    "en":"internationalization"
                },
                {
                    "uuid":"xxxxx",
                    "zh":"国际化"
                }
            ],
            "address":[
                {
                    "uuid":"xxxxx",
                    "en":"zhuhai"
                },
                {
                    "uuid":"xxxxx",
                    "zh":"珠海"
                }
            ],
            "phone":"18123938722"
        }
        
        6.不能国际化的表:
        mrbase_sys_cache_config 缓存配置
        mrbase_sys_data_sources 数据库连接配置
        mrbase_sys_datamodel_field 数据结构字段信息
        mrbase_sys_datamodel_table 数据结构表信息
        mrbase_sys_language_code
        mrbase_sys_language_cont_values
        mrbase_sys_language_master
        mrbase_sys_language_values
        mrbase_sys_message_exchange
        mrbase_sys_message_message_exchange
        mrbase_sys_message_template
        mrbase_sys_message_template_language
        mrbase_sys_message_user_exchange
        mrbase_sys_prompt
        mrbase_sys_swift_config
        mrbase_sys_tree_config
        mrbase_sys_version_buttons_mapping
        定时任务所有表
44.文件上传--第三方文件服务器
    1)获取客户上传的文件总大小:com.lx.base.file.service.FileManagerService
        /**
         * 获取客户上传的文件总大小
         * @param clientUUID        客户UUID
         * @return                  已上传文件总大小
         * @throws BaseException    基本异常
         */
        public int findClientFileUsedCapacity(String clientUUID) throws BaseException
    2)获取客户剩余的文件总大小:com.lx.base.file.service.FileManagerService
        /**
         * 获取客户剩余的文件总大小
         * @param clientUUID    客户UUID
         * @return              剩余空间大小
         */
        public int findClientFileResidueCapacity(String clientUUID) throws BaseException
 
        /**
         * 获取客户剩余的文件总大小
         * @param fse           客户fse
         * @return              剩余空间大小
         */
        public int findClientFileResidueCapacity(FieldSetEntity fse) throws BaseException
    3)上传文件
        1>前端上传文件,返回文件信息给后端,调用请求前缀/api/fileManager/add-file-record-plan/{version},详情见showdoc中14-1、文件新增准备,后端返回fse
        传入json示例:
        {
          "org_level_uuid": "b8631dad-6cc1-4d5a-9f6f-e8c76e6a5464",
          "~table~": "mrbase_sys_attachments",
          "attachment_title": "test_202006221036.doc",
          "client_uuid": "06f959c8-4f41-407c-9bcc-8137a8b22f50",
          "language": "mslc1112",
          "function_uuid": "97779f8b-9657-47e7-8915-2f51113210fe",
          "client_type": "web",
          "attachment_data_table": "test_project",
          "version": "v1",
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsImlhdCI6MTU5Mjc5MzY3OSwic3ViIjoic2hpX2Nob25nZnVAMTYzLmNvbSIsImlzcyI6Ind3dy5tcmMuY29tIiwiZXhwIjoxNTkyODY1Njc5fQ.kgffR0iYgjKhFSNI-ak5hPCf3453aOYXIrwHte7pRAY",
          "product_uuid": "001",
          "staff_uuid": "e2f158ec-a6c7-40e0-a201-4fd7eb2e0e98",
          "attachment_data_field": "attachment",
          "attachment_size": "1"
        }
        2>前端得到后端返回后拼接url,调用至服务器端上传文件,根据服务器端状态返回调用请求前缀/api/fileManager/add-file-callback/{version},详情见showdoc中14-2、文件新增结果回调。服务端新增成功本地执行修改,变更文件记录状态为上传成功,返回update;服务端新增失败本地执行删除,还原记录,返回del
        传入json示例:
        {
          "result": "1",
          "uuid": "c48c0147-8b2f-4a8d-9d5b-46c55ceb725b",
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsImlhdCI6MTU5Mjc5NjMzNiwic3ViIjoic2hpX2Nob25nZnVAMTYzLmNvbSIsImlzcyI6Ind3dy5tcmMuY29tIiwiZXhwIjoxNTkyODY4MzM2fQ.LiUeajNzZAHWuT5O_YdPh5IOp7geVjklBGrWUBz79fo"
        }
    4)删除文件
        1>前端删除文件,返回文件信息给后端,调用请求前缀/api/fileManager/del-file-record-plan/{version},详情见showdoc中14-3、文件删除准备,后端返回fse
        传入json示例:
        {
          "uuid": "c48c0147-8b2f-4a8d-9d5b-46c55ceb725b",
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsImlhdCI6MTU5MjgwNDMyOSwic3ViIjoic2hpX2Nob25nZnVAMTYzLmNvbSIsImlzcyI6Ind3dy5tcmMuY29tIiwiZXhwIjoxNTkyODc2MzI5fQ.Fsau5aHByePG7E-p68Y8_Py6yGAcYwbxQLwhkz20MGQ"
        }
        2>前端得到后端返回后拼接url,调用至服务器端删除文件,根据服务器端状态返回调用请求前缀/api/fileManager/del-file-callback/{version},详情见showdoc中14-4、文件删除结果回调。服务端删除成功本地执行删除,返回del;服务端删除失败本地执行修改,还原文件记录状态,返回update
        传入json示例:
        {
          "result": "0",
          "uuid": "c48c0147-8b2f-4a8d-9d5b-46c55ceb725b",
          "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsImlhdCI6MTU5MjgwNTg4OSwic3ViIjoic2hpX2Nob25nZnVAMTYzLmNvbSIsImlzcyI6Ind3dy5tcmMuY29tIiwiZXhwIjoxNTkyODc3ODg5fQ.0x7xmEM2G8qXq7jiYQiy6iDm48tYEqVS9UqhlHUB9xk"
        }
45.本地文件上传--系统服务器
    核心:需要sigar-amd64-winnt.dll或者sigar-x86-winnt.dll文件置于jdk的bin中或者c盘windows/system32
    上传目录配置,见properties文件中的upload.file。xxxx 几个相关参数
    上传文件自动存到目录下,在controller或service层中读取操作。
    
46.消息服务
    1.新建队列
     public static void createQueue(String queue_name)
     无返回值
    2.删除队列
     public static void deleteQueue(String queue_name)
     无返回值
    3.新建交换机
    messageService.addExchange
    参数
    "exchange_uuid":"新建交换机"
    返回值:交换机uuid
    4.绑定交换机
    messageService.bindExchange
    参数:
    {"user_uuid":"用户uuid",
    "exchange_uuid":"交换机uuid"}
    返回值:Boolean
    5.解绑交换机
     messageService.unbindExchange
     参数:
     {"user_uuid":"用户uuid",
     "exchange_uuid":"交换机uuid"}
     返回值:boolean
     6.添加消息且添加消息记录
     messageService.addMessage
     参数:
       {
       "exchange_uuid":"交换机uuid"
       "message_uuid":"用户uuid"
       "message":"消息内容"
       "template_id":"模板id"
       "create_by":"操作人uuid"
       "virtual_hosts":"虚拟机名"
        }
47.综合搜索:
    findService.listUuid
    参数:
    {
    ~table~:[“”,””,””,””]    //数据库表
    Conditions:[{condition:value},{},{}...]    //条件
    language:value    //国际化语言
    }
    返回值:list<String> uuids
    
    当查询语名,使用多表联合查询,并使用了别名时,需要添加表别名、字段别名设置,并把sql语句使用select * from (查询语句+数据权限条件+高级查询条件)  b 括起来,注意
 48.以下内容变更   
 1.core包引入变更
<dependency>
    <groupId>com.lx</groupId>
    <artifactId>base-server-core</artifactId>
    <version>1.0.0-releases</version>
</dependency>
2.所有引入core包中类的路径含有全部替换成base,如:
import com.product..core.dao.BaseDao;    ->  import com.product.base.core.dao.BaseDao;
 
3.获取当前登录用户对应员工信息:
    改成getCurrentStaff()  FieldSetEntity
 
4.获取当前登录用户对应员工所属公司信息
    getCurrentCompany()  FieldSetEntity
单独获取公司的uuid、org_level_name(公司名称) org_level_code(公司编码)
 
4.获取当前登录用户对应员工所属部门信息
    getCurrentDept()  FieldSetEntity
单独获取部门uuid
 
5.获取当前登录用户对应员工所属客户信息
    getCurrentCustomer()
单独获取客户uuid 、客户名称、客户编码
 
6.获取当前登录用户对应管理员信息
    getCurrentManager()
 
7.获取查询数据集的所有uuid
    public String DataTableEntity.getUuids()  原 ,改为以下
 
    指定表的所有uuid,返回数组
    -> public Object[] getUuids(Object tableName) 
    指定表的所有uuid,返回逗号分隔的字符串
    -> public String getUuidsToString(Object tableName) 
    返回默认表的所有uuid,返回数组
    -> public Object[] getUuids()
    返回默认表的所有uuid,返回逗号分隔的字符串
    -> public String getUuidsToString() 
8.登录上传固定参数
    system_language_code 语言编码 zh en
    system_client_type   客户类型
    system_client_version 代码版本
 
9.接口版本号大写V再加3个数字如下:
所有接口必须上传版本号
http://{IP}:{PORT}/{ProjectName}/api/app/homepage/get-home-page-list/v1 或v2
 
10.new FieldSetEntity()后,首先要设置表名,才能调setValue(String fieldName,Object fieldValue), 否则只能调setValue(String fieldName,Object fieldValue,Object tableName)
 
11.public FieldSetEntity getLeaderStaff() throws BaseException  SystemUser.getLeaderStaff()获取当前人所直属领导信息
 
12.public FieldSetEntity getJobPost() throws BaseException   SystemUser.getJobPost()获取当前人所岗位信息
 
13.public DataTableEntity loadDirectSubordinate(String staffUuid) throws BaseException     StaffManagerService.loadDirectSubordinate()    获取指定人员的直接下属
 
14.public DataTableEntity loadAllSubordinate(String staffUuid) throws BaseException   StaffManagerService.loadAllSubordinate()      获取指定人员的所有直接下属
 
15.public FieldSetEntity loadStaffLeader(Integer userid)    StaffManagerService.loadStaffLeader()                                     获取人员的直属领导
 
16.public FieldSetEntity loadStaffLeader(String staffUuid)    StaffManagerService.loadStaffLeader()                                     获取人员的直属领导
 
17.查询出来的数据集DataTableEntity 或FieldSetEntity 中获取到FieldMetaEntity,调public void addAliasField(String tableName_fieldName,String alias)添加查询中使用的国际化这段别名。
tableName_fieldName: 表名与字段名组合,中间以点分隔  table.field
Alias: sql中对应的字段别名
 
18.如果多表联合查询,要取国际化值的表,必须取该表uuid字段,有重复uuid,自动添加别名,查询出来的uuid会在后面添加数据递增,如:uuid1,uuid2,第一个uuid不会变,如果要手动对重复的uuid取别名,也应按此规则进行,否则可能出现国际获取不到数据等情况
19.如果多表联合查询,其它字段重复与uuid重复类似,
多表联合查询,同一个表,同一个字段,使用两次,需要select * from () b 把查询主体括起来同时表必须设置别名
20.FeildSetEntity中获取Object时有两个方法:getValue(String fieldName)和getObject(String fieldName),区别在于,getValue(String fieldName)会把国际化字段值转成JSONObject对象,而getObject(String fieldName)只是返回基础数据
 
48.手机端JSON数据格式的调用
    语言编码获取
    String language_code=reqp.getOther().get(com.lx.base.core.config.CmnConst.SYSTEM_LANGUAGE_CODE ).toString();
    String client_type=reqp.getOther().get(com.lx.base.core.config.CmnConst.SYSTEM_CLIENT_TYPE ).toString();
    数据保存:
        baseDao.add(FieldSetEntityfse,String language_code);
        baseDao.add(FieldSetEntity fs,boolean subData,String language_code)
        baseDao.add(DataTableEntity fs,String language_code)
    数据修改:
        baseDao.update(FieldSetEntity fs,String language_code)
        baseDao.update(FieldSetEntity fs,boolean subData,String language_code)
        baseDao.update(DataTableEntity fs,String language_code)
       数据查询:
           FieldSetEntity listInternationDataTable(FieldSetEntity fs,String language_code )
           DataTableEntity listInternationDataTable(DataTableEntity dt,String language_code ) 
49.后端错误信息国际化
    1)错误信息枚举类注入,启动类中添加注入代码:
    DataPoolCacheImpl.getInstance()
            .appendErrorEnumClass("com.lx.base.core.config.ErrorCode")
            .appendErrorEnumClass("com.lx.base.module.sys.config.SystemCode")
            .appendErrorEnumClass("com.lx.base.module.sys.config.SystemErrorCode");
    2)特殊情况调用(AbstractBaseController.error()、BaseException.getMessage()、getMessageInfo()已实现)
    String message=DataPoolCacheImpl.getInstance().getErrorLanguageInternation(code, language_code);
    
50.高级参照数据返回规则
    1)所有单位高级参照数据 f1 全称 f2 短编码
    2)所有部门高级参照数据 f1 全称 f2 短编码
    3)所有岗位高级参照数据 f1 全称 
    4)所有岗位等级高级参照数据 f1 等级级别 f2 组名
    5)所有模块高级参照数据 f1 短编码
    6)所有功能高级参照数据 f1 短编码
    7)所有客户高级参照数据 f1 短编码
51.高级参照配置
    数据源表字段更改为后端接口,从DataPoolCacheImpl.getInstance().getCacheData("所有表信息");中获取所有表
    表别名:以 "a"+table_id为表别名
    重复关联表配置:SystemPromptService.getPromptRepetitionJoinTable() ,场景 公司 join 部门 、员工join下属
    关联类型 left join  , inner join , right join
    单表:
        数据源表多出别名
        字段:表别名 "."字段名
    多表
        is_multiple = 1
        relate_filter(多表关联条件)
        relate_type(关联类型)
        在选择了数据源表  a ,b, c , d表别名分别为 a1,a2,a3,a4
        关联类型= left join(根据业务需求定,目前只能选择1种关联方式)
        多表关联条件 = a1.uuid=a2.uuid,a3.uuid=a1.uuid,a2.uuid=a4.uuid 多个表的关联条件 用 "," 分隔,
        多表关联条件填写顺序应与表顺序对应不可颠倒
        每个表关联必须在对应的一组关联条件中用到   表别名"."字段
        错误示范:“a1.uuid=a2.uuid,a3.uuid=a1.uuid”  ,高级参照表关联个数与条件个数不匹配
52.功能权限验证
    必须配置mrbase_sys_function_buttons.api_url配置按钮对应后端接口地址,多个逗号分隔,不能含版本号,如:
    接口地址:/api/management/delete-user/v1 配置地址:/api/management/delete-user
    
53.数据操作权限验证
    主要针对单条数据的删 、改 、查操作,在删 、改 、查的相应接口调用
    必须设置mrbase_sys_datamodel_field.field_type,userid:存放人员的字段类型,orgUuid:存放组织机构的字段类型
    1)Controller接口层调用
    2)调法
        /**
         * 对单条数据进行操作的权限验证
         * @param tableName 表名
         * @param uuid uuid
         * @param type 验证类型 1=人员验证 2= 组织机构验证 3 两者都验证
         * @return
         */
        public boolean validDataPermission(String tableName,String uuid ,int type)
        /**
         * 对单条数据进行操作的权限验证
         * @param fs  上传数据,必须包含表名 uuid ,否一律通过
         * @param type 验证类型 1=人员验证 2= 级织机构验证 3 两者都验证  
         * @return
         */
        public boolean validDataPermission(FieldSetEntity fs ,int type)
        /**
         * 对单条数据进行操作的权限验证 ,特殊权限条件 ,不根据人 组织机构过滤
         * @param tableName 表名
         * @param uuid uuid
         * @param filter 特殊权限条件  
         * @return
         */
        public boolean validDataPermission(String tableName,String uuid,String filter)
        /**
         * 对单条数据进行操作的权限验证 ,特殊权限条件 ,不根据人 组织机构过滤
         * @param fs  上传数据,必须包含表名 uuid ,否一律通过
         * @param filter 特殊权限条件 
         * @return
         */
        public boolean validDataPermission(FieldSetEntity fs ,String filter)
    3)数据操作的权限验证,特殊条件调用示例
    if(!permissionService.validDataPermission(fse, "(client_uuid is null or client_uuid='') or client_uuid='"
    +SpringMVCContextHolder.getCurrentUser().getClient_uuid()+"'")) {
        SpringMVCContextHolder.getSystemLogger().error(SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getValue(),
                SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getText());
        return this.error(SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getValue(), SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getText());
    }
    
    4)按人员、组织机构验证数据权限调用示例
        必须设置mrbase_sys_datamodel_field.field_type,userid:存放人员的字段类型,orgUuid:存放组织机构的字段类型
        if(!permissionService.validDataPermission(fse,CoreConst.DATA_PERMISSION_VALID_TYPE_ALL)) {
            SpringMVCContextHolder.getSystemLogger().error(SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getValue(),
                    SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getText());
            return this.error(SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getValue(), SystemErrorCode.SYSTEM_NOT_OPER_PERMISSION.getText());
        }
54.业务代码逻辑处理
    规则是业务代码类必须注册成spring的bean,被调用的方法只能有一个FieldSetEntity参数,里面封装业务代码中需要的值,如:
  public void addBalance(FieldSetEntity fs)
  {
    this.logger.info("   ");
    this.staffBusinessService.addBalance(fs);
    this.logger.info(" ");
  }
  
54.消息生成
    /**
     * 所有应用服务生成消息调些方法去添加消息
     * 根据message.server.ip参数判断是否等于127.0.0.1
     * 是:则直接调writeUserMessage本机方法添加消息
     * 否:则调消息服务器接口添加消息
     * @param userids      消息接收人               必填
     * @param content      消息内容                 不必填
     * @param title        消息标题                 必填
     * @param send_user_id 消息发送人               必填
     * @param message_type 消息类型                 必填  
     * @param url           消息链接地址             不必填
     * @param source_table 业务数据表               不必填
     * @param source_uuid  业务数据表uuid           不必填
     * @param create_by    创建人       userid      必填 
     * @param is_send_mail 是否发送邮件 0:否 1:是   必填
     * @param is_send_sms  是否发送短信 0:否 1:是   必填
     */
    WebsocketMesssageServiceThread.getInstance().appendMessage(String ....); 
    
    //消息类型
    //表名常量定义
    public static final int MESSAGE_TOP_TYPE_SYSTEM =1; //"系统消息";    
    public static final int MESSAGE_TYPE_ANNOUNCEMENT =11; //"公告消息";
    
    public static final int MESSAGE_TOP_TYPE_TASK =2; //"任务消息";
    public static final int MESSAGE_TYPE_APPROVE =21; //"待办消息";        
    public static final int MESSAGE_TYPE_COORDINATION =22; //"协同消息";
    public static final int MESSAGE_TYPE_TASK = 23;// "任务模块消息";
 
    public static final int MESSAGE_TOP_TYPE_WARNING =3; //"预警消息";
    public static final int MESSAGE_TYPE_WARNING =31; //"预警消息";
    
55.子表排序规则,中括号内表示子表排序 放到orderby参数中 
String s="main_field1,main_field2,{sub_table1:sub_table1_field1 desc,sub_table1_field2},{sub_table2:sub_table2_field1 desc,sub_table2_field2}"
56.错误信息中的动态变量替换
替则使用{}把变量名括起来,此变量名将在Exception中获取:DATA_VERIFY_UNIQUE_ERROR("数据不是唯一:{value}", ModuleEnum.CORE.getValue() + "097"),
示例:
    be.setMessagePara("fieldxxxx","未获取到登录Token信息");
    be.setMessagePara("fieldxxxx",fs.getString("field"));
"fieldxxxx"对应错误定义中的{fieldxxxx}
 
56.反射引用bean :com.product.core.util.ReflectUtil
    /**
     * 
     * @param beanName 被代理对像bean 名称
     * @param methodName 方法名称
     * @param objects  参数
     * @return
     * @throws BaseException
     */
    public static  Object invoke(String beanName,String methodName,Object[] objects) throws BaseException
 
57.产生消息的表,必须在对应表的produce_msg字段中值为1
 
58.自动发起流程
    com.lx.tool.flow.service.FlowService#autoSendFlow
 
    描述:
        (1)service方法,非接口方法
        (2)根据传入的参数,自动发起流程,创建流程的第一步,直接到【开始】环节
 
    传入参数:fse
        {
            "type_code": "5a1dd74e-5b69-479c-afa0-a7db3e7fd6b2",
            "~table~": "lx_oa_conference_apply",
            "accepters": "376",
            "uuid": "5aadc03d-6ae3-470c-8507-4aaf660d9495",
            "flow_title": "6c测试自动发起流程"
        }
 
    参数描述:
        (1)type_code:类型uuid,类型唯一识别
        (2)~table~:业务表名
        (3)accepters:接收人,只能为一个
        (4)uuid:业务表uuid
        (5)flow_title:流程标题
59.产中打包部署
    jar部署:打开工程的pom.mxl,右键->Run as -> Maven install->进入工程目录->target目录->copy 把完包的工程jar,放到服务器的运行目录下的lib目录下(例如200上:D:\LXServer\product-server\lib)
    前端文件部署:进入lx-web并运行packed.bat,重新生成dist目录->进入dist目录copy除baseUrl.js以外的所有文件,放到服务器的运行目录下的web目录下。
    重启(运行桌面快捷键)
    
60.分页查询sql
    select  '6973' as staff_uuid  这种没有from的语句,要添加 from dual,否则分页查询会出错
 
61.查询单条记录,getFieldSet... 与 getFieldSetEntity...的区别: 前面方法在没有查到数据时返回不为空,后面方法在没有查到数据时返回null
 
62.配置报表
    假设过滤条件为"start_time>=('2021-12-01 00:00:00','%Y-%m-%d %H:%i:%s')"
    {$$} 类型为0,只取值,即为"2021-12-01 00:00:00"
    {^^} 类型为1,取除开字段外的所有内容,即为">=('2021-12-01 00:00:00','%Y-%m-%d %H:%i:%s')"
    {&&} 类型为2,取所有内容,包含字段,即为"start_time>=('2021-12-01 00:00:00','%Y-%m-%d %H:%i:%s')"
    [[]] 若是根据上面的所有方式替换之后依然存在任意一种,剔除包含在内的过滤条件