mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat(ui): 新增请求方法及表格
This commit is contained in:
		@@ -4,7 +4,7 @@
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "clear": "rimraf node_modules projects/vue-admin/node_modules projects/vue-mobie/node_modules projects/vue-web/node_modules",
 | 
			
		||||
    "clear": "rimraf node_modules projects/vue-admin/node_modules projects/vue-mobile/node_modules projects/vue-web/node_modules",
 | 
			
		||||
    "dev": "pnpm --filter=@gpt-vue-projects/* run dev",
 | 
			
		||||
    "build": "pnpm --filter=@gpt-vue-projects/* run build"
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -8,5 +8,9 @@
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [],
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC"
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "axios": "^1.6.7",
 | 
			
		||||
    "uuid": "^9.0.1"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								gpt-vue/packages/request/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								gpt-vue/packages/request/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import axios from "axios";
 | 
			
		||||
import tokenHandler from "./token";
 | 
			
		||||
 | 
			
		||||
const { _tokenData, refreshToken, setCurRequest } = tokenHandler();
 | 
			
		||||
 | 
			
		||||
const createInstance = (baseURL: string = (import.meta as any).env.VITE_PROXY_BASE_URL) => {
 | 
			
		||||
 | 
			
		||||
  const instance = axios.create({
 | 
			
		||||
    baseURL,
 | 
			
		||||
    timeout: 10000,
 | 
			
		||||
    withCredentials: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  instance.interceptors.request.use((config) => {
 | 
			
		||||
    if (config.url !== _tokenData.get("lastRequest")) {
 | 
			
		||||
      refreshToken();
 | 
			
		||||
    }
 | 
			
		||||
    if (config.method === "post") {
 | 
			
		||||
      setCurRequest(config.url);
 | 
			
		||||
      config.headers["request-id"] = _tokenData.get("__token");
 | 
			
		||||
    }
 | 
			
		||||
    return config;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default createInstance;
 | 
			
		||||
							
								
								
									
										13
									
								
								gpt-vue/packages/request/token.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								gpt-vue/packages/request/token.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import { getUUID } from "../utils";
 | 
			
		||||
 | 
			
		||||
const _tokenData = new Map();
 | 
			
		||||
export default function tokenHandler() {
 | 
			
		||||
  const refreshToken = () => {
 | 
			
		||||
    _tokenData.set("__token", getUUID());
 | 
			
		||||
    _tokenData.set("lastRequest", null);
 | 
			
		||||
  };
 | 
			
		||||
  const setCurRequest = (curRequest?: string) => {
 | 
			
		||||
    _tokenData.set("lastRequest", curRequest);
 | 
			
		||||
  };
 | 
			
		||||
  return { _tokenData, refreshToken, setCurRequest };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								gpt-vue/packages/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								gpt-vue/packages/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
export interface BaseResponse<T> {
 | 
			
		||||
  code: number;
 | 
			
		||||
  data?: T;
 | 
			
		||||
  message?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ListResponse<T = Record<string, unknown>> {
 | 
			
		||||
  items: T[];
 | 
			
		||||
  page: number;
 | 
			
		||||
  page_size: number;
 | 
			
		||||
  total: number;
 | 
			
		||||
  total_page: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								gpt-vue/packages/utils/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								gpt-vue/packages/utils/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
import { v4 as uuidV4 } from "uuid";
 | 
			
		||||
 | 
			
		||||
export const getUUID = () => {
 | 
			
		||||
  return uuidV4();
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										163
									
								
								gpt-vue/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										163
									
								
								gpt-vue/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -12,13 +12,24 @@ importers:
 | 
			
		||||
        specifier: ^5.0.5
 | 
			
		||||
        version: 5.0.5
 | 
			
		||||
 | 
			
		||||
  packages: {}
 | 
			
		||||
  packages:
 | 
			
		||||
 | 
			
		||||
    dependencies:
 | 
			
		||||
      axios:
 | 
			
		||||
        specifier: ^1.6.7
 | 
			
		||||
        version: 1.6.7
 | 
			
		||||
      uuid:
 | 
			
		||||
        specifier: ^9.0.1
 | 
			
		||||
        version: 9.0.1
 | 
			
		||||
 | 
			
		||||
  projects/vue-admin:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@arco-design/web-vue':
 | 
			
		||||
        specifier: ^2.54.6
 | 
			
		||||
        version: 2.54.6(vue@3.4.21)
 | 
			
		||||
      '@gpt-vue/packages':
 | 
			
		||||
        specifier: workspace:^1.0.0
 | 
			
		||||
        version: link:../../packages
 | 
			
		||||
      pinia:
 | 
			
		||||
        specifier: ^2.1.7
 | 
			
		||||
        version: 2.1.7(typescript@5.3.3)(vue@3.4.21)
 | 
			
		||||
@@ -72,58 +83,6 @@ importers:
 | 
			
		||||
        specifier: ^1.8.27
 | 
			
		||||
        version: 1.8.27(typescript@5.3.3)
 | 
			
		||||
 | 
			
		||||
  projects/vue-mobie:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      pinia:
 | 
			
		||||
        specifier: ^2.1.7
 | 
			
		||||
        version: 2.1.7(typescript@5.3.3)(vue@3.4.21)
 | 
			
		||||
      vue:
 | 
			
		||||
        specifier: ^3.4.15
 | 
			
		||||
        version: 3.4.21(typescript@5.3.3)
 | 
			
		||||
      vue-router:
 | 
			
		||||
        specifier: ^4.2.5
 | 
			
		||||
        version: 4.3.0(vue@3.4.21)
 | 
			
		||||
    devDependencies:
 | 
			
		||||
      '@rushstack/eslint-patch':
 | 
			
		||||
        specifier: ^1.3.3
 | 
			
		||||
        version: 1.7.2
 | 
			
		||||
      '@tsconfig/node20':
 | 
			
		||||
        specifier: ^20.1.2
 | 
			
		||||
        version: 20.1.2
 | 
			
		||||
      '@types/node':
 | 
			
		||||
        specifier: ^20.11.10
 | 
			
		||||
        version: 20.11.24
 | 
			
		||||
      '@vitejs/plugin-vue':
 | 
			
		||||
        specifier: ^5.0.3
 | 
			
		||||
        version: 5.0.4(vite@5.1.5)(vue@3.4.21)
 | 
			
		||||
      '@vitejs/plugin-vue-jsx':
 | 
			
		||||
        specifier: ^3.1.0
 | 
			
		||||
        version: 3.1.0(vite@5.1.5)(vue@3.4.21)
 | 
			
		||||
      '@vue/eslint-config-typescript':
 | 
			
		||||
        specifier: ^12.0.0
 | 
			
		||||
        version: 12.0.0(eslint-plugin-vue@9.22.0)(eslint@8.57.0)(typescript@5.3.3)
 | 
			
		||||
      '@vue/tsconfig':
 | 
			
		||||
        specifier: ^0.5.1
 | 
			
		||||
        version: 0.5.1
 | 
			
		||||
      eslint:
 | 
			
		||||
        specifier: ^8.49.0
 | 
			
		||||
        version: 8.57.0
 | 
			
		||||
      eslint-plugin-vue:
 | 
			
		||||
        specifier: ^9.17.0
 | 
			
		||||
        version: 9.22.0(eslint@8.57.0)
 | 
			
		||||
      npm-run-all2:
 | 
			
		||||
        specifier: ^6.1.1
 | 
			
		||||
        version: 6.1.2
 | 
			
		||||
      typescript:
 | 
			
		||||
        specifier: ~5.3.0
 | 
			
		||||
        version: 5.3.3
 | 
			
		||||
      vite:
 | 
			
		||||
        specifier: ^5.0.11
 | 
			
		||||
        version: 5.1.5(@types/node@20.11.24)
 | 
			
		||||
      vue-tsc:
 | 
			
		||||
        specifier: ^1.8.27
 | 
			
		||||
        version: 1.8.27(typescript@5.3.3)
 | 
			
		||||
 | 
			
		||||
  projects/vue-mobile:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      pinia:
 | 
			
		||||
@@ -1413,6 +1372,20 @@ packages:
 | 
			
		||||
    engines: {node: '>=8'}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /asynckit@0.4.0:
 | 
			
		||||
    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /axios@1.6.7:
 | 
			
		||||
    resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      follow-redirects: 1.15.5
 | 
			
		||||
      form-data: 4.0.0
 | 
			
		||||
      proxy-from-env: 1.1.0
 | 
			
		||||
    transitivePeerDependencies:
 | 
			
		||||
      - debug
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /b-tween@0.3.3:
 | 
			
		||||
    resolution: {integrity: sha512-oEHegcRpA7fAuc9KC4nktucuZn2aS8htymCPcP3qkEGPqiBH+GfqtqoG2l7LxHngg6O0HFM7hOeOYExl1Oz4ZA==}
 | 
			
		||||
    dev: false
 | 
			
		||||
@@ -1523,6 +1496,13 @@ packages:
 | 
			
		||||
      color-string: 1.9.1
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /combined-stream@1.0.8:
 | 
			
		||||
    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
 | 
			
		||||
    engines: {node: '>= 0.8'}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      delayed-stream: 1.0.0
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /compute-scroll-into-view@1.0.20:
 | 
			
		||||
    resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
 | 
			
		||||
    dev: false
 | 
			
		||||
@@ -1587,6 +1567,11 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /delayed-stream@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
 | 
			
		||||
    engines: {node: '>=0.4.0'}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /dir-glob@3.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
 | 
			
		||||
    engines: {node: '>=8'}
 | 
			
		||||
@@ -1854,6 +1839,16 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /follow-redirects@1.15.5:
 | 
			
		||||
    resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==}
 | 
			
		||||
    engines: {node: '>=4.0'}
 | 
			
		||||
    peerDependencies:
 | 
			
		||||
      debug: '*'
 | 
			
		||||
    peerDependenciesMeta:
 | 
			
		||||
      debug:
 | 
			
		||||
        optional: true
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /foreground-child@3.1.1:
 | 
			
		||||
    resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
 | 
			
		||||
    engines: {node: '>=14'}
 | 
			
		||||
@@ -1862,6 +1857,15 @@ packages:
 | 
			
		||||
      signal-exit: 4.1.0
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /form-data@4.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
 | 
			
		||||
    engines: {node: '>= 6'}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      asynckit: 0.4.0
 | 
			
		||||
      combined-stream: 1.0.8
 | 
			
		||||
      mime-types: 2.1.35
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /fs.realpath@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
 | 
			
		||||
    dev: true
 | 
			
		||||
@@ -2203,6 +2207,18 @@ packages:
 | 
			
		||||
      picomatch: 2.3.1
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /mime-db@1.52.0:
 | 
			
		||||
    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
 | 
			
		||||
    engines: {node: '>= 0.6'}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /mime-types@2.1.35:
 | 
			
		||||
    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
 | 
			
		||||
    engines: {node: '>= 0.6'}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      mime-db: 1.52.0
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /mime@1.6.0:
 | 
			
		||||
    resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
 | 
			
		||||
    engines: {node: '>=4'}
 | 
			
		||||
@@ -2426,6 +2442,10 @@ packages:
 | 
			
		||||
    engines: {node: '>= 0.8.0'}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /proxy-from-env@1.1.0:
 | 
			
		||||
    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /prr@1.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
 | 
			
		||||
    requiresBuild: true
 | 
			
		||||
@@ -2713,41 +2733,10 @@ packages:
 | 
			
		||||
    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /vite@5.1.5(@types/node@20.11.24):
 | 
			
		||||
    resolution: {integrity: sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==}
 | 
			
		||||
    engines: {node: ^18.0.0 || >=20.0.0}
 | 
			
		||||
  /uuid@9.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
 | 
			
		||||
    hasBin: true
 | 
			
		||||
    peerDependencies:
 | 
			
		||||
      '@types/node': ^18.0.0 || >=20.0.0
 | 
			
		||||
      less: '*'
 | 
			
		||||
      lightningcss: ^1.21.0
 | 
			
		||||
      sass: '*'
 | 
			
		||||
      stylus: '*'
 | 
			
		||||
      sugarss: '*'
 | 
			
		||||
      terser: ^5.4.0
 | 
			
		||||
    peerDependenciesMeta:
 | 
			
		||||
      '@types/node':
 | 
			
		||||
        optional: true
 | 
			
		||||
      less:
 | 
			
		||||
        optional: true
 | 
			
		||||
      lightningcss:
 | 
			
		||||
        optional: true
 | 
			
		||||
      sass:
 | 
			
		||||
        optional: true
 | 
			
		||||
      stylus:
 | 
			
		||||
        optional: true
 | 
			
		||||
      sugarss:
 | 
			
		||||
        optional: true
 | 
			
		||||
      terser:
 | 
			
		||||
        optional: true
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@types/node': 20.11.24
 | 
			
		||||
      esbuild: 0.19.12
 | 
			
		||||
      postcss: 8.4.35
 | 
			
		||||
      rollup: 4.12.0
 | 
			
		||||
    optionalDependencies:
 | 
			
		||||
      fsevents: 2.3.3
 | 
			
		||||
    dev: true
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /vite@5.1.5(@types/node@20.11.24)(less@4.2.0):
 | 
			
		||||
    resolution: {integrity: sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								gpt-vue/projects/vue-admin/.env.development
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								gpt-vue/projects/vue-admin/.env.development
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
VITE_PROXY_BASE_URL="/api"
 | 
			
		||||
VITE_TARGET_URL="http://172.22.11.2:5678"
 | 
			
		||||
VITE_SOCKET_IO_URL="http://172.28.1.3:8899"
 | 
			
		||||
							
								
								
									
										3
									
								
								gpt-vue/projects/vue-admin/.env.production
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								gpt-vue/projects/vue-admin/.env.production
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
VITE_PROXY_BASE_URL=""
 | 
			
		||||
VITE_TARGET_URL="/"
 | 
			
		||||
VITE_SOCKET_IO_URL="/"
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@arco-design/web-vue": "^2.54.6",
 | 
			
		||||
    "@gpt-vue/packages": "workspace:^1.0.0",
 | 
			
		||||
    "pinia": "^2.1.7",
 | 
			
		||||
    "vue": "^3.4.15",
 | 
			
		||||
    "vue-router": "^4.2.5"
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,117 @@
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, ref, type PropType } from "vue";
 | 
			
		||||
import { getDefaultFormData, useComponentConfig } from "./utils";
 | 
			
		||||
import { ValueType } from "./type.d";
 | 
			
		||||
import type { SearchTableColumns, SearchColumns } from "./type";
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  modelValue: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
  },
 | 
			
		||||
  columns: {
 | 
			
		||||
    type: Array as PropType<SearchTableColumns[]>,
 | 
			
		||||
    default: () => [],
 | 
			
		||||
  },
 | 
			
		||||
  submitting: {
 | 
			
		||||
    type: Boolean,
 | 
			
		||||
    default: false,
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emits = defineEmits(["update:modelValue", "request"]);
 | 
			
		||||
 | 
			
		||||
const size = "small";
 | 
			
		||||
 | 
			
		||||
const collapsed = ref(false);
 | 
			
		||||
 | 
			
		||||
const formData = computed({
 | 
			
		||||
  get: () => props.modelValue,
 | 
			
		||||
  set(value) {
 | 
			
		||||
    emits("update:modelValue", value);
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const searchColumns = computed(() => {
 | 
			
		||||
  return props.columns?.filter(
 | 
			
		||||
    (item) => item.dataIndex && item.search
 | 
			
		||||
  ) as (SearchColumns & { dataIndex: string })[];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const optionsEvent = {
 | 
			
		||||
  onReset: () => {
 | 
			
		||||
    formData.value = getDefaultFormData(props.columns);
 | 
			
		||||
    emits("request");
 | 
			
		||||
  },
 | 
			
		||||
  onSearch: () => emits("request"),
 | 
			
		||||
  onCollapse: (value: boolean) => {
 | 
			
		||||
    collapsed.value = value ?? !collapsed.value;
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <AForm
 | 
			
		||||
    v-if="searchColumns?.length"
 | 
			
		||||
    class="search-form-conteiner"
 | 
			
		||||
    :model="formData"
 | 
			
		||||
    :size="size"
 | 
			
		||||
    :label-col-props="{ span: 0 }"
 | 
			
		||||
    :wrapper-col-props="{ span: 24 }"
 | 
			
		||||
    @submit="optionsEvent.onSearch"
 | 
			
		||||
  >
 | 
			
		||||
    <AGrid
 | 
			
		||||
      :cols="{ md: 1, lg: 2, xl: 3, xxl: 5 }"
 | 
			
		||||
      :row-gap="12"
 | 
			
		||||
      :col-gap="12"
 | 
			
		||||
      :collapsed="collapsed"
 | 
			
		||||
    >
 | 
			
		||||
      <AGridItem
 | 
			
		||||
        v-for="item in searchColumns"
 | 
			
		||||
        :key="item.dataIndex"
 | 
			
		||||
        style="transition: all 0.3s ease-in-out"
 | 
			
		||||
      >
 | 
			
		||||
        <AFormItem :field="item.dataIndex" :label="(item.title as string)">
 | 
			
		||||
          <slot :name="item.search.slotsName">
 | 
			
		||||
            <component
 | 
			
		||||
              v-model="formData[item.dataIndex]"
 | 
			
		||||
              :is="
 | 
			
		||||
                ValueType[item.search.valueType ?? 'input'] ??
 | 
			
		||||
                item.search.render
 | 
			
		||||
              "
 | 
			
		||||
              v-bind="useComponentConfig(size, item)"
 | 
			
		||||
            />
 | 
			
		||||
          </slot>
 | 
			
		||||
        </AFormItem>
 | 
			
		||||
      </AGridItem>
 | 
			
		||||
      <AGridItem suffix>
 | 
			
		||||
        <ASpace>
 | 
			
		||||
          <slot name="search-options" :option="optionsEvent">
 | 
			
		||||
            <AButton
 | 
			
		||||
              type="primary"
 | 
			
		||||
              html-type="submit"
 | 
			
		||||
              :size="size"
 | 
			
		||||
              :loading="submitting"
 | 
			
		||||
            >
 | 
			
		||||
              <icon-search />
 | 
			
		||||
              <span>查询</span>
 | 
			
		||||
            </AButton>
 | 
			
		||||
            <AButton
 | 
			
		||||
              :size="size"
 | 
			
		||||
              @click="optionsEvent.onReset"
 | 
			
		||||
              :loading="submitting"
 | 
			
		||||
            >
 | 
			
		||||
              <icon-refresh />
 | 
			
		||||
              <span>重置</span>
 | 
			
		||||
            </AButton>
 | 
			
		||||
          </slot>
 | 
			
		||||
          <slot name="search-extra" />
 | 
			
		||||
        </ASpace>
 | 
			
		||||
      </AGridItem>
 | 
			
		||||
    </AGrid>
 | 
			
		||||
  </AForm>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.search-form-conteiner {
 | 
			
		||||
  padding: 16px 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -0,0 +1,87 @@
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, ref, onActivated } from "vue";
 | 
			
		||||
import useAsyncTable from "./useAsyncTable";
 | 
			
		||||
import FormSection from "./FormSection.vue";
 | 
			
		||||
import type { SearchTableProps } from "./type";
 | 
			
		||||
import { useTableScroll, getDefaultFormData, useRequestParams } from "./utils";
 | 
			
		||||
import { Message } from "@arco-design/web-vue";
 | 
			
		||||
 | 
			
		||||
const props = defineProps<SearchTableProps>();
 | 
			
		||||
const formData = ref({ ...getDefaultFormData(props.columns) });
 | 
			
		||||
const tableContainerRef = ref<HTMLElement>();
 | 
			
		||||
 | 
			
		||||
// 表格请求参数
 | 
			
		||||
const requestParams = computed(() => ({
 | 
			
		||||
  ...useRequestParams(props.columns, formData.value),
 | 
			
		||||
  ...props.params,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const [tableConfig, getList] = useAsyncTable(props.request, requestParams);
 | 
			
		||||
 | 
			
		||||
const _columns = computed(() => {
 | 
			
		||||
  return props.columns.map((item) => ({
 | 
			
		||||
    ellipsis: true,
 | 
			
		||||
    tooltip: true,
 | 
			
		||||
    ...item,
 | 
			
		||||
  }));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleSearch = async (tips?: boolean) => {
 | 
			
		||||
  tips && Message.success("操作成功");
 | 
			
		||||
  await getList();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
onActivated(handleSearch);
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="search-table">
 | 
			
		||||
    <div class="search-table-header">
 | 
			
		||||
      <div>
 | 
			
		||||
        <slot name="header-title">{{ props.headerTitle }}</slot>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="header-option">
 | 
			
		||||
        <slot
 | 
			
		||||
          name="header-option"
 | 
			
		||||
          :formData="formData"
 | 
			
		||||
          :reload="handleSearch"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <FormSection
 | 
			
		||||
      v-model="formData"
 | 
			
		||||
      :columns="columns"
 | 
			
		||||
      :submitting="(tableConfig.loading as boolean)"
 | 
			
		||||
      @request="handleSearch"
 | 
			
		||||
    />
 | 
			
		||||
    <div ref="tableContainerRef" class="search-table-container">
 | 
			
		||||
      <ATable
 | 
			
		||||
        v-bind="{
 | 
			
		||||
          ...$attrs,
 | 
			
		||||
          ...tableConfig,
 | 
			
		||||
          ...props,
 | 
			
		||||
          scroll: useTableScroll(_columns, tableContainerRef as HTMLElement),
 | 
			
		||||
          columns: _columns
 | 
			
		||||
        }"
 | 
			
		||||
      >
 | 
			
		||||
        <template v-for="slot in Object.keys($slots)" #[slot]="config">
 | 
			
		||||
          <slot :name="slot" v-bind="{ ...config, reload: handleSearch }" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </ATable>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.search-table {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
.search-table-container {
 | 
			
		||||
  flex: 1;
 | 
			
		||||
}
 | 
			
		||||
.search-table-header {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										49
									
								
								gpt-vue/projects/vue-admin/src/components/SearchTable/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								gpt-vue/projects/vue-admin/src/components/SearchTable/type.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
import type { Component } from "vue";
 | 
			
		||||
import type { JsxElement } from "typescript";
 | 
			
		||||
import {
 | 
			
		||||
  DatePicker,
 | 
			
		||||
  Input,
 | 
			
		||||
  InputNumber,
 | 
			
		||||
  RadioGroup,
 | 
			
		||||
  RangePicker,
 | 
			
		||||
  Select,
 | 
			
		||||
  Switch,
 | 
			
		||||
  type TableColumnData,
 | 
			
		||||
} from "@arco-design/web-vue";
 | 
			
		||||
import type { TableOriginalProps, TableRequest } from "./useAsyncTable";
 | 
			
		||||
 | 
			
		||||
type Object = Record<string, unknown>;
 | 
			
		||||
 | 
			
		||||
export enum ValueType {
 | 
			
		||||
  "input" = Input,
 | 
			
		||||
  "select" = Select,
 | 
			
		||||
  "number" = InputNumber,
 | 
			
		||||
  "date" = DatePicker,
 | 
			
		||||
  "range" = RangePicker,
 | 
			
		||||
  "radio" = RadioGroup,
 | 
			
		||||
  "switch" = Switch,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type SearchConfig = {
 | 
			
		||||
  valueType?: keyof typeof ValueType;
 | 
			
		||||
  fieldProps?: Object;
 | 
			
		||||
  render?: Component | JsxElement;
 | 
			
		||||
  slotsName?: string;
 | 
			
		||||
  defaultValue?: any;
 | 
			
		||||
  transform?: (value) => Record<string, any>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface SearchTableColumns extends TableColumnData {
 | 
			
		||||
  search?: SearchConfig;
 | 
			
		||||
  hideInTable?: boolean;
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type SearchColumns = SearchTableColumns & { search: SearchConfig };
 | 
			
		||||
 | 
			
		||||
export interface SearchTableProps extends /* @vue-ignore */ TableOriginalProps {
 | 
			
		||||
  request: TableRequest<Object>;
 | 
			
		||||
  params?: Object;
 | 
			
		||||
  columns: SearchTableColumns[];
 | 
			
		||||
  headerTitle?: string;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,63 @@
 | 
			
		||||
import { computed, onMounted, reactive, unref, type Ref } from "vue";
 | 
			
		||||
import type { TableInstance } from "@arco-design/web-vue";
 | 
			
		||||
import type { BaseResponse, ListResponse } from "@gpt-vue/packages/type";
 | 
			
		||||
 | 
			
		||||
export type TableOriginalProps = TableInstance["$props"];
 | 
			
		||||
export type TableRequest<T extends Record<string, unknown>> = (params?: any) => Promise<BaseResponse<ListResponse<T>>>
 | 
			
		||||
export type TableReturn = [TableOriginalProps, () => Promise<void>];
 | 
			
		||||
function useAsyncTable<T extends Record<string, unknown>>(
 | 
			
		||||
  request: TableRequest<T>,
 | 
			
		||||
  params?: Ref<Record<string, unknown>>
 | 
			
		||||
): TableReturn {
 | 
			
		||||
  const paginationState = reactive({
 | 
			
		||||
    current: 1,
 | 
			
		||||
    pageSize: 10,
 | 
			
		||||
    total: 0,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const tableState = reactive({
 | 
			
		||||
    loading: false,
 | 
			
		||||
    data: []
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const tableConfig = computed<TableOriginalProps>(() => {
 | 
			
		||||
    return {
 | 
			
		||||
      ...tableState,
 | 
			
		||||
      rowKey: "id",
 | 
			
		||||
      pagination: {
 | 
			
		||||
        ...paginationState,
 | 
			
		||||
        showTotal: true,
 | 
			
		||||
        showPageSize: true,
 | 
			
		||||
      },
 | 
			
		||||
      onPageChange: (page) => {
 | 
			
		||||
        paginationState.current = page;
 | 
			
		||||
        getTableData();
 | 
			
		||||
      },
 | 
			
		||||
      onPageSizeChange(pageSize) {
 | 
			
		||||
        paginationState.pageSize = pageSize;
 | 
			
		||||
        getTableData();
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const getTableData = async () => {
 | 
			
		||||
    tableState.loading = true
 | 
			
		||||
    try {
 | 
			
		||||
      const { data } = await request({
 | 
			
		||||
        ...unref(params ?? {}),
 | 
			
		||||
        page: paginationState.current,
 | 
			
		||||
        pageSize: paginationState.pageSize,
 | 
			
		||||
      });
 | 
			
		||||
      tableState.data = data?.items;
 | 
			
		||||
      paginationState.total = data.total;
 | 
			
		||||
    } finally {
 | 
			
		||||
      tableState.loading = false
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  onMounted(getTableData);
 | 
			
		||||
 | 
			
		||||
  return [tableConfig, getTableData] as TableReturn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default useAsyncTable;
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
import type { TableColumnData } from "@arco-design/web-vue";
 | 
			
		||||
import type { SearchTableColumns, SearchColumns } from "./type";
 | 
			
		||||
 | 
			
		||||
export function useTableXScroll(columns: TableColumnData[]) {
 | 
			
		||||
  return columns.reduce((prev, curr) => {
 | 
			
		||||
    const width = curr.width ?? 150;
 | 
			
		||||
    return prev + width;
 | 
			
		||||
  }, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useTableScroll(columns: SearchTableColumns[], container?: HTMLElement) {
 | 
			
		||||
  const x = columns.reduce((prev, curr) => {
 | 
			
		||||
    const width = curr.hideInTable ? 0 : curr.width ?? 150;
 | 
			
		||||
    return prev + width;
 | 
			
		||||
  }, 0);
 | 
			
		||||
  const y = container?.clientHeight ?? undefined;
 | 
			
		||||
  return { x, y };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getDefaultFormData(columns: SearchTableColumns[]) {
 | 
			
		||||
  return columns?.reduce((field, curr) => {
 | 
			
		||||
    if (curr.dataIndex && curr?.search?.defaultValue) {
 | 
			
		||||
      field[curr.dataIndex] = curr.search.defaultValue;
 | 
			
		||||
    }
 | 
			
		||||
    return field;
 | 
			
		||||
  }, {});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useRequestParams(
 | 
			
		||||
  columns: SearchTableColumns[],
 | 
			
		||||
  originFormData: Record<string, any>
 | 
			
		||||
) {
 | 
			
		||||
  const filterFormData = columns?.reduce((prev, curr) => {
 | 
			
		||||
    if (!curr.dataIndex || !curr.search) {
 | 
			
		||||
      return prev;
 | 
			
		||||
    }
 | 
			
		||||
    if (curr?.search?.transform) {
 | 
			
		||||
      const filters = curr.search.transform(originFormData[curr.dataIndex]);
 | 
			
		||||
      return Object.assign(prev, filters);
 | 
			
		||||
    }
 | 
			
		||||
    return Object.assign(prev, { [curr.dataIndex]: originFormData[curr.dataIndex] });
 | 
			
		||||
  }, {});
 | 
			
		||||
  return filterFormData as Record<string, any>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useComponentConfig(size: string, item: SearchColumns) {
 | 
			
		||||
  return {
 | 
			
		||||
    size,
 | 
			
		||||
    placeholder: item.search.valueType === "range" ? ["开始时间", "结束时间"] : item.title,
 | 
			
		||||
    allowClear: true,
 | 
			
		||||
    ...(item.search.fieldProps ?? {}),
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								gpt-vue/projects/vue-admin/src/http/config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								gpt-vue/projects/vue-admin/src/http/config.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
import { Notification } from "@arco-design/web-vue";
 | 
			
		||||
import createInstance from "@gpt-vue/packages/request"
 | 
			
		||||
import type { BaseResponse } from "@gpt-vue/packages/type";
 | 
			
		||||
 | 
			
		||||
export const uploadUrl = import.meta.env.VITE_PROXY_BASE_URL + "/common/upload/minio";
 | 
			
		||||
 | 
			
		||||
export const instance = createInstance()
 | 
			
		||||
 | 
			
		||||
instance.interceptors.request.use((config) => {
 | 
			
		||||
  return config;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
instance.interceptors.response.use(
 | 
			
		||||
  (response) => {
 | 
			
		||||
    const { data }: { data: BaseResponse<unknown> } = response
 | 
			
		||||
    if (data && typeof data === "object" && data.code !== 0) {
 | 
			
		||||
      Notification.error(data.message ?? '未知错误')
 | 
			
		||||
    }
 | 
			
		||||
    return { data, response } as any;
 | 
			
		||||
  },
 | 
			
		||||
  (error) => {
 | 
			
		||||
    const STATUS_CODE: any = {
 | 
			
		||||
      401: {
 | 
			
		||||
        msg: error.response.data || "没有操作权限!",
 | 
			
		||||
        event: null,
 | 
			
		||||
      },
 | 
			
		||||
      500: {
 | 
			
		||||
        msg: error.response.data || "系统正在部署升级中,请稍后再试!",
 | 
			
		||||
        event: null,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const statusCodeEvent = STATUS_CODE?.[error.response.status];
 | 
			
		||||
 | 
			
		||||
    if (statusCodeEvent) {
 | 
			
		||||
      Notification.error(statusCodeEvent.msg);
 | 
			
		||||
      statusCodeEvent.event?.();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (error.message.indexOf("timeout") !== -1) {
 | 
			
		||||
      Notification.error("连接超时");
 | 
			
		||||
    }
 | 
			
		||||
    return Promise.reject(error);
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
function http<T = any>(config: any): Promise<BaseResponse<T>> {
 | 
			
		||||
  return instance(config).then((res) => {
 | 
			
		||||
    return res.data;
 | 
			
		||||
  }) as unknown as Promise<BaseResponse<T>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function originHttp<T = any>(config: any) {
 | 
			
		||||
  return instance<T>(config as any).then((res) => res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default http;
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import {
 | 
			
		||||
  IconUser,
 | 
			
		||||
  IconDashboard
 | 
			
		||||
  IconDashboard,
 | 
			
		||||
  IconOrderedList,
 | 
			
		||||
} from "@arco-design/web-vue/es/icon";
 | 
			
		||||
 | 
			
		||||
const menu = [
 | 
			
		||||
@@ -22,6 +23,15 @@ const menu = [
 | 
			
		||||
    },
 | 
			
		||||
    component: () => import('@/views/User/UserContainer.vue')
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/order',
 | 
			
		||||
    name: 'Order',
 | 
			
		||||
    meta: {
 | 
			
		||||
      title: "充值订单",
 | 
			
		||||
      icon: IconOrderedList,
 | 
			
		||||
    },
 | 
			
		||||
    component: () => import('@/views/Order/OrderContainer.vue')
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default menu;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,72 @@
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import SearchTable from "@/components/SearchTable/SearchTable.vue";
 | 
			
		||||
import type { SearchTableColumns } from "@/components/SearchTable/type";
 | 
			
		||||
import { getList } from "./api";
 | 
			
		||||
 | 
			
		||||
const columns: SearchTableColumns[] = [
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "order_no",
 | 
			
		||||
    title: "订单号",
 | 
			
		||||
    search: {
 | 
			
		||||
      valueType: "input",
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "username",
 | 
			
		||||
    title: "下单用户",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "subject",
 | 
			
		||||
    title: "产品名称",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "amount",
 | 
			
		||||
    title: "订单金额",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "remark.calls",
 | 
			
		||||
    title: "调用次数",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "created_at",
 | 
			
		||||
    title: "下单时间",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "status",
 | 
			
		||||
    title: "订单状态",
 | 
			
		||||
    hideInTable: true,
 | 
			
		||||
    search: {
 | 
			
		||||
      valueType: "select",
 | 
			
		||||
      fieldProps: {
 | 
			
		||||
        options: [
 | 
			
		||||
          { label: "全部", value: -1 },
 | 
			
		||||
          { label: "未支付", value: 0 },
 | 
			
		||||
          { label: "已支付", value: 2 },
 | 
			
		||||
        ],
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "pay_time",
 | 
			
		||||
    title: "支付时间",
 | 
			
		||||
    search: {
 | 
			
		||||
      valueType: "range",
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    dataIndex: "pay_way",
 | 
			
		||||
    title: "支付方式",
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: "操作",
 | 
			
		||||
    slotName: "actions",
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <SearchTable :request="getList" :columns="columns">
 | 
			
		||||
    <template #actions="{ record }">
 | 
			
		||||
      <a-link :key="record.id" status="danger">删除</a-link>
 | 
			
		||||
    </template>
 | 
			
		||||
  </SearchTable>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										9
									
								
								gpt-vue/projects/vue-admin/src/views/Order/api.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								gpt-vue/projects/vue-admin/src/views/Order/api.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
import http from "@/http/config";
 | 
			
		||||
 | 
			
		||||
export const getList = (params?: Record<string, unknown>) => {
 | 
			
		||||
  return http({
 | 
			
		||||
    url: "/admin/order/list",
 | 
			
		||||
    methods: "get",
 | 
			
		||||
    params
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user