Przeglądaj źródła

😁前端表格页面布局调整

zuohuaijun 3 lat temu
rodzic
commit
aa3b458532

+ 2 - 1
Web/package.json

@@ -43,7 +43,8 @@
 		"vue-json-pretty": "^2.2.3",
 		"vue-router": "^4.1.6",
 		"vue-signature-pad": "^3.0.2",
-		"vue3-tree-org": "^4.1.1"
+		"vue3-tree-org": "^4.1.1",
+		"xlsx-js-style": "^1.2.0"
 	},
 	"devDependencies": {
 		"@types/node": "^18.15.0",

+ 131 - 0
Web/pnpm-lock.yaml

@@ -50,6 +50,7 @@ specifiers:
   vue-router: ^4.1.6
   vue-signature-pad: ^3.0.2
   vue3-tree-org: ^4.1.1
+  xlsx-js-style: ^1.2.0
 
 dependencies:
   '@element-plus/icons-vue': registry.npmmirror.com/@element-plus/icons-vue/2.1.0_vue@3.2.47
@@ -86,6 +87,7 @@ dependencies:
   vue-router: registry.npmmirror.com/vue-router/4.1.6_vue@3.2.47
   vue-signature-pad: registry.npmmirror.com/vue-signature-pad/3.0.2_vue@3.2.47
   vue3-tree-org: registry.npmmirror.com/vue3-tree-org/4.2.1_vue@3.2.47
+  xlsx-js-style: registry.npmmirror.com/xlsx-js-style/1.2.0
 
 devDependencies:
   '@types/node': registry.npmmirror.com/@types/node/18.15.0
@@ -1502,6 +1504,24 @@ packages:
     hasBin: true
     dev: true
 
+  registry.npmmirror.com/adler-32/1.2.0:
+    resolution: {integrity: sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/adler-32/-/adler-32-1.2.0.tgz}
+    name: adler-32
+    version: 1.2.0
+    engines: {node: '>=0.8'}
+    hasBin: true
+    dependencies:
+      exit-on-epipe: registry.npmmirror.com/exit-on-epipe/1.0.1
+      printj: registry.npmmirror.com/printj/1.1.2
+    dev: false
+
+  registry.npmmirror.com/adler-32/1.3.1:
+    resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz}
+    name: adler-32
+    version: 1.3.1
+    engines: {node: '>=0.8'}
+    dev: false
+
   registry.npmmirror.com/ajv/6.12.6:
     resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz}
     name: ajv
@@ -1641,6 +1661,16 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
+  registry.npmmirror.com/cfb/1.2.2:
+    resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz}
+    name: cfb
+    version: 1.2.2
+    engines: {node: '>=0.8'}
+    dependencies:
+      adler-32: registry.npmmirror.com/adler-32/1.3.1
+      crc-32: registry.npmmirror.com/crc-32/1.2.2
+    dev: false
+
   registry.npmmirror.com/chalk/4.1.2:
     resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz}
     name: chalk
@@ -1684,6 +1714,17 @@ packages:
       tiny-emitter: registry.npmmirror.com/tiny-emitter/2.1.0
     dev: false
 
+  registry.npmmirror.com/codepage/1.14.0:
+    resolution: {integrity: sha512-iz3zJLhlrg37/gYRWgEPkaFTtzmnEv1h+r7NgZum2lFElYQPi0/5bnmuDfODHxfp0INEfnRqyfyeIJDbb7ahRw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/codepage/-/codepage-1.14.0.tgz}
+    name: codepage
+    version: 1.14.0
+    engines: {node: '>=0.8'}
+    hasBin: true
+    dependencies:
+      commander: registry.npmmirror.com/commander/2.14.1
+      exit-on-epipe: registry.npmmirror.com/exit-on-epipe/1.0.1
+    dev: false
+
   registry.npmmirror.com/color-convert/2.0.1:
     resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz}
     name: color-convert
@@ -1708,6 +1749,18 @@ packages:
       delayed-stream: registry.npmmirror.com/delayed-stream/1.0.0
     dev: false
 
+  registry.npmmirror.com/commander/2.14.1:
+    resolution: {integrity: sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/commander/-/commander-2.14.1.tgz}
+    name: commander
+    version: 2.14.1
+    dev: false
+
+  registry.npmmirror.com/commander/2.17.1:
+    resolution: {integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/commander/-/commander-2.17.1.tgz}
+    name: commander
+    version: 2.17.1
+    dev: false
+
   registry.npmmirror.com/compute-scroll-into-view/1.0.20:
     resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz}
     name: compute-scroll-into-view
@@ -1733,6 +1786,14 @@ packages:
     version: 2.5.0
     dev: false
 
+  registry.npmmirror.com/crc-32/1.2.2:
+    resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz}
+    name: crc-32
+    version: 1.2.2
+    engines: {node: '>=0.8'}
+    hasBin: true
+    dev: false
+
   registry.npmmirror.com/cropperjs/1.5.13:
     resolution: {integrity: sha512-by7jKAo73y5/Do0K6sxdTKHgndY0NMjG2bEdgeJxycbcmHuCiMXqw8sxy5C5Y5WTOTcDGmbT7Sr5CgKOXR06OA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.13.tgz}
     name: cropperjs
@@ -2190,6 +2251,13 @@ packages:
     engines: {node: '>=0.12.0'}
     dev: false
 
+  registry.npmmirror.com/exit-on-epipe/1.0.1:
+    resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz}
+    name: exit-on-epipe
+    version: 1.0.1
+    engines: {node: '>=0.8'}
+    dev: false
+
   registry.npmmirror.com/ext/1.7.0:
     resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz}
     name: ext
@@ -2246,6 +2314,12 @@ packages:
       tough-cookie: registry.npmmirror.com/tough-cookie/4.1.2
     dev: false
 
+  registry.npmmirror.com/fflate/0.3.11:
+    resolution: {integrity: sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fflate/-/fflate-0.3.11.tgz}
+    name: fflate
+    version: 0.3.11
+    dev: false
+
   registry.npmmirror.com/file-entry-cache/6.0.1:
     resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz}
     name: file-entry-cache
@@ -2313,6 +2387,13 @@ packages:
       mime-types: registry.npmmirror.com/mime-types/2.1.35
     dev: false
 
+  registry.npmmirror.com/frac/1.1.2:
+    resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz}
+    name: frac
+    version: 1.1.2
+    engines: {node: '>=0.8'}
+    dev: false
+
   registry.npmmirror.com/fs.realpath/1.0.0:
     resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz}
     name: fs.realpath
@@ -3052,6 +3133,14 @@ packages:
     version: 1.6.0
     dev: false
 
+  registry.npmmirror.com/printj/1.1.2:
+    resolution: {integrity: sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/printj/-/printj-1.1.2.tgz}
+    name: printj
+    version: 1.1.2
+    engines: {node: '>=0.8'}
+    hasBin: true
+    dev: false
+
   registry.npmmirror.com/prismjs/1.29.0:
     resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz}
     name: prismjs
@@ -3325,6 +3414,15 @@ packages:
     version: 3.1.5
     dev: false
 
+  registry.npmmirror.com/ssf/0.11.2:
+    resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz}
+    name: ssf
+    version: 0.11.2
+    engines: {node: '>=0.8'}
+    dependencies:
+      frac: registry.npmmirror.com/frac/1.1.2
+    dev: false
+
   registry.npmmirror.com/ssr-window/3.0.0:
     resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz}
     name: ssr-window
@@ -3733,6 +3831,13 @@ packages:
     version: 1.1.2
     dev: false
 
+  registry.npmmirror.com/wmf/1.0.2:
+    resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz}
+    name: wmf
+    version: 1.0.2
+    engines: {node: '>=0.8'}
+    dev: false
+
   registry.npmmirror.com/word-wrap/1.2.3:
     resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz}
     name: word-wrap
@@ -3740,6 +3845,13 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  registry.npmmirror.com/word/0.3.0:
+    resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/word/-/word-0.3.0.tgz}
+    name: word
+    version: 0.3.0
+    engines: {node: '>=0.8'}
+    dev: false
+
   registry.npmmirror.com/wrappy/1.0.2:
     resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz}
     name: wrappy
@@ -3761,6 +3873,25 @@ packages:
         optional: true
     dev: false
 
+  registry.npmmirror.com/xlsx-js-style/1.2.0:
+    resolution: {integrity: sha512-DDT4FXFSWfT4DXMSok/m3TvmP1gvO3dn0Eu/c+eXHW5Kzmp7IczNkxg/iEPnImbG9X0Vb8QhROda5eatSR/97Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xlsx-js-style/-/xlsx-js-style-1.2.0.tgz}
+    name: xlsx-js-style
+    version: 1.2.0
+    engines: {node: '>=0.8'}
+    hasBin: true
+    dependencies:
+      adler-32: registry.npmmirror.com/adler-32/1.2.0
+      cfb: registry.npmmirror.com/cfb/1.2.2
+      codepage: registry.npmmirror.com/codepage/1.14.0
+      commander: registry.npmmirror.com/commander/2.17.1
+      crc-32: registry.npmmirror.com/crc-32/1.2.2
+      exit-on-epipe: registry.npmmirror.com/exit-on-epipe/1.0.1
+      fflate: registry.npmmirror.com/fflate/0.3.11
+      ssf: registry.npmmirror.com/ssf/0.11.2
+      wmf: registry.npmmirror.com/wmf/1.0.2
+      word: registry.npmmirror.com/word/0.3.0
+    dev: false
+
   registry.npmmirror.com/xml-name-validator/4.0.0:
     resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz}
     name: xml-name-validator

+ 4 - 4
Web/src/api-services/apis/apijsonapi.ts

@@ -25,7 +25,7 @@ import { JToken } from '../models';
 export const APIJSONApiAxiosParamCreator = function (configuration?: Configuration) {
     return {
         /**
-         * 
+         * 参数:{\"[]\":{\"SYS_LOG_OP\":{}}}
          * @summary 统一入口
          * @param {{ [key: string]: JToken; }} [body] 
          * @param {*} [options] Override http request option.
@@ -75,7 +75,7 @@ export const APIJSONApiAxiosParamCreator = function (configuration?: Configurati
 export const APIJSONApiFp = function(configuration?: Configuration) {
     return {
         /**
-         * 
+         * 参数:{\"[]\":{\"SYS_LOG_OP\":{}}}
          * @summary 统一入口
          * @param {{ [key: string]: JToken; }} [body] 
          * @param {*} [options] Override http request option.
@@ -98,7 +98,7 @@ export const APIJSONApiFp = function(configuration?: Configuration) {
 export const APIJSONApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
     return {
         /**
-         * 
+         * 参数:{\"[]\":{\"SYS_LOG_OP\":{}}}
          * @summary 统一入口
          * @param {{ [key: string]: JToken; }} [body] 
          * @param {*} [options] Override http request option.
@@ -118,7 +118,7 @@ export const APIJSONApiFactory = function (configuration?: Configuration, basePa
  */
 export class APIJSONApi extends BaseAPI {
     /**
-     * 
+     * 参数:{\"[]\":{\"SYS_LOG_OP\":{}}}
      * @summary 统一入口
      * @param {{ [key: string]: JToken; }} [body] 
      * @param {*} [options] Override http request option.

+ 4 - 3
Web/src/api-services/apis/sys-code-gen-api.ts

@@ -20,6 +20,7 @@ import { AddCodeGenInput } from '../models';
 import { AdminResultListColumnOuput } from '../models';
 import { AdminResultListDatabaseOutput } from '../models';
 import { AdminResultListTableOutput } from '../models';
+import { AdminResultObject } from '../models';
 import { AdminResultSqlSugarPagedListSysCodeGen } from '../models';
 import { AdminResultSysCodeGen } from '../models';
 import { DeleteCodeGenInput } from '../models';
@@ -615,7 +616,7 @@ export const SysCodeGenApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+        async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
             const localVarAxiosArgs = await SysCodeGenApiAxiosParamCreator(configuration).apiSysCodeGenRunLocalPost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
@@ -744,7 +745,7 @@ export const SysCodeGenApiFactory = function (configuration?: Configuration, bas
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+        async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
             return SysCodeGenApiFp(configuration).apiSysCodeGenRunLocalPost(body, options).then((request) => request(axios, basePath));
         },
         /**
@@ -869,7 +870,7 @@ export class SysCodeGenApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof SysCodeGenApi
      */
-    public async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+    public async apiSysCodeGenRunLocalPost(body?: SysCodeGen, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
         return SysCodeGenApiFp(this.configuration).apiSysCodeGenRunLocalPost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**

+ 83 - 69
Web/src/api-services/apis/sys-config-api.ts

@@ -17,10 +17,12 @@ import { Configuration } from '../configuration';
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
 import { AddConfigInput } from '../models';
+import { AdminResultListString } from '../models';
 import { AdminResultListSysConfig } from '../models';
 import { AdminResultSqlSugarPagedListSysConfig } from '../models';
 import { AdminResultSysConfig } from '../models';
 import { DeleteConfigInput } from '../models';
+import { PageConfigInput } from '../models';
 import { UpdateConfigInput } from '../models';
 /**
  * SysConfigApi - axios parameter creator
@@ -157,12 +159,12 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 获取参数配置列表
+         * @summary 获取分组列表
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysConfigListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysConfig/list`;
+        apiSysConfigGroupListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysConfig/groupList`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -193,20 +195,12 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 获取参数配置分页列表
-         * @param {string} [name] 名称
-         * @param {string} [code] 编码
-         * @param {string} [groupCode] 分组编码
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @summary 获取参数配置列表
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysConfigPageGet: async (name?: string, code?: string, groupCode?: string, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysConfig/page`;
+        apiSysConfigListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysConfig/list`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -219,37 +213,44 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura
 
             // authentication Bearer required
 
-            if (name !== undefined) {
-                localVarQueryParameter['Name'] = name;
-            }
-
-            if (code !== undefined) {
-                localVarQueryParameter['Code'] = code;
-            }
-
-            if (groupCode !== undefined) {
-                localVarQueryParameter['GroupCode'] = groupCode;
-            }
-
-            if (page !== undefined) {
-                localVarQueryParameter['Page'] = page;
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
             }
-
-            if (pageSize !== undefined) {
-                localVarQueryParameter['PageSize'] = pageSize;
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
             }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 
-            if (field !== undefined) {
-                localVarQueryParameter['Field'] = field;
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 获取参数配置分页列表
+         * @param {PageConfigInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysConfigPagePost: async (body?: PageConfigInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysConfig/page`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
             }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
 
-            if (order !== undefined) {
-                localVarQueryParameter['Order'] = order;
-            }
+            // authentication Bearer required
 
-            if (descStr !== undefined) {
-                localVarQueryParameter['DescStr'] = descStr;
-            }
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
 
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
@@ -261,6 +262,8 @@ export const SysConfigApiAxiosParamCreator = function (configuration?: Configura
             localVarUrlObj.search = (new URLSearchParams(query)).toString();
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
 
             return {
                 url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
@@ -359,6 +362,19 @@ export const SysConfigApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 获取分组列表
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysConfigGroupListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListString>>> {
+            const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigGroupListGet(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 获取参数配置列表
@@ -375,19 +391,12 @@ export const SysConfigApiFp = function(configuration?: Configuration) {
         /**
          * 
          * @summary 获取参数配置分页列表
-         * @param {string} [name] 名称
-         * @param {string} [code] 编码
-         * @param {string} [groupCode] 分组编码
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @param {PageConfigInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysConfigPageGet(name?: string, code?: string, groupCode?: string, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>>> {
-            const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigPageGet(name, code, groupCode, page, pageSize, field, order, descStr, options);
+        async apiSysConfigPagePost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>>> {
+            const localVarAxiosArgs = await SysConfigApiAxiosParamCreator(configuration).apiSysConfigPagePost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -446,6 +455,15 @@ export const SysConfigApiFactory = function (configuration?: Configuration, base
         async apiSysConfigDetailGet(id: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysConfig>> {
             return SysConfigApiFp(configuration).apiSysConfigDetailGet(id, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 获取分组列表
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysConfigGroupListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListString>> {
+            return SysConfigApiFp(configuration).apiSysConfigGroupListGet(options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 获取参数配置列表
@@ -458,19 +476,12 @@ export const SysConfigApiFactory = function (configuration?: Configuration, base
         /**
          * 
          * @summary 获取参数配置分页列表
-         * @param {string} [name] 名称
-         * @param {string} [code] 编码
-         * @param {string} [groupCode] 分组编码
-         * @param {number} [page] 当前页码
-         * @param {number} [pageSize] 页码容量
-         * @param {string} [field] 排序字段
-         * @param {string} [order] 排序方向
-         * @param {string} [descStr] 降序排序
+         * @param {PageConfigInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysConfigPageGet(name?: string, code?: string, groupCode?: string, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>> {
-            return SysConfigApiFp(configuration).apiSysConfigPageGet(name, code, groupCode, page, pageSize, field, order, descStr, options).then((request) => request(axios, basePath));
+        async apiSysConfigPagePost(body?: PageConfigInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>> {
+            return SysConfigApiFp(configuration).apiSysConfigPagePost(body, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -525,6 +536,16 @@ export class SysConfigApi extends BaseAPI {
     public async apiSysConfigDetailGet(id: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysConfig>> {
         return SysConfigApiFp(this.configuration).apiSysConfigDetailGet(id, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 获取分组列表
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysConfigApi
+     */
+    public async apiSysConfigGroupListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListString>> {
+        return SysConfigApiFp(this.configuration).apiSysConfigGroupListGet(options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 获取参数配置列表
@@ -538,20 +559,13 @@ export class SysConfigApi extends BaseAPI {
     /**
      * 
      * @summary 获取参数配置分页列表
-     * @param {string} [name] 名称
-     * @param {string} [code] 编码
-     * @param {string} [groupCode] 分组编码
-     * @param {number} [page] 当前页码
-     * @param {number} [pageSize] 页码容量
-     * @param {string} [field] 排序字段
-     * @param {string} [order] 排序方向
-     * @param {string} [descStr] 降序排序
+     * @param {PageConfigInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysConfigApi
      */
-    public async apiSysConfigPageGet(name?: string, code?: string, groupCode?: string, page?: number, pageSize?: number, field?: string, order?: string, descStr?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>> {
-        return SysConfigApiFp(this.configuration).apiSysConfigPageGet(name, code, groupCode, page, pageSize, field, order, descStr, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysConfigPagePost(body?: PageConfigInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysConfig>> {
+        return SysConfigApiFp(this.configuration).apiSysConfigPagePost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 1 - 0
Web/src/api-services/models/index.ts

@@ -131,6 +131,7 @@ export * from './notice-input';
 export * from './notice-status-enum';
 export * from './notice-type-enum';
 export * from './notice-user-status-enum';
+export * from './page-config-input';
 export * from './platform-type-enum';
 export * from './reset-pwd-user-input';
 export * from './role-input';

+ 68 - 0
Web/src/api-services/models/page-config-input.ts

@@ -0,0 +1,68 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+/**
+ * 
+ * @export
+ * @interface PageConfigInput
+ */
+export interface PageConfigInput {
+    /**
+     * 当前页码
+     * @type {number}
+     * @memberof PageConfigInput
+     */
+    page?: number;
+    /**
+     * 页码容量
+     * @type {number}
+     * @memberof PageConfigInput
+     */
+    pageSize?: number;
+    /**
+     * 排序字段
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    field?: string | null;
+    /**
+     * 排序方向
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    order?: string | null;
+    /**
+     * 降序排序
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    descStr?: string | null;
+    /**
+     * 名称
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    name?: string | null;
+    /**
+     * 编码
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    code?: string | null;
+    /**
+     * 分组编码
+     * @type {string}
+     * @memberof PageConfigInput
+     */
+    groupCode?: string | null;
+}

+ 187 - 84
Web/src/components/table/index.vue

@@ -1,26 +1,75 @@
 <template>
 	<div class="table-container">
+		<div class="table-header mb15">
+			<div>
+				<slot name="command"></slot>
+			</div>
+			<div v-loading="state.importLoading" class="table-footer-tool">
+				<!-- <SvgIcon name="iconfont icon-yunxiazai_o" :size="22" title="导出" @click="onImportTable" /> -->
+				<SvgIcon name="iconfont icon-shuaxin" :size="22" title="刷新" @click="onRefreshTable" />
+				<el-dropdown v-if="!config.hideExport" trigger="click">
+					<SvgIcon name="iconfont icon-yunxiazai_o" :size="22" title="导出" />
+					<template #dropdown>
+						<el-dropdown-menu>
+							<el-dropdown-item @click="onImportTable">导出本页数据</el-dropdown-item>
+							<el-dropdown-item @click="onImportTableAll">导出全部数据</el-dropdown-item>
+						</el-dropdown-menu>
+					</template>
+				</el-dropdown>
+				<el-popover placement="top-end" trigger="click" transition="el-zoom-in-top" popper-class="table-tool-popper" :width="300" :persistent="false" @show="onSetTable">
+					<template #reference>
+						<SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置" />
+					</template>
+					<template #default>
+						<div class="tool-box">
+							<el-tooltip content="拖动进行排序" placement="top-start">
+								<SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399" />
+							</el-tooltip>
+							<el-checkbox v-model="state.checkListAll" :indeterminate="state.checkListIndeterminate" class="ml10 mr1" label="列显示" @change="onCheckAllChange" />
+							<el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号" />
+							<el-checkbox v-if="getConfig.showSelection" v-model="getConfig.isSelection" class="ml12 mr1" label="多选" />
+						</div>
+						<el-scrollbar>
+							<div ref="toolSetRef" class="tool-sortable">
+								<div class="tool-sortable-item" v-for="v in header" :key="v.key" :data-key="v.key">
+									<i class="fa fa-arrows-alt handle cursor-pointer"></i>
+									<el-checkbox v-model="v.isCheck" size="default" class="ml12 mr8" :label="v.title" @change="onCheckChange" />
+								</div>
+							</div>
+						</el-scrollbar>
+					</template>
+				</el-popover>
+			</div>
+		</div>
 		<el-table
-			:data="data"
+			ref="tableRef"
+			:data="state.data"
 			:border="setBorder"
 			v-bind="$attrs"
 			row-key="id"
-			stripe
 			style="width: 100%"
-			v-loading="config.loading"
+			v-loading="state.loading"
+			:default-sort="defaultSort"
 			@selection-change="onSelectionChange"
+			@sort-change="sortChange"
 		>
-			<el-table-column type="selection" :reserve-selection="true" width="30" v-if="config.isSelection" />
-			<el-table-column type="index" label="序号" width="60" v-if="config.isSerialNo" />
+			<el-table-column type="selection" :reserve-selection="true" width="30" v-if="config.isSelection && config.showSelection" />
+			<el-table-column type="index" label="序号" align="center" width="60" v-if="config.isSerialNo" />
 			<el-table-column
 				v-for="(item, index) in setHeader"
 				:key="index"
-				show-overflow-tooltip
+				:show-overflow-tooltip="item.toolTip"
 				:prop="item.key"
 				:width="item.colWidth"
 				:label="item.title"
+				:align="item.align"
+				:header-align="item.headerAlign"
+				:sortable="item.key == 'action' ? false : item.sortable"
 			>
-				<template v-slot="scope">
+				<template #default="scope" v-if="$slots[item.key]">
+					<slot :name="item.key" v-bind="scope"></slot>
+				</template>
+				<template v-else v-slot="scope">
 					<template v-if="item.type === 'image'">
 						<img :src="scope.row[item.key]" :width="item.width" :height="item.height" />
 					</template>
@@ -29,92 +78,56 @@
 					</template>
 				</template>
 			</el-table-column>
-			<el-table-column label="操作" width="100" v-if="config.isOperate">
-				<template v-slot="scope">
-					<el-popconfirm title="确定删除吗?" @confirm="onDelRow(scope.row)">
-						<template #reference>
-							<el-button text type="primary">删除</el-button>
-						</template>
-					</el-popconfirm>
-				</template>
-			</el-table-column>
+			<!-- <el-table-column label="操作" width="100" v-if="config.isOperate">
+        <template v-slot="scope">
+          <el-popconfirm title="确定删除吗?" @confirm="onDelRow(scope.row)">
+            <template #reference>
+              <el-button text type="primary">删除</el-button>
+            </template>
+          </el-popconfirm>
+        </template>
+      </el-table-column> -->
 			<template #empty>
 				<el-empty description="暂无数据" />
 			</template>
 		</el-table>
 		<div class="table-footer mt15">
 			<el-pagination
-				v-model:current-page="state.page.pageNum"
+				small
+				v-model:current-page="state.page.page"
 				v-model:page-size="state.page.pageSize"
 				:pager-count="5"
-				:page-sizes="[10, 20, 30]"
-				:total="config.total"
+				:page-sizes="[10, 30, 50, 100]"
+				:total="state.total"
 				layout="total, sizes, prev, pager, next, jumper"
 				background
 				@size-change="onHandleSizeChange"
 				@current-change="onHandleCurrentChange"
 			>
 			</el-pagination>
-			<div class="table-footer-tool">
-				<SvgIcon name="iconfont icon-yunxiazai_o" :size="22" title="导出" @click="onImportTable" />
-				<SvgIcon name="iconfont icon-shuaxin" :size="22" title="刷新" @click="onRefreshTable" />
-				<el-popover
-					placement="top-end"
-					trigger="click"
-					transition="el-zoom-in-top"
-					popper-class="table-tool-popper"
-					:width="300"
-					:persistent="false"
-					@show="onSetTable"
-				>
-					<template #reference>
-						<SvgIcon name="iconfont icon-quanjushezhi_o" :size="22" title="设置" />
-					</template>
-					<template #default>
-						<div class="tool-box">
-							<el-tooltip content="拖动进行排序" placement="top-start">
-								<SvgIcon name="fa fa-question-circle-o" :size="17" class="ml11" color="#909399" />
-							</el-tooltip>
-							<el-checkbox
-								v-model="state.checkListAll"
-								:indeterminate="state.checkListIndeterminate"
-								class="ml10 mr1"
-								label="列显示"
-								@change="onCheckAllChange"
-							/>
-							<el-checkbox v-model="getConfig.isSerialNo" class="ml12 mr1" label="序号" />
-							<el-checkbox v-model="getConfig.isSelection" class="ml12 mr1" label="多选" />
-						</div>
-						<el-scrollbar>
-							<div ref="toolSetRef" class="tool-sortable">
-								<div class="tool-sortable-item" v-for="v in header" :key="v.key" :data-key="v.key">
-									<i class="fa fa-arrows-alt handle cursor-pointer"></i>
-									<el-checkbox v-model="v.isCheck" size="default" class="ml12 mr8" :label="v.title" @change="onCheckChange" />
-								</div>
-							</div>
-						</el-scrollbar>
-					</template>
-				</el-popover>
-			</div>
 		</div>
 	</div>
 </template>
 
 <script setup lang="ts" name="netxTable">
-import { reactive, computed, nextTick, ref } from 'vue';
+import { reactive, computed, nextTick, ref, onMounted } from 'vue';
 import { ElMessage } from 'element-plus';
-import table2excel from 'js-table2excel';
 import Sortable from 'sortablejs';
 import { storeToRefs } from 'pinia';
 import { useThemeConfig } from '/@/stores/themeConfig';
-import '/@/theme/tableTool.scss';
+import { exportExcel } from '/@/utils/exportExcel';
+// import '/@/theme/tableTool.scss';
 
 // 定义父组件传过来的值
 const props = defineProps({
 	// 列表内容
-	data: {
-		type: Array<EmptyObjectType>,
-		default: () => [],
+	// data: {
+	//   type: Array<EmptyObjectType>,
+	//   default: () => [],
+	// },
+	getData: {
+		type: Function,
+		required: true,
 	},
 	// 表头内容
 	header: {
@@ -126,19 +139,37 @@ const props = defineProps({
 		type: Object,
 		default: () => {},
 	},
+	param: {
+		type: Object,
+		default: () => {},
+	},
+	defaultSort: {
+		type: Object,
+		default: () => {},
+	},
+	exportChangeData: {
+		type: Function,
+	},
 });
 
 // 定义子组件向父组件传值/事件
-const emit = defineEmits(['delRow', 'pageChange', 'sortHeader']);
+const emit = defineEmits(['delRow', 'pageChange', 'selectionChange', 'sortHeader']);
 
 // 定义变量内容
 const toolSetRef = ref();
+const tableRef = ref();
 const storesThemeConfig = useThemeConfig();
 const { themeConfig } = storeToRefs(storesThemeConfig);
 const state = reactive({
+	data: [] as Array<EmptyObjectType>,
+	loading: false,
+	importLoading: false,
+	total: 0,
 	page: {
-		pageNum: 1,
+		page: 1,
 		pageSize: 10,
+		field: '',
+		order: '',
 	},
 	selectlist: [] as EmptyObjectType[],
 	checkListAll: true,
@@ -169,38 +200,73 @@ const onCheckChange = () => {
 	state.checkListAll = headers === props.header.length;
 	state.checkListIndeterminate = headers > 0 && headers < props.header.length;
 };
-// 表格多选改变时,用于导出
+// 表格多选改变时
 const onSelectionChange = (val: EmptyObjectType[]) => {
 	state.selectlist = val;
-};
-// 删除当前项
-const onDelRow = (row: EmptyObjectType) => {
-	emit('delRow', row);
+	emit('selectionChange', state.selectlist);
 };
 // 分页改变
 const onHandleSizeChange = (val: number) => {
 	state.page.pageSize = val;
-	emit('pageChange', state.page);
+	handleList();
+	// emit('pageChange', state.page);
 };
-// 分页改变
+// 改变当前页
 const onHandleCurrentChange = (val: number) => {
-	state.page.pageNum = val;
-	emit('pageChange', state.page);
+	state.page.page = val;
+	handleList();
+	// emit('pageChange', state.page);
+};
+// 列排序
+const sortChange = (column: any) => {
+	state.page.field = column.prop;
+	state.page.order = column.order;
+	handleList();
 };
 // 搜索时,分页还原成默认
 const pageReset = () => {
-	state.page.pageNum = 1;
-	state.page.pageSize = 10;
-	emit('pageChange', state.page);
+	tableRef.value.clearSelection();
+	state.page.page = 1;
+	handleList();
+	// state.page.pageSize = 10;
+	// emit('pageChange', state.page);
 };
 // 导出
 const onImportTable = () => {
-	if (state.selectlist.length <= 0) return ElMessage.warning('请先选择要导出的数据');
-	table2excel(props.header, state.selectlist, `${themeConfig.value.globalTitle} ${new Date().toLocaleString()}`);
+	if (setHeader.value.length <= 0) return ElMessage.error('没有勾选要导出的列');
+	importData(state.data);
+};
+// 全部导出
+const onImportTableAll = async () => {
+	if (setHeader.value.length <= 0) return ElMessage.error('没有勾选要导出的列');
+	state.importLoading = true;
+	const param = Object.assign({}, props.param, { page: 1, pageSize: 99999 });
+	const res = await props.getData(param);
+	state.importLoading = false;
+	const data = res.result?.items ?? [];
+	importData(data);
+};
+const importData = (data: Array<EmptyObjectType>) => {
+	if (data.length <= 0) return ElMessage.error('没有数据可以导出');
+	state.importLoading = true;
+	let exportData = JSON.parse(JSON.stringify(data));
+	if (props.exportChangeData) {
+		exportData = props.exportChangeData(exportData);
+	}
+	exportExcel(
+		exportData,
+		`${props.config.exportFileName ? props.config.exportFileName : themeConfig.value.globalTitle}_${new Date().toLocaleString()}.xlsx`,
+		setHeader.value.filter((item) => {
+			return item.type != 'action';
+		}),
+		'导出数据'
+	);
+	state.importLoading = false;
 };
 // 刷新
 const onRefreshTable = () => {
-	emit('pageChange', state.page);
+	handleList();
+	// emit('pageChange', state.page);
 };
 // 设置
 const onSetTable = () => {
@@ -211,7 +277,7 @@ const onSetTable = () => {
 			animation: 150,
 			onEnd: () => {
 				const headerList: EmptyObjectType[] = [];
-				sortable.toArray().forEach((val) => {
+				sortable.toArray().forEach((val: any) => {
 					props.header.forEach((v) => {
 						if (v.key === val) headerList.push({ ...v });
 					});
@@ -222,9 +288,28 @@ const onSetTable = () => {
 	});
 };
 
+const handleList = async () => {
+	state.loading = true;
+	const param = Object.assign({}, props.param, { ...state.page });
+	const res = await props.getData(param);
+	state.loading = false;
+	state.data = res.result?.items ?? [];
+	state.total = res.result?.total ?? 0;
+};
+
+onMounted(() => {
+	if (props.defaultSort) {
+		state.page.field = props.defaultSort.prop;
+		state.page.order = props.defaultSort.order;
+	}
+	state.page.pageSize = props.config.pageSize;
+	handleList();
+});
+
 // 暴露变量
 defineExpose({
 	pageReset,
+	handleList,
 });
 </script>
 
@@ -232,24 +317,42 @@ defineExpose({
 .table-container {
 	display: flex;
 	flex-direction: column;
+	height: 100%;
+
 	.el-table {
 		flex: 1;
 	}
+
 	.table-footer {
 		display: flex;
+		justify-content: flex-end;
+	}
+
+	.table-header {
+		display: flex;
+
 		.table-footer-tool {
 			flex: 1;
 			display: flex;
 			align-items: center;
 			justify-content: flex-end;
+
 			i {
 				margin-right: 10px;
 				cursor: pointer;
 				color: var(--el-text-color-regular);
+
 				&:last-of-type {
 					margin-right: 0;
 				}
 			}
+
+			.el-dropdown {
+				i {
+					margin-right: 10px;
+					color: var(--el-text-color-regular);
+				}
+			}
 		}
 	}
 }

+ 102 - 0
Web/src/components/table/search.vue

@@ -0,0 +1,102 @@
+<template>
+	<div class="table-search-container" v-if="props.search.length > 0">
+		<el-form ref="tableSearchRef" :model="state.form" size="default" label-width="100px" class="table-form">
+			<el-row :gutter="20">
+				<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb20" v-for="(val, key) in search" :key="key" v-show="key < 3 || state.isToggle">
+					<template v-if="val.type !== ''">
+						<el-form-item :label="val.label" :prop="val.prop" :rules="[{ required: val.required, message: `${val.label}不能为空`, trigger: val.type === 'input' ? 'blur' : 'change' }]">
+							<el-input v-model="state.form[val.prop]" :placeholder="val.placeholder" clearable v-if="val.type === 'input'" @keyup.enter="onSearch(tableSearchRef)" style="width: 100%" />
+							<el-date-picker v-model="state.form[val.prop]" type="date" :placeholder="val.placeholder" v-else-if="val.type === 'date'" style="width: 100%" />
+							<el-select v-model="state.form[val.prop]" clearable :placeholder="val.placeholder" v-else-if="val.type === 'select'" style="width: 100%">
+								<el-option v-for="item in val.options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
+							</el-select>
+						</el-form-item>
+					</template>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb20">
+					<el-form-item class="table-form-btn" :label-width="search.length <= 1 ? '10px' : '100px'">
+						<template #label v-if="search.length > 3">
+							<div class="table-form-btn-toggle ml10" @click="state.isToggle = !state.isToggle">
+								<span>{{ state.isToggle ? '收起' : '展开' }}</span>
+								<SvgIcon :name="state.isToggle ? 'ele-ArrowUp' : 'ele-ArrowDown'" />
+							</div>
+						</template>
+						<div>
+							<el-button size="default" type="primary" icon="ele-Search" plain @click="onSearch(tableSearchRef)"> 查询 </el-button>
+							<el-button size="default" plain icon="ele-Refresh" @click="onReset(tableSearchRef)"> 重置 </el-button>
+						</div>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+	</div>
+</template>
+
+<script setup lang="ts" name="makeTableDemoSearch">
+import { reactive, ref, onMounted } from 'vue';
+import type { FormInstance } from 'element-plus';
+
+// 定义父组件传过来的值
+const props = defineProps({
+	// 搜索表单
+	search: {
+		type: Array<TableSearchType>,
+		default: () => [],
+	},
+});
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['search']);
+
+// 定义变量内容
+const tableSearchRef = ref<FormInstance>();
+const state = reactive({
+	form: {},
+	isToggle: false,
+});
+
+// 查询
+const onSearch = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.validate((valid: boolean) => {
+		if (valid) {
+			emit('search', state.form);
+		} else {
+			return false;
+		}
+	});
+};
+// 重置
+const onReset = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	emit('search', state.form);
+};
+// 初始化 form 字段,取自父组件 search.prop
+const initFormField = () => {
+	if (props.search.length <= 0) return false;
+	props.search.forEach((v) => (state.form[v.prop] = ''));
+};
+// 页面加载时
+onMounted(() => {
+	initFormField();
+});
+</script>
+
+<style scoped lang="scss">
+.table-search-container {
+	display: flex;
+
+	.table-form {
+		flex: 1;
+
+		.table-form-btn-toggle {
+			white-space: nowrap;
+			user-select: none;
+			display: flex;
+			align-items: center;
+			color: var(--el-color-primary);
+		}
+	}
+}
+</style>

+ 9 - 9
Web/src/theme/common/transition.scss

@@ -102,15 +102,15 @@
 	animation-duration: 0.3s;
 }
 
-// 自定义弹窗动画
-.dialog-fade-enter-active .el-dialog{
-	animation: bounceInDown;
-	animation-duration: 0.3s;
-}
-.dialog-fade-leave-active .el-dialog{
-	animation: bounceOutRight;
-	animation-duration: 0.3s;
-}
+// // 自定义弹窗动画
+// .dialog-fade-enter-active .el-dialog{
+// 	animation: bounceInDown;
+// 	animation-duration: 0.3s;
+// }
+// .dialog-fade-leave-active .el-dialog{
+// 	animation: bounceOutRight;
+// 	animation-duration: 0.3s;
+// }
 
 
 /* 页面切换动画

+ 9 - 9
Web/src/theme/element.scss

@@ -277,7 +277,7 @@
 	background: var(--el-color-primary);
 }
 .el-dialog__footer {
-	border-top: 1px solid var(--el-color-primary-light-7);
+	border-top: 1px solid var(--el-color-info-light-7);
 	padding-bottom: 10px;
   }
 .el-dialog__headerbtn{
@@ -320,9 +320,9 @@
 
 /* Pagination 分页
 ------------------------------- */
-.el-pagination__editor {
-	margin-right: 8px;
-}
+// .el-pagination__editor {
+// 	margin-right: 8px;
+// }
 /*深色模式时分页高亮问题*/
 .el-pagination.is-background .btn-next.is-active,
 .el-pagination.is-background .btn-prev.is-active,
@@ -330,11 +330,11 @@
 	background-color: var(--el-color-primary) !important;
 	color: var(--el-color-white) !important;
 }
-// 分页组件靠右显示
-.el-pagination {
-	float: right;
-	margin: 15px 0 15px 0 !important;
-}
+// // 分页组件靠右显示
+// .el-pagination {
+// 	float: right;
+// 	margin: 5px 0 5px 0 !important;
+// }
 
 /* scrollbar
 ------------------------------- */

+ 15 - 5
Web/src/types/views.d.ts

@@ -287,7 +287,7 @@ declare type WorkflowDrawerState<T = any> = {
  */
 // tableDemo
 declare type TableDemoPageType = {
-	pageNum: number;
+	page: number;
 	pageSize: number;
 };
 
@@ -300,6 +300,10 @@ declare type TableHeaderType = {
 	width?: string | number;
 	height?: string | number;
 	isCheck: boolean;
+	align: string;
+	headerAlign: string;
+	toolTip: boolean;
+	sortable: boolean;
 };
 
 declare type TableSearchType = {
@@ -313,17 +317,23 @@ declare type TableSearchType = {
 
 declare type TableDemoState = {
 	tableData: {
-		data: EmptyObjectType[];
+		// data: EmptyObjectType[];
 		header: TableHeaderType[];
 		config: {
-			total: number;
-			loading: boolean;
+			// total: number;
+			// loading: boolean;
 			isBorder: boolean;
 			isSelection: boolean;
+			showSelection: boolean;
 			isSerialNo: boolean;
-			isOperate: boolean;
+			pageSize: number;
+			hideExport: boolean;
+			exportFileName: string;
+			// isOperate: boolean;
 		};
+		// actions: WorkflowDrawerLabelType[];
 		search: TableSearchType[];
 		param: EmptyObjectType;
+		defaultSort: EmptyObjectType;
 	};
 };

+ 85 - 0
Web/src/utils/exportExcel.ts

@@ -0,0 +1,85 @@
+import XLSXS from 'xlsx-js-style';
+/**
+* @description:
+* @param {Object} json 服务端发过来的数据
+* @param {String} name 导出Excel文件名字
+
+* @param {String} titleArr 导出Excel表头
+
+* @param {String} sheetName 导出sheetName名字
+* @return:
+**/
+export function exportExcel(jsonarr: Array<EmptyObjectType>, name: string, header: Array<EmptyObjectType>, sheetName: string) {
+	var data = new Array();
+	var wpxArr = new Array(); //列宽度
+	const borderStyle = {
+		//边框样式
+		top: {
+			style: 'thin',
+			color: {
+				rgb: '000000',
+			},
+		},
+		bottom: {
+			style: 'thin',
+			color: {
+				rgb: '000000',
+			},
+		},
+		left: {
+			style: 'thin',
+			color: {
+				rgb: '000000',
+			},
+		},
+		right: {
+			style: 'thin',
+			color: {
+				rgb: '000000',
+			},
+		},
+	};
+	var headrow = new Array();
+	header.forEach((item) => {
+		let width = 200;
+		if (item.colWidth && !isNaN(item.colWidth)) {
+			width = parseInt(item.colWidth) * 0.7;
+		}
+		wpxArr.push({ wpx: width });
+		headrow.push({
+			v: item.title,
+			t: 's',
+			s: {
+				font: { bold: true },
+				alignment: { wrapText: true, horizontal: item.headerAlign ? item.headerAlign : item.align, vertical: 'center' },
+				border: borderStyle,
+			},
+		});
+	});
+	data.push(headrow); //写入标题
+	jsonarr.forEach((json) => {
+		var row = new Array();
+		header.forEach((item) => {
+			if (json.hasOwnProperty(item.key)) {
+				let val = '';
+				if (json[item.key] != null) val = json[item.key];
+				row.push({
+					v: val,
+					t: 's',
+					s: {
+						alignment: { wrapText: true, horizontal: item.align, vertical: 'center' },
+						border: borderStyle,
+					},
+				});
+			}
+		});
+		data.push(row);
+	});
+	console.log(data);
+	const ws = XLSXS.utils.aoa_to_sheet(data);
+	const wb = XLSXS.utils.book_new();
+	ws['!cols'] = wpxArr;
+	XLSXS.utils.book_append_sheet(wb, ws, sheetName);
+	/* generate file and send to client */
+	XLSXS.writeFile(wb, name + '.xlsx');
+}

+ 114 - 110
Web/src/views/system/config/index.vue

@@ -1,109 +1,132 @@
 <template>
 	<div class="sys-config-container">
 		<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
-			<el-form :model="state.queryParams" ref="queryForm" :inline="true">
-        <el-row :gutter="35">
-          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
-            <el-form-item label="配置名称" prop="name">
-              <el-input placeholder="配置名称" clearable @keyup.enter="handleQuery" v-model="state.queryParams.name" />
-            </el-form-item>
-          </el-col>
-          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">  
-            <el-form-item label="配置编码" prop="code">
-              <el-input placeholder="配置编码" clearable @keyup.enter="handleQuery" v-model="state.queryParams.code" />
-            </el-form-item>
-          </el-col>
-          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">  
-            <el-form-item label="分组编码" prop="groupCode">
-              <el-input placeholder="分组编码" clearable @keyup.enter="handleQuery" v-model="state.queryParams.groupCode" />
-            </el-form-item>
-          </el-col>
-          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20 search-actions">
-            <div>
-              <el-button type="primary"  icon="ele-Plus" @click="openAddConfig" v-auth="'sysConfig:add'"> 新增 </el-button>
-            </div>
-            <div>
-              <el-form-item>
-                <el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
-                <el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysConfig:page'" plain> 查询 </el-button> 
-              </el-form-item>
-            </div>
-          </el-col>
-        </el-row>
-			</el-form>
+			<TableSearch :search="tb.tableData.search" @search="onSearch" />
 		</el-card>
-
 		<el-card shadow="hover" style="margin-top: 8px">
-			<el-table :data="state.configData" style="width: 100%" v-loading="state.loading" border>
-				<el-table-column type="index" label="序号" width="55" align="center" />
-				<el-table-column prop="name" label="配置名称" show-overflow-tooltip />
-				<el-table-column prop="code" label="配置编码" show-overflow-tooltip />
-				<el-table-column prop="value" label="属性值" show-overflow-tooltip />
-				<el-table-column prop="sysFlag" label="内置参数" width="100" align="center" show-overflow-tooltip>
-					<template #default="scope">
-						<el-tag v-if="scope.row.sysFlag === 1"> 是 </el-tag>
-						<el-tag type="danger" v-else> 否 </el-tag>
-					</template>
-				</el-table-column>
-				<el-table-column prop="groupCode" label="分组编码" show-overflow-tooltip />
-				<el-table-column prop="orderNo" label="排序" width="70" align="center" show-overflow-tooltip />
-				<el-table-column prop="createTime" label="修改时间" align="center" show-overflow-tooltip />
-				<el-table-column prop="remark" label="备注" show-overflow-tooltip />
-				<el-table-column label="操作" width="140" fixed="right" align="center" show-overflow-tooltip>
-					<template #default="scope">
-						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditConfig(scope.row)" v-auth="'sysConfig:update'"> 编辑 </el-button>
-						<el-button icon="ele-Delete" size="small" text type="danger" @click="delConfig(scope.row)" v-auth="'sysConfig:delete'"> 删除 </el-button>
-					</template>
-				</el-table-column>
-			</el-table>
-			<el-pagination
-				v-model:currentPage="state.tableParams.page"
-				v-model:page-size="state.tableParams.pageSize"
-				:total="state.tableParams.total"
-				:page-sizes="[10, 20, 50, 100]"
-				small
-				background
-				@size-change="handleSizeChange"
-				@current-change="handleCurrentChange"
-				layout="total, sizes, prev, pager, next, jumper"
-			/>
+			<Table ref="tableRef" v-bind="tb.tableData" :getData="getData" :exportChangeData="exportChangeData" @sortHeader="onSortHeader" @selectionChange="tableSelection">
+				<template #command>
+					<el-button type="primary" icon="ele-Plus" @click="openAddConfig" v-auth="'sysConfig:add'"> 新增 </el-button>
+					<el-button v-if="state.selectlist.length > 0" type="danger" icon="ele-Delete" @click="bacthDelete" v-auth="'sysConfig:delete'"> 批量删除 </el-button>
+				</template>
+				<template #sysFlag="scope">
+					<el-tag v-if="scope.row.sysFlag === 1"> 是 </el-tag>
+					<el-tag type="danger" v-else> 否 </el-tag>
+				</template>
+				<template #action="scope">
+					<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditConfig(scope.row)" v-auth="'sysConfig:update'"> 编辑 </el-button>
+					<el-button icon="ele-Delete" size="small" text type="danger" @click="delConfig(scope.row)" v-auth="'sysConfig:delete'"> 删除 </el-button>
+				</template>
+			</Table>
 		</el-card>
 		<EditConfig ref="editConfigRef" :title="state.editConfigTitle" />
 	</div>
 </template>
 
 <script lang="ts" setup name="sysConfig">
-import { onMounted, onUnmounted, reactive, ref } from 'vue';
+import { onMounted, onUnmounted, reactive, ref, defineAsyncComponent, nextTick } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import mittBus from '/@/utils/mitt';
 import EditConfig from '/@/views/system/config/component/editConfig.vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysConfigApi } from '/@/api-services/api';
-import { SysConfig } from '/@/api-services/models';
 
+// 引入组件
+const Table = defineAsyncComponent(() => import('/@/components/table/index.vue'));
+const TableSearch = defineAsyncComponent(() => import('/@/components/table/search.vue'));
 const editConfigRef = ref<InstanceType<typeof EditConfig>>();
+const tableRef = ref<RefType>();
+
 const state = reactive({
-	loading: false,
-	configData: [] as Array<SysConfig>,
-	queryParams: {
-		name: undefined,
-		code: undefined,
-		groupCode: undefined,
-	},
-	tableParams: {
-		page: 1,
-		pageSize: 10,
-		total: 0 as any,
-	},
 	editConfigTitle: '',
+	selectlist: [] as EmptyObjectType[],
 });
 
-onMounted(async () => {
-	handleQuery();
+const tb = reactive<TableDemoState>({
+	tableData: {
+		// 表头内容(必传,注意格式)
+		header: [
+			{ key: 'name', colWidth: '180', title: '配置名称', type: 'text', align: 'center', headerAlign: '', toolTip: false, sortable: true, isCheck: true },
+			{ key: 'code', colWidth: '180', title: '配置编码', type: 'text', align: 'center', headerAlign: '', toolTip: true, sortable: true, isCheck: true },
+			{ key: 'value', colWidth: '120', title: '属性值', type: 'text', align: 'center', headerAlign: '', toolTip: false, sortable: false, isCheck: true },
+			{ key: 'sysFlag', colWidth: '120', title: '内置参数', type: 'text', align: 'center', headerAlign: '', toolTip: false, sortable: false, isCheck: true },
+			{ key: 'groupCode', colWidth: '120', title: '分组编码', type: 'text', align: 'center', headerAlign: '', toolTip: false, sortable: false, isCheck: true },
+			{ key: 'orderNo', colWidth: '80', title: '排序', type: 'text', align: 'center', headerAlign: '', toolTip: false, sortable: false, isCheck: true },
+			{ key: 'remark', colWidth: '', title: '备注', type: 'text', align: '', headerAlign: 'center', toolTip: false, sortable: false, isCheck: true },
+			{ key: 'action', colWidth: '150', title: '操作', type: 'action', align: 'center', headerAlign: '', toolTip: false, sortable: false, isCheck: true },
+		],
+		// 配置项(必传)
+		config: {
+			isBorder: true, // 是否显示表格边框
+			isSerialNo: true, // 是否显示表格序号
+			isSelection: false, // 是否勾选表格多选
+			showSelection: false, //是否显示表格多选
+			pageSize: 20, // 每页条数
+			hideExport: false, //是否隐藏导出按钮
+			exportFileName: '参数配置', //导出报表的文件名,不填写取应用名称
+		},
+		// 搜索表单,动态生成(传空数组时,将不显示搜索,type有3种类型:input,date,select)
+		search: [
+			{ label: '配置名称', prop: 'name', placeholder: '配置名称', required: false, type: 'input' },
+			{ label: '配置编码', prop: 'code', placeholder: '配置编码', required: false, type: 'input' },
+			// { label: '分组编码', prop: 'groupCode', placeholder: '分组编码', required: false, type: 'input' },
+			// { label: '创建时间', prop: 'time', placeholder: '请选择', required: false, type: 'date' },
+		],
+		param: {},
+		defaultSort: {
+			prop: 'orderNo',
+			order: 'ascending',
+		},
+	},
+});
+const getData = async (param: any) => {
+	var res = await getAPI(SysConfigApi).apiSysConfigPagePost(param);
+	return res.data;
+};
+const exportChangeData = (data: Array<EmptyObjectType>) => {
+	data.forEach((item) => {
+		item.sysFlag = item.sysFlag == 1 ? '是' : '否';
+	});
+	return data;
+};
+// 拖动显示列排序回调
+const onSortHeader = (data: TableHeaderType[]) => {
+	tb.tableData.header = data;
+};
+// 搜索点击时表单回调
+const onSearch = (data: EmptyObjectType) => {
+	tb.tableData.param = Object.assign({}, tb.tableData.param, { ...data });
+	nextTick(() => {
+		tableRef.value.pageReset();
+	});
+};
 
+const getGroupList = async () => {
+	const res = await getAPI(SysConfigApi).apiSysConfigGroupListGet();
+	const groupSearch = {
+		label: '分组编码',
+		prop: 'groupCode',
+		placeholder: '请选择',
+		required: false,
+		type: 'select',
+		options: [],
+	} as TableSearchType;
+	res.data.result?.forEach((item) => {
+		groupSearch.options?.push({ label: item, value: item });
+	});
+	tb.tableData.search.push(groupSearch);
+};
+//表格多选事件
+const tableSelection = (data: EmptyObjectType[]) => {
+	console.log('表格多选事件', data);
+	state.selectlist = data;
+};
+
+onMounted(async () => {
+	getGroupList();
 	mittBus.on('submitRefresh', () => {
-		handleQuery();
+		tableRef.value.handleList();
 	});
 });
 
@@ -111,23 +134,6 @@ onUnmounted(() => {
 	mittBus.off('submitRefresh');
 });
 
-// 查询操作
-const handleQuery = async () => {
-	state.loading = true;
-	var res = await getAPI(SysConfigApi).apiSysConfigPageGet(state.queryParams.name, state.queryParams.code, state.queryParams.groupCode, state.tableParams.page, state.tableParams.pageSize);
-	state.configData = res.data.result?.items ?? [];
-	state.tableParams.total = res.data.result?.total;
-	state.loading = false;
-};
-
-// 重置操作
-const resetQuery = () => {
-	state.queryParams.name = undefined;
-	state.queryParams.code = undefined;
-	state.queryParams.groupCode = undefined;
-	handleQuery();
-};
-
 // 打开新增页面
 const openAddConfig = () => {
 	state.editConfigTitle = '添加配置';
@@ -149,21 +155,19 @@ const delConfig = (row: any) => {
 	})
 		.then(async () => {
 			await getAPI(SysConfigApi).apiSysConfigDeletePost({ id: row.id });
-			handleQuery();
+			tableRef.value.handleList();
 			ElMessage.success('删除成功');
 		})
 		.catch(() => {});
 };
-
-// 改变页面容量
-const handleSizeChange = (val: number) => {
-	state.tableParams.pageSize = val;
-	handleQuery();
-};
-
-// 改变页码序号
-const handleCurrentChange = (val: number) => {
-	state.tableParams.page = val;
-	handleQuery();
+//批量删除
+const bacthDelete = () => {
+	if (state.selectlist.length == 0) return false;
+	ElMessageBox.confirm(`确定批量删除【${state.selectlist[0].name}】等${state.selectlist.length}个配置?`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+	});
+	console.log('批量删除了');
 };
 </script>