Lith 7 ay önce
ebeveyn
işleme
a5b96b25df
43 değiştirilmiş dosya ile 610 ekleme ve 632 silme
  1. 2 1
      Sqler.sln
  2. 94 129
      doc/AutoTemp.README.md
  3. 0 127
      doc/AutoTemp.md
  4. 0 14
      doc/ReleaseLog.md
  5. 14 0
      doc/ReleaseNotes.md
  6. 93 0
      doc/controllerConfig.js
  7. 54 0
      doc/infoGet.README.md
  8. 46 0
      src/Sqler/Data/Sqler_DataEditor_schema.ControllerConfig.json
  9. 1 1
      src/Sqler/Module/Sqler/Controllers/SqlBackup/MySqlBackupController.cs
  10. 1 1
      src/Sqler/Module/Sqler/Controllers/SqlBackup/SqlServerBackupController.cs
  11. 5 30
      src/Sqler/Module/Sqler/Logical/DataEditor/GridManage/GridManageDataProvider.cs
  12. 4 1
      src/Sqler/Module/Sqler/Logical/DataEditor/GridManage/GridService.cs
  13. 5 1
      src/Sqler/Module/Sqler/Logical/DataEditor/TableSchemaEntity.cs
  14. 12 0
      src/Sqler/Module/Sqler/Logical/Settings.cs
  15. 3 3
      src/Sqler/Module/Sqler/Logical/SqlBackup/MySqlBackup/ConfigRepository.cs
  16. 4 4
      src/Sqler/Module/Sqler/Logical/SqlBackup/SqlServerBackup/ConfigRepository.cs
  17. 2 2
      src/Sqler/Module/Sqler/Logical/SqlRun/ConfigRepository.cs
  18. 2 2
      src/Sqler/Module/Sqler/Logical/SqlVersion/ConfigRepository.cs
  19. 4 4
      src/Sqler/Module/Sqler/Logical/SqlVersion/Entity/sqler_version.cs
  20. 1 1
      src/Sqler/Module/Sqler/Logical/SqlVersion/ModuleRepository.cs
  21. 4 4
      src/Sqler/Module/Sqler/Logical/SqlVersion/SqlCodeRepository.cs
  22. 11 0
      src/Sqler/Sqler.csproj
  23. 33 36
      src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.Controller.js
  24. 42 29
      src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.Field.js
  25. 7 7
      src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.dataProvider.LocalStorageProvider.js
  26. 14 4
      src/Sqler/wwwroot/Scripts/autoTemp/item.html
  27. 0 3
      src/Sqler/wwwroot/Scripts/infoGet/infoGet.README.md
  28. 4 4
      src/Sqler/wwwroot/Scripts/infoGet/widget/demo/demo.html
  29. 10 10
      src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.js
  30. 3 3
      src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.widget.Text.js
  31. 3 5
      src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.widget.TextArea.js
  32. 4 3
      src/Sqler/wwwroot/sqler/index.html
  33. 34 0
      src/Vit.AutoTemp/AutoTempControllerConfig.FieldConfig.cs
  34. 23 0
      src/Vit.AutoTemp/AutoTempControllerConfig.ListConfig.cs
  35. 20 0
      src/Vit.AutoTemp/AutoTempControllerConfig.cs
  36. 21 172
      src/Vit.AutoTemp/AutoTempHelp.cs
  37. 7 9
      src/Vit.AutoTemp/DataProvider/DataProvider_Vitorm.cs
  38. 1 1
      src/Vit.AutoTemp/DataProvider/IDataProvider.cs
  39. 6 4
      src/Vit.AutoTemp/Demo/DemoDataProvider.cs
  40. 2 2
      src/Vit.AutoTemp/Demo/DemoRepository.cs
  41. 2 2
      src/Vit.AutoTemp/Repository/Extensions/IRepositoryExtensions.cs
  42. 11 13
      src/Vit.AutoTemp/Repository/RespositoryDataProvider.cs
  43. 1 0
      src/Vit.AutoTemp/Vit.AutoTemp.csproj

+ 2 - 1
Sqler.sln

@@ -14,7 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9568E206-5A8
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{02D7A308-F1D2-489D-84C6-2102C7F24C09}"
 	ProjectSection(SolutionItems) = preProject
-		doc\AutoTemp.md = doc\AutoTemp.md
+		doc\AutoTemp.README.md = doc\AutoTemp.README.md
+		doc\controllerConfig.js = doc\controllerConfig.js
 		README.md = README.md
 		doc\ReleaseLog.md = doc\ReleaseLog.md
 		doc\Sqler.md = doc\Sqler.md

+ 94 - 129
src/Sqler/wwwroot/Scripts/autoTemp/AutoTemp.README.md → doc/AutoTemp.README.md

@@ -1,129 +1,94 @@
-autoTemp 2.0.2(2022-02-10)
-
-可通过修改数据库字段的注释 来配置字段控件属性。如:
- 
-    [fieldIgnore]        忽略当前字段
-    [idField]            手动指定当前列为id列,默认为数据库主键
-	[field:{path}=value] 直接把值设置到field中,path可以为多级路径,如:[field:title=登录名]
-    [field:title=登录名]     字段的title为登录名,即标题显示登录名
-    [field:visiable=false]   字段不可见
-    [field:editable=false]   字段不可编辑
-    [field:list_width=200]   列表页中此字段的宽度为200
-	[field:field=name]       字段的field为name,同时为ig-id的值
-	[field:ig-class=TextArea]字段的ig-class为 TextArea,不指定则为Text
-    [field:ig-param={height:100,width:100}]    ig-param的值,一般为对象
-
-
-    树形列表:  必须同时指定pid列和treeField列,否则作为普通列表数据展示
-    [pidField]          当前列为pid
-    [treeField]         列表页中当前列作为树形展示
- 
-    [rootPidValue:0]    树控件根节点的pid的值,默认为0,在任一列的注释中指定皆可
-
-
-    列表页数据筛选条件:  同一字段可指定多个筛选条件
-    [filter:开始时间,=]   当前列作为筛选条件,筛选条件名称为开始时间(若不指定则为当前列title),筛选方式为"="
-    
-	[controller:path=value] 直接把值设置到controllerConfig中,path可以为多级路径,如:[controller:permit.delete=false]
-	[controller:list.title=SqlText] 设置list页面标题为SqlText
-
- 
-
-	设置不可删除(其他同理: insert、update、show、delete)
-		[controller:permit.delete=false]
-
-	设置list页面rowButtons:
-		[controller:list.rowButtons=[{text:'查看id',handler:'function(callback,id){  callback();alert(id); }' }]] 
-									
-
-
-field:
-{ 'ig-class': 'TextArea', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200 ,visiable:false,editable:false  }
-
-filter:
- { field: 'name', title: '装修商',filterOpt:'=' }
-
-
- 注释:
-
- 1.值中若出现中括号,可用以下转义。
- [  \x5B --- 左中括号  
- ]  \x5D --- 右中括号  
-
-
- 2.xml转义符号
-  <     &lt;	
-  >		&gt;	
-  &		&amp;	
-  '		&apos;	
-  "		&quot;	
-  空格  &nbsp;	
-
-
-
-
-
-	demo:
-	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider
-    http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider&tree=false
-
-
-	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_list/{action}
-	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_repository_list/{action}
-	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_tree/{action}
-
-
-
-
-
-
-var controllerConfig = {
-       dependency: {
-	    css: [],
-	    js: []
-	},
-
-	/* 添加、修改、查看、删除 等权限,可不指定。 默认值均为true  */
-	'//permit': {
-	    insert: false,
-	    update: false,
-	    show: false,
-	    delete: false
-	},
-
-	idField: 'id',
-	pidField: 'pid',
-	//treeField: 'name',
-	rootPidValue: '0',
-
-	list: {
-	    title: 'autoTemp-demo',
-	    buttons: [
-		{ text: '执行js', handler: 'function(callback){  setTimeout(callback,5000); }' },
-		//{ text: '调用接口', ajax: { type: 'GET', url: '/autoTemp/demo_list/getConfig' } }
-	    ],
-	    rowButtons: [
-		{ text: '查看id', handler: 'function(callback,id){  callback();alert(id); }' },
-		//{ text: '调用接口', ajax: { type: 'GET', url: '/autoTemp/{template}/getConfig?name={id}' } }
-	    ]
-	},
-
-
-	fields: [
-	    { 'ig-class': 'Text', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200, editable: false },
-	    { 'ig-class': 'Text', field: 'sex', title: '性别', list_width: 80, visiable: false },
-	    { 'ig-class': 'TextArea', field: 'random', title: 'random', list_width: 150, 'ig-param': {height:300} },
-	    { 'ig-class': 'Text', field: 'random2', title: 'random2', list_width: 150 }
-	],
-
-	filterFields: [
-	    { 'ig-class': 'Text', field: 'name', title: '装修商', filterOpt: 'Contains' },
-	    { 'ig-class': 'Text', field: 'sex', title: '性别' },
-	    { 'ig-class': 'Text', field: 'random', title: 'random' }
-	]
-
-    };
-
-
-
-
+# autoTemp
+
+
+## url
+        list:       list.html?template=tempDemo1
+
+        show:       item.html?template=tempDemo1&mode=show&id=12
+        update:     item.html?template=tempDemo1&mode=update&id=12
+        disable:    item.html?template=tempDemo1&mode=disable&id=12
+        insert:
+                    item.html?template=tempDemo1&mode=insert
+                    item.html?template=tempDemo1&mode=insert&pid=12   (tree)
+
+
+
+
+
+
+
+可通过修改数据库字段的注释 来配置字段控件属性。如:
+ 
+    [fieldIgnore]        忽略当前字段
+    [idField]            手动指定当前列为id列,默认为数据库主键
+	[field:{path}=value] 直接把值设置到field中,path可以为多级路径,如:[field:title=登录名]
+    [field:title=登录名]     字段的title为登录名,即标题显示登录名
+    [field:visible=false]   字段不可见
+    [field:editable=false]   字段不可编辑
+    [field:list_width=200]   列表页中此字段的宽度为200
+	[field:field=name]       字段的field为name,同时为ig_id的值
+	[field:ig_class=TextArea]字段的ig_class为 TextArea,不指定则为Text
+    [field:ig_param={height:100,width:100}]    ig_param的值,一般为对象
+
+
+    树形列表:  必须同时指定pid列和treeField列,否则作为普通列表数据展示
+    [pidField]          当前列为pid
+    [treeField]         列表页中当前列作为树形展示
+ 
+    [rootPidValue:0]    树控件根节点的pid的值,默认为0,在任一列的注释中指定皆可
+
+
+    列表页数据筛选条件:  同一字段可指定多个筛选条件
+    [filter:开始时间,=]   当前列作为筛选条件,筛选条件名称为开始时间(若不指定则为当前列title),筛选方式为"="
+    
+	[controller:path=value] 直接把值设置到controllerConfig中,path可以为多级路径,如:[controller:permit.delete=false]
+	[controller:list.title=SqlText] 设置list页面标题为SqlText
+
+ 
+
+	设置不可删除(其他同理: insert、update、show、delete)
+		[controller:permit.delete=false]
+
+	设置list页面rowButtons:
+		[controller:list.rowButtons=&#91;{text:'查看id',handler:'function(callback,id){  callback();alert(id); }' }&#93;] 
+									
+
+
+field:
+{ 'ig_class': 'TextArea', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200 ,visible:false,editable:false  }
+
+filter:
+ { field: 'name', title: '装修商',filterOpt:'=' }
+
+
+ 注释:
+
+ 1.值中若出现中括号,可用以下转义。
+ [  \x5B --- 左中括号  
+ ]  \x5D --- 右中括号  
+
+
+ 2.xml转义符号
+  <     &lt;	
+  >		&gt;	
+  &		&amp;	
+  '		&apos;	
+  "		&quot;	
+  空格  &nbsp;	
+
+
+
+
+
+	demo:
+	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider
+    http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider&tree=false
+
+
+	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_list/{action}
+	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_repository_list/{action}
+	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?apiRoute=/autoTemp/data/demo_tree/{action}
+
+
+
+	 

+ 0 - 127
doc/AutoTemp.md

@@ -1,127 +0,0 @@
-可通过修改数据库字段的注释 来配置字段控件属性。如:
- 
-    [fieldIgnore]        忽略当前字段
-    [idField]            手动指定当前列为id列,默认为数据库主键
-	[field:{path}=value] 直接把值设置到field中,path可以为多级路径,如:[field:title=登录名]
-    [field:title=登录名]     字段的title为登录名,即标题显示登录名
-    [field:visiable=false]   字段不可见
-    [field:editable=false]   字段不可编辑
-    [field:list_width=200]   列表页中此字段的宽度为200
-	[field:field=name]       字段的field为name,同时为ig-id的值
-	[field:ig-class=TextArea]字段的ig-class为 TextArea,不指定则为Text
-    [field:ig-param={height:100,width:100}]    ig-param的值,一般为对象
-
-
-    树形列表:  必须同时指定pid列和treeField列,否则作为普通列表数据展示
-    [pidField]          当前列为pid
-    [treeField]         列表页中当前列作为树形展示
- 
-    [rootPidValue:0]    树控件根节点的pid的值,默认为0,在任一列的注释中指定皆可
-
-
-    列表页数据筛选条件:  同一字段可指定多个筛选条件
-    [filter:开始时间,=]   当前列作为筛选条件,筛选条件名称为开始时间(若不指定则为当前列title),筛选方式为"="
-    
-	[controller:path=value] 直接把值设置到controllerConfig中,path可以为多级路径,如:[controller:permit.delete=false]
-	[controller:list.title=SqlText] 设置list页面标题为SqlText
-
- 
-
-	设置不可删除(其他同理: insert、update、show、delete)
-		[controller:permit.delete=false]
-
-	设置list页面rowButtons:
-		[controller:list.rowButtons=&#91;{text:'查看id',handler:'function(callback,id){  callback();alert(id); }' }&#93;] 
-									
-
-
-field:
-{ 'ig-class': 'TextArea', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200 ,visiable:false,editable:false  }
-
-filter:
- { field: 'name', title: '装修商',filterOpt:'=' }
-
-
- 注释:
-
- 1.值中若出现中括号,可用以下转义。
- [  \x5B --- 左中括号  
- ]  \x5D --- 右中括号  
-
-
- 2.xml转义符号
-  <     &lt;	
-  >		&gt;	
-  &		&amp;	
-  '		&apos;	
-  "		&quot;	
-  空格  &nbsp;	
-
-
-
-
-
-	demo:
-	http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider
-    http://localhost:4570/autoTemp/Scripts/autoTemp/list.html?dataProvider=LocalStorageProvider&tree=false
-
-
-
-
-
-
-
-
-
-
-
-var controllerConfig = {
-       dependency: {
-	    css: [],
-	    js: []
-	},
-
-	/* 添加、修改、查看、删除 等权限,可不指定。 默认值均为true  */
-	'//permit': {
-	    insert: false,
-	    update: false,
-	    show: false,
-	    delete: false
-	},
-
-	idField: 'id',
-	pidField: 'pid',
-	//treeField: 'name',
-	rootPidValue: '0',
-
-	list: {
-	    title: 'autoTemp-demo',
-	    buttons: [
-		{ text: '执行js', handler: 'function(callback){  setTimeout(callback,5000); }' },
-		//{ text: '调用接口', ajax: { type: 'GET', url: '/autoTemp/demo_list/getConfig' } }
-	    ],
-	    rowButtons: [
-		{ text: '查看id', handler: 'function(callback,id){  callback();alert(id); }' },
-		//{ text: '调用接口', ajax: { type: 'GET', url: '/autoTemp/{template}/getConfig?name={id}' } }
-	    ]
-	},
-
-
-	fields: [
-	    { 'ig-class': 'Text', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200, editable: false },
-	    { 'ig-class': 'Text', field: 'sex', title: '性别', list_width: 80, visiable: false },
-	    { 'ig-class': 'TextArea', field: 'random', title: 'random', list_width: 150, 'ig-param': {height:300} },
-	    { 'ig-class': 'Text', field: 'random2', title: 'random2', list_width: 150 }
-	],
-
-	filterFields: [
-	    { 'ig-class': 'Text', field: 'name', title: '装修商', filterOpt: 'Contains' },
-	    { 'ig-class': 'Text', field: 'sex', title: '性别' },
-	    { 'ig-class': 'Text', field: 'random', title: 'random' }
-	]
-
-    };
-
-
-
-

+ 0 - 14
doc/ReleaseLog.md

@@ -1,14 +0,0 @@
-# Sqler ReleaseLog
-
-
------------------------
-# 4.1.0
-
-
-
-
-
------------------------
-# 3.0.10
-- fix bug: --set not work in console
-- In Sql Server, support import/export Geometry type data

+ 14 - 0
doc/ReleaseNotes.md

@@ -0,0 +1,14 @@
+# Sqler ReleaseNotes
+
+
+-----------------------
+# 4.1.0
+
+
+QueryBuilder https://gitcode.com/gh_mirrors/jq/jQuery-QueryBuilder/overview?utm_source=artical_gitcode&index=bottom&type=card&webUrl
+
+
+-----------------------
+# 3.0.10
+- fix bug: --set not work in console
+- In Sql Server, support import/export Geometry type data

+ 93 - 0
doc/controllerConfig.js

@@ -0,0 +1,93 @@
+var controllerConfig = {
+
+    //"dependency": {
+    //    "css": [],
+    //    "js": []
+    //},
+
+    ///* 添加、修改、查看、删除 等权限,可不指定。 默认值均为true  */
+    //"//permit": {
+    //    "insert": false,
+    //    "update": false,
+    //    "show": false,
+    //    "delete": false
+    //},
+
+    "idField": "id",
+    "pidField": "pid",
+    "treeField": 'name',
+    "rootPidValue": "0",
+
+    "listConfig": {
+        "title": "autoTemp-demo",
+        "listButtons": [
+            {
+                "title": "执行js",
+                "jsHandler": "(sender)=>{ sender.progressStart(sender.title); setTimeout(sender.progressStop,5000); }" // sender: { ...button,  progressStart,progressStop }
+            },
+            {
+                "title": "调用接口",
+                "ajax": {
+                    "type": "GET",
+                    "url": "/autoTemp/demo_list/getConfig"
+                }
+            }
+        ],
+        "rowButtons": [
+            {
+                "title": "查看id",
+                "jsHandler": "(sender,id,row)=>{ sender.progressStart(sender.title); setTimeout(sender.progressStop,5000); }" // sender: { ...button,  progressStart,progressStop }
+            },
+            {
+                "title": "调用接口",
+                "ajax": {
+                    "type": "GET",
+                    "url": "/autoTemp/{template}/getConfig?name={id}"
+                }
+            }
+        ]
+    },
+
+
+    "fields": [
+        {
+            "field": "name", // db field
+            "title": "装修商",  // [optional] defaultValue is column.field
+
+            "visiable": false,
+            "editable": false,
+
+            "list_config": { 
+                "title": "<span title=\"装修商名称\">装修商</span>", // [optional] defaultValue is field.title
+                "width": 200,
+                "visiable": true,
+            },
+
+            "ig_attr": {
+                "ig_class": "Text",
+                "ig_param": { "width": 300 }
+            },
+
+        }
+    ],
+
+    //"filterFields_TODO": [
+    //    {
+    //        "ig_class": "Text",
+    //        "field": "name",
+    //        "title": "装修商",
+    //        "filterOpt": "Contains"
+    //    },
+    //    {
+    //        "ig_class": "Text",
+    //        "field": "sex",
+    //        "title": "性别"
+    //    },
+    //    {
+    //        "ig_class": "Text",
+    //        "field": "random",
+    //        "title": "random"
+    //    }
+    //]
+
+};

+ 54 - 0
doc/infoGet.README.md

@@ -0,0 +1,54 @@
+infoGet 2.0.2(2020-02-22)
+
+http://localhost:4570/infoGet/widget/demo/demo.html
+
+
+
+    IgAttr数据格式DEMO为:
+    var demo =  {      'ig_class': 'Text', 
+                       'ig_id': '名称',   
+                       'ig_param': {xx:'xx'} 
+                 };
+
+
+
+# 1 properties
+
+ig_param 数据格式:
+    width(int): 控件的宽度(默认150)。
+    height(int): 控件的高度(默认22)。
+    // required(string): 控件是否必填,  'true': 必填; 
+    // 'valueSetToDefaultIfInvalid':若为无效值则设为默认值;  其他(例如'false'):非必填(默认值)
+    // invalidMessage(string): 必填提示内容,为空则启用自定义提示消息 ,例如:'名字不允许为空!' 。
+    // disabled(bool): 控件是否禁用,禁用为"true",否则为"false"(默认false)。 
+    // desc(string): 控件描述。例如:'申请的金额总额,单位:万元。'。
+    // defaultValue: 默认值。如果为时间框,并且默认值为"getdate()",则初始时会转换成当前时间
+
+    otherParam: 其他自定义属性
+    {
+        type(string):文本框类型,可选值:"textbox","textarea","numberbox","password","datebox"(默认"textbox")。
+        dateFmt(string):时间格式,例如:"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd HH:mm","HH:mm:ss"
+        numberFmt(string):保留小数点位数.默认0
+    }
+
+
+#2 method
+
+    (#1)  init() 
+    (#2)  getValue(), setValue(value)  
+    (#3)  enable(), disable() 
+    (#4)  setMode(mode)  // show | edit
+    (#5)  resize(width, height)
+
+    // (#)  validate(howToReport) 
+    // (#)  getDefaultValue() 
+
+    // (#) event_Set(eventName, funcEvent) 
+    // (#) event_Add(eventName, funcEvent)
+
+
+
+#3 event
+
+    //(#1) onSetValue(callback) :  (value) => void;
+            在值变更时触发

+ 46 - 0
src/Sqler/Data/Sqler_DataEditor_schema.ControllerConfig.json

@@ -0,0 +1,46 @@
+{
+  "idField": "id",
+  "pidField": "pid",
+  "treeField": "name",
+
+  "fields": [
+    {
+      "field": "name",
+      "list_config": { "width": 200 },
+      "ig_attr": { "ig_class": "Text" }
+    },
+    {
+      "field": "templateName",
+      "list_config": { "width": 200 }
+    },
+    {
+      "field": "primary_key",
+      "list_config": { "width": 80 }
+    },
+    {
+      "field": "autoincrement",
+      "list_config": { "width": 100 },
+      "list_width": 100,
+      "editable": false
+    },
+    {
+
+      "field": "column_comment",
+      "list_config": { "width": 150 },
+      "ig_attr": { "ig_class": "TextArea" },
+      "editable": false
+    },
+    {
+      "field": "user_comment",
+      "list_config": { "width": 150 },
+      "ig_attr": { "ig_class": "TextArea" }
+    },
+    {
+      "field": "column_type",
+
+      "list_config": { "width": 100 },
+      "editable": false
+    }
+  ]
+
+}

+ 1 - 1
src/Sqler/Module/Sqler/Controllers/SqlBackup/MySqlBackupController.cs

@@ -77,7 +77,7 @@ namespace App.Module.Sqler.Controllers.SqlBackup
                 },
 
                 fields: [                  
-                    {  'ig-class': 'TextArea', field: 'fileName', title: '文件名', list_width: 400,editable:true },
+                    {  'ig_class': 'TextArea', field: 'fileName', title: '文件名', list_width: 400,editable:true },
                     { field: 'size', title: '大小(MB)', list_width: 80,editable:false },
                     { field: 'size_kb', title: '大小(KB)', list_width: 80,editable:false },
                     { field: 'createTime', title: '创建时间', list_width: 150,editable:false }

+ 1 - 1
src/Sqler/Module/Sqler/Controllers/SqlBackup/SqlServerBackupController.cs

@@ -76,7 +76,7 @@ namespace App.Module.Sqler.Controllers.SqlBackup
                 },
 
                 fields: [
-                    {  'ig-class': 'TextArea', field: 'fileName', title: '文件名', list_width: 400,editable:true },
+                    {  'ig_class': 'TextArea', field: 'fileName', title: '文件名', list_width: 400,editable:true },
                     { field: 'size', title: '大小(MB)', list_width: 80,editable:false },
                     { field: 'size_kb', title: '大小(KB)', list_width: 80,editable:false },
                     { field: 'createTime', title: '创建时间', list_width: 150,editable:false }

+ 5 - 30
src/Sqler/Module/Sqler/Logical/DataEditor/GridManage/GridManageDataProvider.cs

@@ -2,8 +2,10 @@
 
 using Sqler.Module.Sqler.Logical.DataEditor.GridManage;
 
+using Vit.AutoTemp;
 using Vit.AutoTemp.Repository;
 using Vit.Core.Module.Serialization;
+using Vit.Core.Util.Common;
 using Vit.Core.Util.ComponentModel.Data;
 using Vit.Core.Util.ComponentModel.SsError;
 using Vit.Linq;
@@ -18,39 +20,12 @@ namespace App.Module.Sqler.Logical.DataEditor.GridManage
     {
         public RespositoryDataProvider<Model> ToDataProvider()
         {
-            return new RespositoryDataProvider<Model>(this, templateName, GetControllerConfig());
+            var str = File.ReadAllText(CommonHelp.GetAbsPath("Data", "Sqler_DataEditor_schema.ControllerConfig.json"));
+            var controllerConfig = Json.Deserialize<AutoTempControllerConfig>(str);
+            return new RespositoryDataProvider<Model>(this, templateName, controllerConfig);
         }
 
         const string templateName = "Sqler_DataEditor_schema";
-        static JObject GetControllerConfig()
-        {
-            var data = @"{
-                idField: 'id',
-                pidField: 'pid',
-                treeField: 'name',
-
-                dependency: {
-                    css: [],
-                    js: []
-                },
- 
-                fields: [
-                    {  field: 'name', title: 'name', list_width: 200,editable:false },
-                    {  field: 'primary_key', title: 'primary_key', list_width: 80,editable:false },
-                    {  field: 'autoincrement', title: 'autoincrement', list_width: 100,editable:false },
-                    {  'ig-class':'TextArea', field: 'column_comment', title: 'column_comment', list_width: 150,editable:false },
-                    {  'ig-class':'TextArea', field: 'user_comment', title: 'user_comment', list_width: 150 },
-                    {  field: 'column_type', title: 'column_type', list_width: 100,editable:false }
-                ],
- 
-                 filterFields: [
-                    { field: 'name', title: 'name',filterOpt:'Contains' }
-                ]
-            }";
-            return Json.Deserialize<JObject>(data);
-        }
-
-
 
 
         IQueryable<Model> dataSource => GridService.models.AsQueryable();

+ 4 - 1
src/Sqler/Module/Sqler/Logical/DataEditor/GridManage/GridService.cs

@@ -96,7 +96,10 @@ namespace Sqler.Module.Sqler.Logical.DataEditor.GridManage
                 else
                 {
                     entity.tableName = model.name;
-                    Data.Update(entity);
+                    entity.templateName = model.templateName;
+
+                    Data.Delete(entity);
+                    Data.Add(entity);
 
                     return model;
                 }

+ 5 - 1
src/Sqler/Module/Sqler/Logical/DataEditor/TableSchemaEntity.cs

@@ -25,7 +25,10 @@ namespace Sqler.DataEditor.Config
         [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "text")]
         public string columns { get; set; }
 
-        public string ext { get; set; }
+
+        public string controlerConfig { get; set; }
+
+
 
         public List<Column> GetColumnSchemas()
         {
@@ -58,6 +61,7 @@ namespace Sqler.DataEditor.Config
                 col.pid = templateName;
                 col.id = templateName + "." + column_name;
                 col.name = column_name;
+                col.templateName= templateName;
 
                 return col;
             }

+ 12 - 0
src/Sqler/Module/Sqler/Logical/DataEditor/Settings.cs → src/Sqler/Module/Sqler/Logical/Settings.cs

@@ -1,5 +1,7 @@
 using Sqler.DataEditor.Config;
 
+using Vit.Core.Module.Serialization;
+
 using Vitorm;
 
 
@@ -23,11 +25,21 @@ namespace Sqler.Module.Sqler.Logical.DataEditor
             }
 
         }
+        public static void Set<T>(string key, T value)
+        {
+             Set(key, Json.Serialize(key));
+        }
+
         public static string Get(string key)
         {
             return Data.Get<SettingEntity>(key)?.value;
         }
 
+        public static T Get<T>(string key)
+        {
+            return Json.Deserialize<T>(Get(key));
+        }
+
 
     }
 }

+ 3 - 3
src/Sqler/Module/Sqler/Logical/SqlBackup/MySqlBackup/ConfigRepository.cs

@@ -57,7 +57,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.MySqlBackup
     {
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// [controller:permit.delete=false] 
         /// </summary>
         [Key]
@@ -68,7 +68,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.MySqlBackup
         /// <summary>
         /// 连接字符串
         /// [field:title=&lt;span title='数据库连接字符串'&gt;连接字符串&lt;/span&gt;]       
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public String ConnectionString { get; set; }
 
@@ -76,7 +76,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.MySqlBackup
         /// <summary>
         /// 数据库备份还原文件的所在文件夹。例:@"F:\\db"。若不指定则为 /Data/MySqlBackup
         /// [field:title=&lt;span title='数据库备份还原文件的文件夹路径。例:@"F:\\db"。若不指定则为 Data/MySqlBackup'&gt;备份路径&lt;/span&gt;]
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public String BackupPath { get; set; }
 

+ 4 - 4
src/Sqler/Module/Sqler/Logical/SqlBackup/SqlServerBackup/ConfigRepository.cs

@@ -57,7 +57,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.SqlServerBackup
     {
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// [controller:permit.delete=false] 
         /// </summary>
         [Key]
@@ -68,7 +68,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.SqlServerBackup
         /// <summary>
         /// Ms连接字符串
         /// [field:title=&lt;span title='SqlServer数据库连接字符串'&gt;Ms连接字符串&lt;/span&gt;]       
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public String ConnectionString { get; set; }
 
@@ -76,7 +76,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.SqlServerBackup
         /// <summary>
         /// SqlServer数据库备份还原文件的所在文件夹。例:@"F:\\db"。若不指定则为 /Data/SqlServerBackup
         /// [field:title=&lt;span title='SqlServer数据库备份还原文件的文件夹路径。例:@"F:\\db"。若不指定则为 Data/SqlServerBackup'&gt;Ms备份路径&lt;/span&gt;]
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public String BackupPath { get; set; }
 
@@ -85,7 +85,7 @@ namespace App.Module.Sqler.Logical.SqlBackup.SqlServerBackup
         /// SqlServer数据库文件所在文件夹。例:"..\DataBaseFile" 、 "C:\Program Files (x86)\Microsoft SQL Server\MSSQL\data"。若不指定则为系统默认路径
         /// 
         /// [field:title=&lt;span title='SqlServer数据库文件所在文件夹。例:"..\DataBaseFile" 、 "C:\Program Files (x86)\Microsoft SQL Server\MSSQL\data"。若不指定则为系统默认路径'&gt;Ms数据库路径&lt;/span&gt;]
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public String MdfPath { get; set; }
 

+ 2 - 2
src/Sqler/Module/Sqler/Logical/SqlRun/ConfigRepository.cs

@@ -57,7 +57,7 @@ namespace App.Module.Sqler.Logical.SqlRun
     {
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// [controller:permit.delete=false] 
         /// </summary>
         [Key]
@@ -72,7 +72,7 @@ namespace App.Module.Sqler.Logical.SqlRun
 
 
         /// <summary>
-        /// 连接字符串[field:ig-class=TextArea]
+        /// 连接字符串[field:ig_class=TextArea]
         /// </summary>
         public String ConnectionString { get; set; }
 

+ 2 - 2
src/Sqler/Module/Sqler/Logical/SqlVersion/ConfigRepository.cs

@@ -45,7 +45,7 @@ namespace App.Module.Sqler.Logical.SqlVersion
     {
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// [controller:permit.delete=false] 
         /// </summary>
         [Key]
@@ -66,7 +66,7 @@ namespace App.Module.Sqler.Logical.SqlVersion
 
 
         /// <summary>
-        /// 连接字符串[field:ig-class=TextArea]
+        /// 连接字符串[field:ig_class=TextArea]
         /// </summary>
         public String connectionString { get; set; }
 

+ 4 - 4
src/Sqler/Module/Sqler/Logical/SqlVersion/Entity/sqler_version.cs

@@ -33,8 +33,8 @@ namespace App.Module.Sqler.Logical.SqlVersion.Entity
 
         /// <summary>
         /// 语句执行结果
-        /// [field:ig-class=TextArea]
-        /// [field:ig-param={height:250}]
+        /// [field:ig_class=TextArea]
+        /// [field:ig_param={height:250}]
         /// </summary>
         [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "ntext")]
         public string result { get; set; }
@@ -42,8 +42,8 @@ namespace App.Module.Sqler.Logical.SqlVersion.Entity
 
         /// <summary>
         /// sql语句
-        /// [field:ig-class=TextArea]
-        /// [field:ig-param={height:50}]
+        /// [field:ig_class=TextArea]
+        /// [field:ig_param={height:50}]
         /// </summary>
         [System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "ntext")]
         public string code { get; set; }

+ 1 - 1
src/Sqler/Module/Sqler/Logical/SqlVersion/ModuleRepository.cs

@@ -89,7 +89,7 @@ namespace App.Module.Sqler.Logical.SqlVersion
         public SqlCodeRepository repository { get; private set; }
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// 
         /// [controller:permit.update=false]
         /// [controller:permit.delete=false]

+ 4 - 4
src/Sqler/Module/Sqler/Logical/SqlVersion/SqlCodeRepository.cs

@@ -131,15 +131,15 @@ namespace App.Module.Sqler.Logical.SqlVersion
 
         /// <summary>
         /// sql语句
-        /// [field:ig-class=TextArea] 
-        /// [field:ig-param={height:200}]
+        /// [field:ig_class=TextArea] 
+        /// [field:ig_param={height:200}]
         /// </summary>
         public String code { get; set; }
 
         /// <summary>
         /// 说明
-        /// [field:ig-class=TextArea]       
-        /// [field:ig-param={height:50}]
+        /// [field:ig_class=TextArea]       
+        /// [field:ig_param={height:50}]
         /// </summary>
         public String comment { get; set; }
 

+ 11 - 0
src/Sqler/Sqler.csproj

@@ -40,6 +40,12 @@
             <CopyToOutputDirectory>Always</CopyToOutputDirectory>
         </Content>
 
+        <Content Update="Data\Sqler_DataEditor_schema.ControllerConfig.json">
+          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+          <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
+          <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+        </Content>
+
         <Content Update="Data\sqler.SqlVersion.table.json">
             <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
         </Content>
@@ -70,4 +76,9 @@
         </None>
     </ItemGroup>
 
+
+    <ItemGroup>
+      <Folder Include="Module\Sqler\Logical\Menu\" />
+    </ItemGroup>
+
 </Project>

+ 33 - 36
src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.Controller.js

@@ -43,23 +43,23 @@
 
         var gridConfig = {};
 
-        //(x.1)idField treeField
+        // #1 idField treeField
         gridConfig.idField = controllerConfig.idField;
         gridConfig.treeField = controllerConfig.treeField;
 
 
-        //(x.2)title
-        if (controllerConfig.list) {
-            gridConfig.title = controllerConfig.list.title;
+        // #2 title
+        if (controllerConfig.listConfig?.title) {
+            gridConfig.title = controllerConfig.listConfig.title;
         }
 
 
-        //(x.3)toolbar (from buttons)
-        if (controllerConfig.list && controllerConfig.list.buttons) {
+        // #3 toolbar (from listButtons)
+        if (controllerConfig.listConfig?.listButtons) {
 
             var toolbar = gridConfig.toolbar = [];
 
-            var buttons = controllerConfig.list.buttons;
+            var buttons = controllerConfig.listConfig?.listButtons;
             for (var t in buttons) {
                 buildButton(buttons[t]);
             }
@@ -69,25 +69,23 @@
                 toolbar.push({
                     text: button.text, handler: function () {
 
-                        //(x.1)执行js
-                        if (button.handler) {
-                            //button    {text:'执行js',    handler:'function(callback){  setTimeout(callback,5000); }'    },
-
-                            if (typeof (button.handler) == 'string') {
-                                button.handler = eval('(' + button.handler + ')');
+                        // ##1 jsHandler
+                        if (button.jsHandler) {
+                            if (typeof (button.jsHandler) == 'string') {
+                                button.handler = eval('(' + button.jsHandler + ')');
                             }
-                            theme.progressStart(button.text);
+                            theme.progressStart(button.title);
 
-                            button.handler(theme.progressStop);
+                            let arg = { ...button, progressStart: theme.progressStart, progressStop: theme.progressStop };
+                            button.handler(arg, null);
                             return;
                         }
 
 
-                        //(x.2)调用接口
+                        // ##2 ajax
                         if (button.ajax) {
-                            //button   {text:'调用接口',  ajax:{ type:'GET',url:'/autoTemp/{template}/getConfig'    }     }
 
-                            theme.confirm(button.text + '?', function () {
+                            theme.confirm(button.title + '?', function () {
 
                                 autoTemp.dataProvider.ajax({
                                     url: button.ajax.url,
@@ -112,33 +110,31 @@
         }
 
 
-        //(x.4)row button
-        if (controllerConfig.list && controllerConfig.list.rowButtons) {
-            var rowButtons = controllerConfig.list.rowButtons;
+        // #4 row buttons
+        if (controllerConfig.listConfig?.rowButtons) {
+            var rowButtons = controllerConfig.rowButtons.rowButtons;
             $.each(rowButtons, function (i, button) {
 
                 controller.addRowButton({
                     text: button.text,
                     onclick: function (id) {
-                        //(x.1)执行js
-                        if (button.handler) {
-                            //button   {text:'查看id',    handler:'function(callback,id){  callback();alert(id); }'    },
-
-                            if (typeof (button.handler) == 'string') {
-                                button.handler = eval('(' + button.handler + ')');
+                        // ##1 jsHandler
+                        if (button.jsHandler) {
+                            if (typeof (button.jsHandler) == 'string') {
+                                button.handler = eval('(' + button.jsHandler + ')');
                             }
+                            theme.progressStart(button.title);
 
-                            theme.progressStart(button.text);
-                            button.handler(theme.progressStop, id);
+                            let arg = { ...button, progressStart: theme.progressStart, progressStop:theme.progressStop };
+                            button.handler(arg, id, null);
                             return;
                         }
 
 
-                        //(x.2)调用接口
+                        // ##2 ajax
                         if (button.ajax) {
-                            //button   {text:'调用接口',  ajax:{ type:'GET',url:'/autoTemp/{template}/getConfig?name={id}'    }     }
 
-                            theme.confirm(button.text + '?', function () {
+                            theme.confirm(button.title + '?', function () {
 
                                 autoTemp.dataProvider.ajax({
                                     url: button.ajax.url.replace('{id}', id),
@@ -162,14 +158,14 @@
         }
 
 
-        //(x.5)columns
+        // #5 fields
         if (controller.atFields) {
             var atFields = controller.atFields;
             var frozenColumns = [
                 //{ field: 'ck', checkbox: true }
             ];
             var columns = [];
-            //(x.x.1)column
+            // ##1 column
             gridConfig.frozenColumns = [frozenColumns];
             gridConfig.columns = [columns];
             for (var t in atFields) {
@@ -178,7 +174,7 @@
                 if (item) columns.push(item);
             }
 
-            //(x.x.2)opt column
+            // ##2 opt column
             frozenColumns.push({
                 field: 'opt', title: '操作', width: 250, align: "center", formatter: function (value, row, index) {
                     return getOptHtml(row, controller);
@@ -293,7 +289,8 @@
             try {
                 var field = new autoTemp.Field(config);
                 atFields.push(field);
-            } catch (e) {
+            } catch (error) {
+                console.log(error);
             }
         }
         return atFields;

+ 42 - 29
src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.Field.js

@@ -10,17 +10,44 @@
 
 
     scope.Field = function (fieldConfig, controller) {
-        //   field 对应 ig-id
-        //  { field: 'name', title: '装修商', list_width: 200 ,visiable:false,editable:false ,'ig-class':'','ig-param':{}  }
+        //   field 对应 ig_id
+        //  { field: 'name', title: '装修商', list_width: 200 ,visible:false,editable:false ,'ig_class':'','ig_param':{}  }
 
         var self = this;
 
         self.config = fieldConfig;
 
+        // init default config
+        (() => {
+            let ig_attr = self.config?.ig_attr;
+            if (!ig_attr) self.config.ig_attr = ig_attr = {};
+
+
+            // ig_id
+            ig_attr.ig_id = self.config.field;
+
+            // ig_class
+            if (!ig_attr.ig_class) ig_attr.ig_class = 'Text';
+
+            // ig_param
+            var ig_param = ig_attr.ig_param;
+            if (typeof (ig_param) == 'string') {
+                try {
+                    ig_attr.ig_param = ig_param = eval('(' + ig_param + ')')
+                } catch (e) {
+                }
+            }
+            if (!ig_param) ig_attr.ig_param = ig_param = {};
+            if (self.config.editable == false) {
+                ig_param.disabled = true;
+            }
+
+        })();
+
 
 
         self.getVisiable = function () {
-            return self.config.visiable != false && self.config.visiable != 'false';
+            return self.config.visible != false && self.config.visible != 'false';
         }
 
 
@@ -49,18 +76,25 @@
 
 
         self.list_init = function () {
+
             if (!self.getVisiable()) {
                 return null;
             }
             //align: "center",
-            return { field: self.config.field, title: self.config.title, width: self.config.list_width || 80, formatter: outSpan, sortable: true };
+            return {
+                field: self.config.field,
+                title: self.config.list_config?.title || self.config.title || self.config.field,
+                width: self.config.list_config?.width || 80,
+                formatter: outSpan,
+                sortable: true,
+            };
         }
 
 
 
         function getIgWidget() {
             if (!arguments.callee.igWidget) {
-                arguments.callee.igWidget = infoGet.getWidgetByIgId(self.config.field);
+                arguments.callee.igWidget = infoGet.getWidgetByIgId(self.config.ig_attr.ig_id);
             }
             return arguments.callee.igWidget;
         }
@@ -69,39 +103,18 @@
             if (!self.getVisiable()) {
                 return '';
             }
+            let igAttr = self.config.ig_attr;
 
             var html = "<li><table><tr><td class='mtbTitle'>";
-            html += self.config.title;
+            html += self.config.title || self.config.field;
             html += "</td><td class='mtbValue' >";
 
-            //build ctrl
-            var igAttr = { 'ig-id': self.config.field, 'ig-class': (self.config['ig-class'] || 'Text') };
-
-            //ig-param
-            var igParam = null;
-            if (self.config['ig-param']) {
-                igParam = self.config['ig-param'];
-                if (typeof (igParam) == 'string') {
-                    try {
-                        igParam = eval('(' + igParam + ')')
-                    } catch (e) {
-                    }
-                }
-            }
-
-            if (!self.getEditable()) {
-                if (!igParam) igParam = {};
-                igParam.disabled = true;
-            }
-
-            if (igParam) {
-                igAttr['ig-param'] = igParam;
-            }
 
             html += infoGet.buildHtml(igAttr);
             //html += "<input type='text'  id='" + domId+ "' class='ctl' />";
 
             html += "</td></tr></table></li>";
+
             return html;
         }
 

+ 7 - 7
src/Sqler/wwwroot/Scripts/autoTemp/autoTemp.dataProvider.LocalStorageProvider.js

@@ -78,16 +78,16 @@
 
 
                 fields: [
-                    { 'ig-class': 'Text', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200, editable: false },
-                    { 'ig-class': 'Text', field: 'sex', title: '性别', list_width: 80, visiable: false },
-                    { 'ig-class': 'TextArea', field: 'random', title: 'random', list_width: 150, 'ig-param': {height:300} },
-                    { 'ig-class': 'Text', field: 'random2', title: 'random2', list_width: 150 }
+                    { 'ig_class': 'Text', field: 'name', title: '<span title="装修商名称">装修商</span>', list_width: 200, editable: false },
+                    { 'ig_class': 'Text', field: 'sex', title: '性别', list_width: 80, visible: false },
+                    { 'ig_class': 'TextArea', field: 'random', title: 'random', list_width: 150, 'ig_param': {height:300} },
+                    { 'ig_class': 'Text', field: 'random2', title: 'random2', list_width: 150 }
                 ],
 
                 filterFields: [
-                    { 'ig-class': 'Text', field: 'name', title: '装修商', filterOpt: 'Contains' },
-                    { 'ig-class': 'Text', field: 'sex', title: '性别' },
-                    { 'ig-class': 'Text', field: 'random', title: 'random' }
+                    { 'ig_class': 'Text', field: 'name', title: '装修商', filterOpt: 'Contains' },
+                    { 'ig_class': 'Text', field: 'sex', title: '性别' },
+                    { 'ig_class': 'Text', field: 'random', title: 'random' }
                 ]
 
             };

+ 14 - 4
src/Sqler/wwwroot/Scripts/autoTemp/item.html

@@ -32,10 +32,19 @@
     <script type="text/javascript" src="../infoGet/widget/infoGet.widget.TextArea.js"></script>
 
     <script type="text/javascript">
-
-        //insert  update show disable(禁用控件 的编辑模式)
-
-        var dependencyCount = 0;
+ 
+        /* url
+
+        show:       item.html?template=tempDemo1&mode=show&id=12
+        update:     item.html?template=tempDemo1&mode=update&id=12
+        disable:    item.html?template=tempDemo1&mode=disable&id=12
+        insert:
+                    item.html?template=tempDemo1&mode=insert
+                    item.html?template=tempDemo1&mode=insert&pid=12   (tree)
+        
+        */
+
+        // insert | update | show | disable(禁用控件 的编辑模式)
         var mode = document.url_GetCurArg('mode') || 'update';
         var id = document.url_GetCurArg('id');
         var pid = document.url_GetCurArg('pid');
@@ -43,6 +52,7 @@
         var controllerConfig;
         var atFields;
         var model = {};
+        var dependencyCount = 0;
 
         var controller;
         var dataProvider = autoTemp.createDataPrivider();

+ 0 - 3
src/Sqler/wwwroot/Scripts/infoGet/infoGet.README.md

@@ -1,3 +0,0 @@
-infoGet 2.0.2(2020-02-22)
-
-http://localhost:4570/infoGet/widget/demo/demo.html

+ 4 - 4
src/Sqler/wwwroot/Scripts/infoGet/widget/demo/demo.html

@@ -20,9 +20,9 @@
         $(function () {
 
 
-            var w1 = new infoGet.widget.Text($('*[ig-id=txt]'));
+            var w1 = new infoGet.widget.Text($('*[ig_id=txt]'));
 
-            var w2 = new infoGet.widget.TextArea($('*[ig-id=TextArea]'));
+            var w2 = new infoGet.widget.TextArea($('*[ig_id=TextArea]'));
 
             widget = w2;
 
@@ -40,8 +40,8 @@
     </script>
 </head>
 <body>
-    单行文本:<input type="text" ig-class='Text'  ig-id='Text' style="width:150px;height:22px;" /> <br />
-    多行文本:<textarea cols="40" rows="3" ig-class='TextArea' ig-id='TextArea' ></textarea> <br />
+    单行文本:<input type="text" ig_class='Text'  ig_id='Text' style="width:150px;height:22px;" /> <br />
+    多行文本:<textarea cols="40" rows="3" ig_class='TextArea' ig_id='TextArea' ></textarea> <br />
 
     <p>&nbsp;</p>
 

+ 10 - 10
src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.js

@@ -9,8 +9,8 @@
 
 /* 
     IgAttr数据格式DEMO为:
-    var demo =  {      'ig-class': 'Text', 
-                       'ig-id': '名称',   'ig-param': {xx:'xx'}    };
+    var demo =  {      'ig_class': 'Text', 
+                       'ig_id': '名称',   'ig_param': {xx:'xx'}    };
 
  
 */
@@ -52,7 +52,7 @@
      
 
     //infoGet.getElems = function () {
-    //    return $('*[ig-class]');
+    //    return $('*[ig_class]');
     //};
 
 
@@ -78,7 +78,7 @@
         if (!widget) {
             var je = $(elem);
             var igAttr = getIgAttrFromJe(je);
-            var className = igAttr['ig-class'];
+            var className = igAttr['ig_class'];
             with (infoGet.widget) {
                 var widgetClass = eval(className);
             }
@@ -93,13 +93,13 @@
 
     //通过igId获取控件
     infoGet.getWidgetByIgId = function (igId) { 
-        return infoGet.getWidget ($('*[ig-id="' + (""+igId).toJsStr() + '"]')[0]);
+        return infoGet.getWidget ($('*[ig_id="' + (""+igId).toJsStr() + '"]')[0]);
     };
 
 
 
     infoGet.parse = function (jqParent) {
-        var jqElems = (jqParent || $(document)).find('*[ig-class]');
+        var jqElems = (jqParent || $(document)).find('*[ig_class]');
 
         jqElems.each(function (i, elem) {
             infoGet.getWidget(elem);
@@ -109,7 +109,7 @@
 
     infoGet.buildHtml = function (igAttr) {
 
-        var className = igAttr['ig-class'];
+        var className = igAttr['ig_class'];
         with (infoGet.widget) {
             var widgetClass = eval(className);
         }
@@ -131,9 +131,9 @@
         }
 
         var igAttr = {
-            'ig-class': je.attr('ig-class'),
-            'ig-id': je.attr('ig-id'),
-            'ig-param': getAttrEval(je, 'ig-param')            
+            'ig_class': je.attr('ig_class'),
+            'ig_id': je.attr('ig_id'),
+            'ig_param': getAttrEval(je, 'ig_param')            
         };    
          
         return igAttr;

+ 3 - 3
src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.widget.Text.js

@@ -11,7 +11,7 @@
 
 /*
     (1).初始化属性
-    ig-param 数据格式:
+    ig_param 数据格式:
         width(int): 控件的宽度(默认150)。
         height(int): 控件的高度(默认22)。
       
@@ -71,7 +71,7 @@ if (!infoGet.widget) infoGet.widget = {};
 
         self.init = function () {
             jeEdit.addClass('ig_mode_edit').addClass('ig_Text');
-            var igParam = igAttr['ig-param'];
+            var igParam = igAttr['ig_param'];
             if (!igParam) return;
             if (igParam.disabled === true) {
                 self.disable();
@@ -170,7 +170,7 @@ if (!infoGet.widget) infoGet.widget = {};
 
 
         //html += ' style="width:' + width + 'px;height:' + height + 'px;" ';
-        var igParam = igAttr['ig-param'];
+        var igParam = igAttr['ig_param'];
         if (igParam) {
             var style = '';
             if (igParam.width) style += 'width:' + igParam.width + 'px;';

+ 3 - 5
src/Sqler/wwwroot/Scripts/infoGet/widget/infoGet.widget.TextArea.js

@@ -11,7 +11,7 @@
 
 /*
     (1).初始化属性
-    ig-param 数据格式:
+    ig_param 数据格式:
         width(int): 控件的宽度(默认150)。
         height(int): 控件的高度(默认22)。
         required(string): 控件是否必填,  'true': 必填; 'valueSetToDefaultIfInvalid':若为无效值则设为默认值;  其他(例如'false'):非必填(默认值)
@@ -20,8 +20,6 @@
         desc(string): 控件描述。例如:'申请的金额总额,单位:万元。'。
         value(string or other): 默认值。如果为时间框,并且默认值为"getdate()",则初始时会转换成当前时间
 
-        builderId: 构建器的id,用于再次构建时定位构建器    
-
         otherParam: 其他自定义属性存放。
         {
             type(string):文本框类型,可选值:"textbox","textarea","numberbox","password","datebox"(默认"textbox")。
@@ -80,7 +78,7 @@ if (!infoGet.widget) infoGet.widget = {};
 
         self.init = function () {
             jeEdit.addClass('ig_mode_edit').addClass('ig_TextArea');
-            var igParam = igAttr['ig-param'];
+            var igParam = igAttr['ig_param'];
             if (!igParam) return;
             if (igParam.disabled === true) {
                 self.disable();
@@ -180,7 +178,7 @@ if (!infoGet.widget) infoGet.widget = {};
  
 
         //html += ' style="width:' + width + 'px;height:' + height + 'px;" ';
-        var igParam = igAttr['ig-param'];
+        var igParam = igAttr['ig_param'];
         if (igParam) {
             var style = '';
             if (igParam.width) style += 'width:' + igParam.width + 'px;';

+ 4 - 3
src/Sqler/wwwroot/sqler/index.html

@@ -212,7 +212,8 @@
                     },
                     {
                         "attributes": {
-                            "url": "/sqler/DataEditor/index.html"
+                            "url": "/sqler/DataEditor/index.html",
+                            "target":"blank"
                         },
                         "text": "<img  mid='" + Math.random() + "' />DataEditor",
                         "iconCls": "icon-null"
@@ -277,8 +278,8 @@
                             var url = node.attributes.url;
                             if (!url) return;
                             switch (node.attributes.target) {
-                                case 1: window.top.location = url; break;
-                                case 2: window.open(url); break;
+                                case 'jump': window.top.location = url; break;
+                                case 'blank': window.open(url); break;
                                 default: addTab(node.text, url);
                             }
                         },

+ 34 - 0
src/Vit.AutoTemp/AutoTempControllerConfig.FieldConfig.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Vit.AutoTemp
+{
+    public partial class AutoTempControllerConfig
+    {
+        public class FieldConfig
+        {
+            public string field;
+            public string title;
+
+            public bool? visible;
+            public bool? editable;
+
+            public ListConfig list_config;
+            public IgAttr ig_attr;
+
+            public class ListConfig
+            {
+                public string title;
+                public int? width;
+                public bool? visible;
+            }
+
+            public class IgAttr
+            {
+                public string ig_class;
+                public Dictionary<string,object> ig_param;
+            }
+        }
+    }
+}

+ 23 - 0
src/Vit.AutoTemp/AutoTempControllerConfig.ListConfig.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Vit.AutoTemp
+{
+    public partial class AutoTempControllerConfig
+    {
+        public class ListConfig
+        {
+            public string title;
+
+            public List<Button> listButtons;
+            public List<Button> rowButtons;
+
+            public class Button
+            {
+                public string title;
+                public string jsHandler;
+            }
+        }
+    }
+}

+ 20 - 0
src/Vit.AutoTemp/AutoTempControllerConfig.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+
+
+namespace Vit.AutoTemp
+{
+    public partial class AutoTempControllerConfig
+    {
+        public string idField;
+        public string pidField;
+        public string treeField;
+        public string rootPidValue;
+
+        public ListConfig listConfig;
+
+        public List<FieldConfig> fields;
+    }
+}

+ 21 - 172
src/Vit.AutoTemp/AutoTempHelp.cs

@@ -15,6 +15,8 @@ using Vit.Extensions;
 using Vit.Extensions.Newtonsoft_Extensions;
 using Vit.Extensions.Serialize_Extensions;
 
+using static Vit.AutoTemp.AutoTempControllerConfig;
+
 namespace Vit.AutoTemp
 {
     public class AutoTempHelp
@@ -68,11 +70,11 @@ namespace Vit.AutoTemp
 
 
         #region BuildControllerConfigByTable
-        public static JObject BuildControllerConfigByEntityType(Type entityType)
+        public static AutoTempControllerConfig BuildControllerConfigByEntityType(Type entityType)
         {
             return BuildControllerConfigByTable(EntityTypeToTableSchema(entityType));
         }
-        public static JObject BuildControllerConfigByTable(TableSchema tableInfo)
+        public static AutoTempControllerConfig BuildControllerConfigByTable(TableSchema tableInfo)
         {
 
             #region SplitStringTo2
@@ -93,7 +95,7 @@ namespace Vit.AutoTemp
             #endregion
 
 
-            var controllerConfig = new JObject();
+            var controllerConfig = new AutoTempControllerConfig();
 
             string idField = null;
 
@@ -102,11 +104,11 @@ namespace Vit.AutoTemp
             string treeField = null;
 
 
-            var fields = new JArray();
-            var filterFields = new JArray();
+            var fields = new List<AutoTempControllerConfig.FieldConfig>();
+           
 
 
-            #region build field       
+            #region build field
             Regex ctrlAttribute = new Regex("\\[[^\\[\\]]+?\\]"); //正则匹配 [editable:true] 
             foreach (var column in tableInfo.columns)
             {
@@ -116,40 +118,18 @@ namespace Vit.AutoTemp
                     idField = column.column_name;
                 }
 
-                var field = new JObject();
+                var field = new FieldConfig() { list_config = new(), ig_attr = new() };
 
-                field["field"] = column.column_name;
-                field["list_width"] = 200;
+                field.field = column.column_name;
+                field.list_config.width = 200;
 
                 if (column.primary_key == 1)
                 {
-                    field["editable"] = false;
+                    field.editable = false;
                 }
 
-                #region (x.2)从column_comment获取用户配置
                 //   [editable:true]
                 string comment = column.column_comment;
-                if (!string.IsNullOrEmpty(comment))
-                {
-                    foreach (Match item in ctrlAttribute.Matches(comment))
-                    {
-                        string key, value;
-
-                        #region (x.x.1)获取key value 用户配置信息
-                        var comm = item.Value[1..^1];
-
-                        SplitStringTo2(comm, ":", out key, out value);
-                        value = value?.Replace("\\x5B", "[").Replace("\\x5D", "]");
-                        if (string.IsNullOrWhiteSpace(key)) continue;
-                        #endregion
-
-                        //(x.x.2)
-                        BuildFieldConfigFromComment(key, value);
-
-                    }
-                }
-
-                #endregion
 
                 //fieldIgnore
                 if ((comment ?? "").Contains("[fieldIgnore]"))
@@ -158,9 +138,9 @@ namespace Vit.AutoTemp
                 }
                 fields.Add(field);
 
-                #region (x.3)设置title               
+                #region #3 title
                 {
-                    var title = field["title"].ConvertToString();
+                    var title = field.title;
                     if (string.IsNullOrWhiteSpace(title))
                     {
                         title = comment ?? column.column_name;
@@ -171,151 +151,20 @@ namespace Vit.AutoTemp
                     {
                         title = column.column_name;
                     }
-                    field["title"] = title;
-                }
-                #endregion
-
-
-                #region (x.4)设置筛选条件的title          
-                {
-                    var title = field["title"];
-                    filterFields.Where(token => token["field"].EqualIgnore(column.column_name)
-                    && string.IsNullOrWhiteSpace(token["title"].ConvertToString())).IEnumerable_ForEach(
-                        token =>
-                        {
-                            token["title"] = title;
-                        });
-                }
-                #endregion
-
-
-
-                #region Method BuildFieldConfigFromComment
-                void BuildFieldConfigFromComment(string key, string value)
-                {
-                    if (string.IsNullOrEmpty(key)) return;
-
-                    #region (x.1)手动指定idField
-                    if (key == "idField")
-                    {
-                        idField = column.column_name;
-                        return;
-                    }
-                    #endregion
-
-                    #region (x.2)树形列表配置                   
-                    if (key == "pidField")
-                    {
-                        pidField = column.column_name;
-                        return;
-                    }
-                    if (key == "treeField")
-                    {
-                        treeField = column.column_name;
-                        return;
-                    }
-                    if (key == "rootPidValue")
-                    {
-                        rootPidValue = value;
-                        return;
-                    }
-                    #endregion
-
-                    #region (x.3)列表筛选条件
-                    //     [filter:开始时间,>=]   当前列作为筛选条件,筛选条件名称为开始时间,筛选方式为">="
-                    // filter:
-                    //  { field: 'name', title: '装修商',filterOpt:'=' }
-                    if (key == "filter")
-                    {
-                        var property = value.Split(',');
-
-                        var filterField = new JObject()
-                        {
-                            ["class"] = "Text",
-                            ["field"] = column.column_name,
-                            //["title"] = "Text",
-                            ["filterOpt"] = "="
-                        };
-                        filterFields.Add(filterField);
-
-                        #region (x.x.1)筛选方式
-                        if (property.Length > 1)
-                        {
-                            filterField["filterOpt"] = property[1];
-                        }
-                        #endregion
-
-                        #region (x.x.2)title
-                        if (property.Length > 0)
-                        {
-                            filterField["title"] = property[0];
-                        }
-                        #endregion
-                    }
-                    #endregion
-
-                    #region (x.4)设置controller的属性
-                    if (key == "controller")
-                    {
-                        try
-                        {
-                            SplitStringTo2(value, "=", out var part1, out var part2);
-                            object jsonValue;
-                            try
-                            {
-                                jsonValue = part2?.Deserialize<object>();
-                            }
-                            catch
-                            {
-                                jsonValue = part2;
-                            }
-                            controllerConfig.ValueSetByPath(jsonValue, part1.Split('.'));
-                        }
-                        catch (Exception ex)
-                        {
-                            Logger.Error(ex);
-                        }
-                        return;
-                    }
-                    #endregion
-
-                    #region (x.5)直接作为控件属性
-                    if (key == "field")
-                    {
-                        try
-                        {
-                            SplitStringTo2(value, "=", out var part1, out var part2);
-                            object jsonValue;
-                            try
-                            {
-                                jsonValue = part2?.Deserialize<object>();
-                            }
-                            catch
-                            {
-                                jsonValue = part2;
-                            }
-                            field.ValueSetByPath(jsonValue, part1.Split('.'));
-                        }
-                        catch (Exception ex)
-                        {
-                            Logger.Error(ex);
-                        }
-                        return;
-                    }
-                    #endregion                    
+                    field.title = title;
                 }
                 #endregion
             }
             #endregion
 
 
-            controllerConfig["fields"] = fields;
-            controllerConfig["filterFields"] = filterFields;
+            controllerConfig.fields = fields;
+ 
 
-            controllerConfig["idField"] = idField;
-            controllerConfig["treeField"] = treeField;
-            controllerConfig["pidField"] = pidField;
-            controllerConfig["rootPidValue"] = rootPidValue;
+            controllerConfig.idField = idField;
+            controllerConfig.treeField = treeField;
+            controllerConfig.pidField = pidField;
+            controllerConfig.rootPidValue = rootPidValue;
 
             return controllerConfig;
         }

+ 7 - 9
src/Vit.AutoTemp/DataProvider/DataProvider_Vitorm.cs

@@ -27,10 +27,10 @@ namespace Vit.AutoTemp.DataProvider
         public TableSchema tableSchema { get; private set; }
 
 
-        string idField;
-        string pidField;
+        string idField => controllerConfig?.idField;
+        string pidField => controllerConfig?.pidField;
         readonly Type entityType;
-        JObject controllerConfig;
+        AutoTempControllerConfig controllerConfig;
         readonly Func<DbContext> CreateDbContext;
 
 
@@ -57,18 +57,16 @@ namespace Vit.AutoTemp.DataProvider
         /// </summary>
         public void Init()
         {
-            controllerConfig = AutoTempHelp.BuildControllerConfigByTable(tableSchema);
-
-            idField = controllerConfig["idField"]?.Value<string>();
-            pidField = controllerConfig["pidField"]?.Value<string>();
+            controllerConfig = AutoTempHelp.BuildControllerConfigByTable(tableSchema); 
         }
 
 
 
         #region getConfig
-        public ApiReturn getControllerConfig(object sender)
+        public ApiReturn<AutoTempControllerConfig> getControllerConfig(object sender)
         {
-            return new ApiReturn<JObject>(controllerConfig);
+            var config = Json.ConvertBySerialize<AutoTempControllerConfig>(controllerConfig);
+            return config;
         }
         #endregion
 

+ 1 - 1
src/Vit.AutoTemp/DataProvider/IDataProvider.cs

@@ -12,7 +12,7 @@ namespace Vit.AutoTemp.DataProvider
     {
         string template { get; }
         ApiReturn delete(object sender, JObject arg);
-        ApiReturn getControllerConfig(object sender);
+        ApiReturn<AutoTempControllerConfig> getControllerConfig(object sender);
         ApiReturn getList(object sender, FilterRule filter, IEnumerable<OrderField> sort, PageInfo page, JObject arg);
         ApiReturn getModel(object sender, string id);
         ApiReturn insert(object sender, JObject model);

+ 6 - 4
src/Vit.AutoTemp/Demo/DemoDataProvider.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using Newtonsoft.Json.Linq;
 
 using Vit.AutoTemp.DataProvider;
+using Vit.Core.Module.Serialization;
 using Vit.Core.Util.Common;
 using Vit.Core.Util.ComponentModel.Data;
 using Vit.Extensions.Newtonsoft_Extensions;
@@ -62,7 +63,7 @@ namespace Vit.AutoTemp.Demo
         public bool isTree = false;
 
         #region getConfig
-        public ApiReturn getControllerConfig(object sender)
+        public ApiReturn<AutoTempControllerConfig> getControllerConfig(object sender)
         {
 
             var data = @"{
@@ -99,8 +100,8 @@ namespace Vit.AutoTemp.Demo
                
                 fields: [                  
                     { field: 'name', title: '<span title=""装修商名称"">装修商</span>', list_width: 200,editable:false },
-                    { field: 'sex', title: '性别', list_width: 80,visiable:false },
-                    { 'ig-class': 'TextArea', field: 'random', title: 'random', list_width: 150 },
+                    { field: 'sex', title: '性别', list_width: 80,visible:false },
+                    { 'ig_class': 'TextArea', field: 'random', title: 'random', list_width: 150 },
                     { field: 'random2', title: 'random2', list_width: 150 }
                 ],
  
@@ -110,7 +111,8 @@ namespace Vit.AutoTemp.Demo
                     { field: 'random', title: 'random' }
                 ]
             }";
-            return new ApiReturn<JObject>(data.Deserialize<JObject>());
+            var config = Json.ConvertBySerialize<AutoTempControllerConfig>(data);
+            return config;
         }
         #endregion
 

+ 2 - 2
src/Vit.AutoTemp/Demo/DemoRepository.cs

@@ -21,7 +21,7 @@ namespace Vit.AutoTemp.Demo
     {
 
         /// <summary>
-        /// [field:visiable=false]
+        /// [field:visible=false]
         /// [controller:permit.delete=false] 
         /// </summary>
         [Key]
@@ -42,7 +42,7 @@ namespace Vit.AutoTemp.Demo
         public string sex { get; set; }
 
         /// <summary>
-        /// [field:ig-class=TextArea]
+        /// [field:ig_class=TextArea]
         /// </summary>
         public string random { get; set; }
         public string random2 { get; set; }

+ 2 - 2
src/Vit.AutoTemp/Repository/Extensions/IRepositoryExtensions.cs

@@ -8,9 +8,9 @@ namespace Vit.Extensions
     {
 
         #region ToDataProvider
-        public static RespositoryDataProvider<T> ToDataProvider<T>(this IRepository<T> data, string templateName, JObject controllerConfig = null)
+        public static RespositoryDataProvider<T> ToDataProvider<T>(this IRepository<T> data, string templateName )
         {
-            return new RespositoryDataProvider<T>(data, templateName, controllerConfig);
+            return new RespositoryDataProvider<T>(data, templateName);
         }
         #endregion
 

+ 11 - 13
src/Vit.AutoTemp/Repository/RespositoryDataProvider.cs

@@ -3,6 +3,7 @@
 using Newtonsoft.Json.Linq;
 
 using Vit.AutoTemp.DataProvider;
+using Vit.Core.Module.Serialization;
 using Vit.Core.Util.ComponentModel.Data;
 using Vit.Extensions.Serialize_Extensions;
 using Vit.Linq.ComponentModel;
@@ -14,45 +15,42 @@ namespace Vit.AutoTemp.Repository
     public class RespositoryDataProvider<T> : IDataProvider
     {
 
-        public IRepository<T> respository { get; private set; }
+        public IRepository<T> repository { get; private set; }
 
-        public RespositoryDataProvider(IRepository<T> respository, string template, JObject controllerConfig = null)
+        public RespositoryDataProvider(IRepository<T> repository, string template, AutoTempControllerConfig controllerConfig = null)
         {
             this.template = template;
-            this.respository = respository;
+            this.repository = repository;
 
             this.controllerConfig = controllerConfig ?? AutoTempHelp.BuildControllerConfigByEntityType(typeof(T));
         }
 
-        readonly JObject controllerConfig;
+        readonly AutoTempControllerConfig controllerConfig;
 
         public string template { get; private set; }
-        public ApiReturn getControllerConfig(object sender)
-        {
-            return new ApiReturn<JObject>(controllerConfig);
-        }
+        public ApiReturn<AutoTempControllerConfig> getControllerConfig(object sender) => controllerConfig;
 
 
         public ApiReturn delete(object sender, JObject arg)
         {
-            return respository.Delete(respository.GetModel(arg["id"].Value<string>()).data);
+            return repository.Delete(repository.GetModel(arg["id"].Value<string>()).data);
         }
 
         public ApiReturn getList(object sender, FilterRule filter, IEnumerable<OrderField> sort, PageInfo page, JObject arg)
         {
-            return respository.GetList(filter, sort, page);
+            return repository.GetList(filter, sort, page);
         }
         public ApiReturn getModel(object sender, string id)
         {
-            return respository.GetModel(id);
+            return repository.GetModel(id);
         }
         public ApiReturn insert(object sender, JObject model)
         {
-            return respository.Insert(model.ConvertBySerialize<T>());
+            return repository.Insert(model.ConvertBySerialize<T>());
         }
         public ApiReturn update(object sender, JObject model)
         {
-            return respository.Update(model.ConvertBySerialize<T>());
+            return repository.Update(model.ConvertBySerialize<T>());
         }
     }
 }

+ 1 - 0
src/Vit.AutoTemp/Vit.AutoTemp.csproj

@@ -3,6 +3,7 @@
 
     <PropertyGroup>
         <TargetFramework>netstandard2.1</TargetFramework>
+        <LangVersion>9.0</LangVersion>
     </PropertyGroup>
 
     <ItemGroup>