mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
fix: resolved eslint errors
This commit is contained in:
parent
287ef7527d
commit
d325dd7493
33 changed files with 643 additions and 584 deletions
9
app/components.d.ts
vendored
9
app/components.d.ts
vendored
|
@ -77,14 +77,6 @@ declare module 'vue' {
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SetLanguageSetLanguage: typeof import('./src/components/SetLanguage/SetLanguage.vue')['default']
|
SetLanguageSetLanguage: typeof import('./src/components/SetLanguage/SetLanguage.vue')['default']
|
||||||
StdDataDisplayStdBatchEdit: typeof import('./src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue')['default']
|
|
||||||
StdDataDisplayStdCurd: typeof import('./src/components/StdDesign/StdDataDisplay/StdCurd.vue')['default']
|
|
||||||
StdDataDisplayStdPagination: typeof import('./src/components/StdDesign/StdDataDisplay/StdPagination.vue')['default']
|
|
||||||
StdDataDisplayStdTable: typeof import('./src/components/StdDesign/StdDataDisplay/StdTable.vue')['default']
|
|
||||||
StdDataEntryComponentsStdPassword: typeof import('./src/components/StdDesign/StdDataEntry/components/StdPassword.vue')['default']
|
|
||||||
StdDataEntryComponentsStdSelect: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelect.vue')['default']
|
|
||||||
StdDataEntryComponentsStdSelector: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelector.vue')['default']
|
|
||||||
StdDataEntryStdFormItem: typeof import('./src/components/StdDesign/StdDataEntry/StdFormItem.vue')['default']
|
|
||||||
StdDesignStdDataDisplayStdBatchEdit: typeof import('./src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue')['default']
|
StdDesignStdDataDisplayStdBatchEdit: typeof import('./src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue')['default']
|
||||||
StdDesignStdDataDisplayStdCurd: typeof import('./src/components/StdDesign/StdDataDisplay/StdCurd.vue')['default']
|
StdDesignStdDataDisplayStdCurd: typeof import('./src/components/StdDesign/StdDataDisplay/StdCurd.vue')['default']
|
||||||
StdDesignStdDataDisplayStdPagination: typeof import('./src/components/StdDesign/StdDataDisplay/StdPagination.vue')['default']
|
StdDesignStdDataDisplayStdPagination: typeof import('./src/components/StdDesign/StdDataDisplay/StdPagination.vue')['default']
|
||||||
|
@ -92,6 +84,7 @@ declare module 'vue' {
|
||||||
StdDesignStdDataEntryComponentsStdPassword: typeof import('./src/components/StdDesign/StdDataEntry/components/StdPassword.vue')['default']
|
StdDesignStdDataEntryComponentsStdPassword: typeof import('./src/components/StdDesign/StdDataEntry/components/StdPassword.vue')['default']
|
||||||
StdDesignStdDataEntryComponentsStdSelect: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelect.vue')['default']
|
StdDesignStdDataEntryComponentsStdSelect: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelect.vue')['default']
|
||||||
StdDesignStdDataEntryComponentsStdSelector: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelector.vue')['default']
|
StdDesignStdDataEntryComponentsStdSelector: typeof import('./src/components/StdDesign/StdDataEntry/components/StdSelector.vue')['default']
|
||||||
|
StdDesignStdDataEntryStdDataEntry: typeof import('./src/components/StdDesign/StdDataEntry/StdDataEntry.vue')['default']
|
||||||
StdDesignStdDataEntryStdFormItem: typeof import('./src/components/StdDesign/StdDataEntry/StdFormItem.vue')['default']
|
StdDesignStdDataEntryStdFormItem: typeof import('./src/components/StdDesign/StdDataEntry/StdFormItem.vue')['default']
|
||||||
SwitchAppearanceIconsVPIconMoon: typeof import('./src/components/SwitchAppearance/icons/VPIconMoon.vue')['default']
|
SwitchAppearanceIconsVPIconMoon: typeof import('./src/components/SwitchAppearance/icons/VPIconMoon.vue')['default']
|
||||||
SwitchAppearanceIconsVPIconSun: typeof import('./src/components/SwitchAppearance/icons/VPIconSun.vue')['default']
|
SwitchAppearanceIconsVPIconSun: typeof import('./src/components/SwitchAppearance/icons/VPIconSun.vue')['default']
|
||||||
|
|
5
app/env.d.ts
vendored
Normal file
5
app/env.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
declare module '*.svg' {
|
||||||
|
import React from 'react'
|
||||||
|
const content: React.FC<React.SVGProps<SVGElement>>
|
||||||
|
export default content
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "nginx-ui-app-next",
|
"name": "nginx-ui-app-next",
|
||||||
"private": true,
|
|
||||||
"version": "2.0.0-beta.4",
|
"version": "2.0.0-beta.4",
|
||||||
"type": "commonjs",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"lint": "eslint . -c .eslintrc.js --fix --ext .ts,.vue,.tsx",
|
"typecheck": "vue-tsc --noEmit",
|
||||||
|
"lint": "eslint . -c .eslintrc.js --fix --ext .ts,.vue,.tsx,.d.ts",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"gettext:extract": "vue-gettext-extract",
|
"gettext:extract": "vue-gettext-extract",
|
||||||
|
@ -14,9 +13,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "^7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
"@formkit/auto-animate": "^0.8.0",
|
"@formkit/auto-animate": "^0.8.0",
|
||||||
"@types/lodash": "^4.14.202",
|
|
||||||
"@types/nprogress": "^0.2.0",
|
|
||||||
"@types/sortablejs": "^1.15.0",
|
|
||||||
"@vue/reactivity": "^3.3.9",
|
"@vue/reactivity": "^3.3.9",
|
||||||
"@vue/shared": "^3.3.9",
|
"@vue/shared": "^3.3.9",
|
||||||
"@vueuse/core": "^10.6.1",
|
"@vueuse/core": "^10.6.1",
|
||||||
|
@ -45,6 +41,10 @@
|
||||||
"xterm-addon-fit": "^0.8.0"
|
"xterm-addon-fit": "^0.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/lodash": "^4.14.202",
|
||||||
|
"@types/nprogress": "^0.2.0",
|
||||||
|
"@types/sortablejs": "^1.15.0",
|
||||||
|
"@vue/tsconfig": "^0.4.0",
|
||||||
"@antfu/eslint-config-vue": "^0.43.1",
|
"@antfu/eslint-config-vue": "^0.43.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
||||||
"@typescript-eslint/parser": "^6.13.0",
|
"@typescript-eslint/parser": "^6.13.0",
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
"unplugin-auto-import": "^0.17.1",
|
"unplugin-auto-import": "^0.17.1",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"unplugin-vue-define-options": "^1.4.0",
|
"unplugin-vue-define-options": "^1.4.0",
|
||||||
"vite": "^5.0.2",
|
"vite": "^5.0.3",
|
||||||
"vite-plugin-html": "^3.2.0",
|
"vite-plugin-html": "^3.2.0",
|
||||||
"vite-svg-loader": "^5.1.0",
|
"vite-svg-loader": "^5.1.0",
|
||||||
"vue-tsc": "^1.8.22"
|
"vue-tsc": "^1.8.22"
|
||||||
|
|
57
app/pnpm-lock.yaml
generated
57
app/pnpm-lock.yaml
generated
|
@ -11,15 +11,6 @@ dependencies:
|
||||||
'@formkit/auto-animate':
|
'@formkit/auto-animate':
|
||||||
specifier: ^0.8.0
|
specifier: ^0.8.0
|
||||||
version: 0.8.1
|
version: 0.8.1
|
||||||
'@types/lodash':
|
|
||||||
specifier: ^4.14.202
|
|
||||||
version: 4.14.202
|
|
||||||
'@types/nprogress':
|
|
||||||
specifier: ^0.2.0
|
|
||||||
version: 0.2.3
|
|
||||||
'@types/sortablejs':
|
|
||||||
specifier: ^1.15.0
|
|
||||||
version: 1.15.7
|
|
||||||
'@vue/reactivity':
|
'@vue/reactivity':
|
||||||
specifier: ^3.3.9
|
specifier: ^3.3.9
|
||||||
version: 3.3.9
|
version: 3.3.9
|
||||||
|
@ -103,6 +94,15 @@ devDependencies:
|
||||||
'@antfu/eslint-config-vue':
|
'@antfu/eslint-config-vue':
|
||||||
specifier: ^0.43.1
|
specifier: ^0.43.1
|
||||||
version: 0.43.1(@typescript-eslint/eslint-plugin@6.13.0)(@typescript-eslint/parser@6.13.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0)(typescript@5.3.2)
|
version: 0.43.1(@typescript-eslint/eslint-plugin@6.13.0)(@typescript-eslint/parser@6.13.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0)(typescript@5.3.2)
|
||||||
|
'@types/lodash':
|
||||||
|
specifier: ^4.14.202
|
||||||
|
version: 4.14.202
|
||||||
|
'@types/nprogress':
|
||||||
|
specifier: ^0.2.0
|
||||||
|
version: 0.2.3
|
||||||
|
'@types/sortablejs':
|
||||||
|
specifier: ^1.15.0
|
||||||
|
version: 1.15.7
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^6.13.0
|
specifier: ^6.13.0
|
||||||
version: 6.13.0(@typescript-eslint/parser@6.13.0)(eslint@8.54.0)(typescript@5.3.2)
|
version: 6.13.0(@typescript-eslint/parser@6.13.0)(eslint@8.54.0)(typescript@5.3.2)
|
||||||
|
@ -111,13 +111,16 @@ devDependencies:
|
||||||
version: 6.13.0(eslint@8.54.0)(typescript@5.3.2)
|
version: 6.13.0(eslint@8.54.0)(typescript@5.3.2)
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
specifier: ^4.5.0
|
specifier: ^4.5.0
|
||||||
version: 4.5.0(vite@5.0.2)(vue@3.3.9)
|
version: 4.5.0(vite@5.0.3)(vue@3.3.9)
|
||||||
'@vitejs/plugin-vue-jsx':
|
'@vitejs/plugin-vue-jsx':
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0(vite@5.0.2)(vue@3.3.9)
|
version: 3.1.0(vite@5.0.3)(vue@3.3.9)
|
||||||
'@vue/compiler-sfc':
|
'@vue/compiler-sfc':
|
||||||
specifier: ^3.3.9
|
specifier: ^3.3.9
|
||||||
version: 3.3.9
|
version: 3.3.9
|
||||||
|
'@vue/tsconfig':
|
||||||
|
specifier: ^0.4.0
|
||||||
|
version: 0.4.0
|
||||||
ace-builds:
|
ace-builds:
|
||||||
specifier: ^1.31.2
|
specifier: ^1.31.2
|
||||||
version: 1.31.2
|
version: 1.31.2
|
||||||
|
@ -167,11 +170,11 @@ devDependencies:
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.4.0(vue@3.3.9)
|
version: 1.4.0(vue@3.3.9)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.3
|
||||||
version: 5.0.2(less@4.2.0)
|
version: 5.0.3(less@4.2.0)
|
||||||
vite-plugin-html:
|
vite-plugin-html:
|
||||||
specifier: ^3.2.0
|
specifier: ^3.2.0
|
||||||
version: 3.2.0(vite@5.0.2)
|
version: 3.2.0(vite@5.0.3)
|
||||||
vite-svg-loader:
|
vite-svg-loader:
|
||||||
specifier: ^5.1.0
|
specifier: ^5.1.0
|
||||||
version: 5.1.0(vue@3.3.9)
|
version: 5.1.0(vue@3.3.9)
|
||||||
|
@ -1297,7 +1300,7 @@ packages:
|
||||||
|
|
||||||
/@types/lodash@4.14.202:
|
/@types/lodash@4.14.202:
|
||||||
resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==}
|
resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@types/mdast@3.0.15:
|
/@types/mdast@3.0.15:
|
||||||
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
|
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
|
||||||
|
@ -1327,7 +1330,7 @@ packages:
|
||||||
|
|
||||||
/@types/nprogress@0.2.3:
|
/@types/nprogress@0.2.3:
|
||||||
resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
|
resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@types/parse-json@4.0.2:
|
/@types/parse-json@4.0.2:
|
||||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||||
|
@ -1343,7 +1346,7 @@ packages:
|
||||||
|
|
||||||
/@types/sortablejs@1.15.7:
|
/@types/sortablejs@1.15.7:
|
||||||
resolution: {integrity: sha512-PvgWCx1Lbgm88FdQ6S7OGvLIjWS66mudKPlfdrWil0TjsO5zmoZmzoKiiwRShs1dwPgrlkr0N4ewuy0/+QUXYQ==}
|
resolution: {integrity: sha512-PvgWCx1Lbgm88FdQ6S7OGvLIjWS66mudKPlfdrWil0TjsO5zmoZmzoKiiwRShs1dwPgrlkr0N4ewuy0/+QUXYQ==}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/@types/unist@2.0.10:
|
/@types/unist@2.0.10:
|
||||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||||
|
@ -1549,7 +1552,7 @@ packages:
|
||||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vitejs/plugin-vue-jsx@3.1.0(vite@5.0.2)(vue@3.3.9):
|
/@vitejs/plugin-vue-jsx@3.1.0(vite@5.0.3)(vue@3.3.9):
|
||||||
resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
|
resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -1559,20 +1562,20 @@ packages:
|
||||||
'@babel/core': 7.23.3
|
'@babel/core': 7.23.3
|
||||||
'@babel/plugin-transform-typescript': 7.23.4(@babel/core@7.23.3)
|
'@babel/plugin-transform-typescript': 7.23.4(@babel/core@7.23.3)
|
||||||
'@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.3)
|
'@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.3)
|
||||||
vite: 5.0.2(less@4.2.0)
|
vite: 5.0.3(less@4.2.0)
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@5.3.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vitejs/plugin-vue@4.5.0(vite@5.0.2)(vue@3.3.9):
|
/@vitejs/plugin-vue@4.5.0(vite@5.0.3)(vue@3.3.9):
|
||||||
resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==}
|
resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^4.0.0 || ^5.0.0
|
vite: ^4.0.0 || ^5.0.0
|
||||||
vue: ^3.2.25
|
vue: ^3.2.25
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.0.2(less@4.2.0)
|
vite: 5.0.3(less@4.2.0)
|
||||||
vue: 3.3.9(typescript@5.3.2)
|
vue: 3.3.9(typescript@5.3.2)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -1734,6 +1737,10 @@ packages:
|
||||||
/@vue/shared@3.3.9:
|
/@vue/shared@3.3.9:
|
||||||
resolution: {integrity: sha512-ZE0VTIR0LmYgeyhurPTpy4KzKsuDyQbMSdM49eKkMnT5X4VfFBLysMzjIZhLEFQYjjOVVfbvUDHckwjDFiO2eA==}
|
resolution: {integrity: sha512-ZE0VTIR0LmYgeyhurPTpy4KzKsuDyQbMSdM49eKkMnT5X4VfFBLysMzjIZhLEFQYjjOVVfbvUDHckwjDFiO2eA==}
|
||||||
|
|
||||||
|
/@vue/tsconfig@0.4.0:
|
||||||
|
resolution: {integrity: sha512-CPuIReonid9+zOG/CGTT05FXrPYATEqoDGNrEaqS4hwcw5BUNM2FguC0mOwJD4Jr16UpRVl9N0pY3P+srIbqmg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vueuse/core@10.6.1(vue@3.3.9):
|
/@vueuse/core@10.6.1(vue@3.3.9):
|
||||||
resolution: {integrity: sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==}
|
resolution: {integrity: sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5360,7 +5367,7 @@ packages:
|
||||||
- terser
|
- terser
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vite-plugin-html@3.2.0(vite@5.0.2):
|
/vite-plugin-html@3.2.0(vite@5.0.3):
|
||||||
resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==}
|
resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: '>=2.0.0'
|
vite: '>=2.0.0'
|
||||||
|
@ -5377,7 +5384,7 @@ packages:
|
||||||
html-minifier-terser: 6.1.0
|
html-minifier-terser: 6.1.0
|
||||||
node-html-parser: 5.4.2
|
node-html-parser: 5.4.2
|
||||||
pathe: 0.2.0
|
pathe: 0.2.0
|
||||||
vite: 5.0.2(less@4.2.0)
|
vite: 5.0.3(less@4.2.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-svg-loader@5.1.0(vue@3.3.9):
|
/vite-svg-loader@5.1.0(vue@3.3.9):
|
||||||
|
@ -5426,8 +5433,8 @@ packages:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vite@5.0.2(less@4.2.0):
|
/vite@5.0.3(less@4.2.0):
|
||||||
resolution: {integrity: sha512-6CCq1CAJCNM1ya2ZZA7+jS2KgnhbzvxakmlIjN24cF/PXhRMzpM/z8QgsVJA/Dm5fWUWnVEsmtBoMhmerPxT0g==}
|
resolution: {integrity: sha512-WgEq8WEKpZ8c0DL4M1+E+kBZEJyjBmGVrul6z8Ljfhv+PPbNF4aGq014DwNYxGz2FGq6NKL0N8usdiESWd2l2w==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
|
@ -26,6 +26,7 @@ class Curd<T> {
|
||||||
get = this._get.bind(this)
|
get = this._get.bind(this)
|
||||||
save = this._save.bind(this)
|
save = this._save.bind(this)
|
||||||
destroy = this._destroy.bind(this)
|
destroy = this._destroy.bind(this)
|
||||||
|
update_order = this._update_order.bind(this)
|
||||||
|
|
||||||
constructor(baseUrl: string, plural: string | null = null) {
|
constructor(baseUrl: string, plural: string | null = null) {
|
||||||
this.baseUrl = baseUrl
|
this.baseUrl = baseUrl
|
||||||
|
@ -51,6 +52,14 @@ class Curd<T> {
|
||||||
_destroy(id: any = null) {
|
_destroy(id: any = null) {
|
||||||
return http.delete(`${this.baseUrl}/${id}`)
|
return http.delete(`${this.baseUrl}/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_order(data: {
|
||||||
|
target_id: number
|
||||||
|
direction: number
|
||||||
|
affected_ids: number[]
|
||||||
|
}) {
|
||||||
|
return http.post(`${this.plural}/order`, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Curd
|
export default Curd
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
|
import type { ModelBase } from '@/api/curd'
|
||||||
import Curd from '@/api/curd'
|
import Curd from '@/api/curd'
|
||||||
|
|
||||||
const environment = new Curd('/environment')
|
export interface Environment extends ModelBase {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
token: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const environment: Curd<Environment> = new Curd('/environment')
|
||||||
|
|
||||||
export default environment
|
export default environment
|
||||||
|
|
|
@ -7,7 +7,7 @@ export interface ChatComplicationMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
const openai = {
|
const openai = {
|
||||||
store_record(data: { file_name: string; messages: ChatComplicationMessage[] }) {
|
store_record(data: { file_name?: string; messages: ChatComplicationMessage[] }) {
|
||||||
return http.post('/chat_gpt_record', data)
|
return http.post('/chat_gpt_record', data)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
import type { ModelBase } from '@/api/curd'
|
||||||
import Curd from '@/api/curd'
|
import Curd from '@/api/curd'
|
||||||
|
|
||||||
const user: Curd = new Curd('user')
|
export interface User extends ModelBase {
|
||||||
|
name: string
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const user: Curd<User> = new Curd('user')
|
||||||
|
|
||||||
export default user
|
export default user
|
||||||
|
|
|
@ -17,7 +17,7 @@ const breadList = computed(() => {
|
||||||
route.matched.forEach(item => {
|
route.matched.forEach(item => {
|
||||||
// item.name !== 'index' && this.breadList.push(item)
|
// item.name !== 'index' && this.breadList.push(item)
|
||||||
_breadList.push({
|
_breadList.push({
|
||||||
name: item.name as () => string,
|
name: item.name as never as () => string,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import type { Ref } from 'vue'
|
||||||
import { useSettingsStore } from '@/pinia'
|
import { useSettingsStore } from '@/pinia'
|
||||||
import type { Series } from '@/components/Chart/types'
|
import type { Series } from '@/components/Chart/types'
|
||||||
|
|
||||||
const { series, max, y_formatter } = defineProps<{
|
const { series, max, yFormatter } = defineProps<{
|
||||||
series: Series[]
|
series: Series[]
|
||||||
max?: number
|
max?: number
|
||||||
yFormatter?: (value: number) => string
|
yFormatter?: (value: number) => string
|
||||||
|
@ -69,7 +69,7 @@ let chartOptions = {
|
||||||
style: {
|
style: {
|
||||||
colors: fontColor(),
|
colors: fontColor(),
|
||||||
},
|
},
|
||||||
formatter: y_formatter,
|
formatter: yFormatter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
|
@ -106,7 +106,7 @@ const callback = () => {
|
||||||
style: {
|
style: {
|
||||||
colors: fontColor(),
|
colors: fontColor(),
|
||||||
},
|
},
|
||||||
formatter: y_formatter,
|
formatter: yFormatter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
|
|
|
@ -295,7 +295,7 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
||||||
v-model:value="ask_buffer"
|
v-model:value="ask_buffer"
|
||||||
auto-size
|
auto-size
|
||||||
/>
|
/>
|
||||||
<div class="sned-btn">
|
<div class="send-btn">
|
||||||
<AButton
|
<AButton
|
||||||
size="small"
|
size="small"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -356,7 +356,7 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sned-btn {
|
.send-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 3px;
|
bottom: 3px;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
import { useGettext } from 'vue3-gettext'
|
import { useGettext } from 'vue3-gettext'
|
||||||
import environment from '@/api/environment'
|
import environment from '@/api/environment'
|
||||||
|
|
||||||
|
|
|
@ -1,82 +1,45 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { provide, reactive, ref } from 'vue'
|
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
|
import type { ComputedRef } from 'vue'
|
||||||
|
import type { StdTableProps } from './StdTable.vue'
|
||||||
import StdTable from './StdTable.vue'
|
import StdTable from './StdTable.vue'
|
||||||
import gettext from '@/gettext'
|
import gettext from '@/gettext'
|
||||||
|
|
||||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||||
|
import type { Column } from '@/components/StdDesign/types'
|
||||||
|
|
||||||
const props = defineProps({
|
export interface StdCurdProps {
|
||||||
api: Object,
|
cardTitleKey?: string
|
||||||
columns: Array,
|
modalMaxWidth?: string | number
|
||||||
title: String,
|
disableAdd?: boolean
|
||||||
data_key: {
|
onClickAdd?: () => void
|
||||||
type: String,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
default: 'data',
|
onClickEdit?: (id: number | string, record: any, index: number) => void
|
||||||
},
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
disable_search: {
|
beforeSave?: (data: any) => void
|
||||||
type: Boolean,
|
}
|
||||||
default: false,
|
|
||||||
},
|
const props = defineProps<StdTableProps & StdCurdProps>()
|
||||||
disable_add: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
soft_delete: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
edit_text: String,
|
|
||||||
deletable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
get_params: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
editable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
beforeSave: {
|
|
||||||
type: Function,
|
|
||||||
default: () => {
|
|
||||||
},
|
|
||||||
},
|
|
||||||
exportCsv: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
modalWidth: {
|
|
||||||
type: Number,
|
|
||||||
default: 600,
|
|
||||||
},
|
|
||||||
useSortable: Boolean,
|
|
||||||
})
|
|
||||||
|
|
||||||
const { $gettext } = gettext
|
const { $gettext } = gettext
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const update = ref(0)
|
const update = ref(0)
|
||||||
const data: any = reactive({ id: null })
|
const data = reactive({ id: null })
|
||||||
|
|
||||||
provide('data', data)
|
provide('data', data)
|
||||||
|
|
||||||
const error: any = reactive({})
|
const error = reactive({})
|
||||||
const selected = ref([])
|
const selected = ref([])
|
||||||
|
|
||||||
function onSelect(keys: any) {
|
function onSelect(keys) {
|
||||||
selected.value = keys
|
selected.value = keys
|
||||||
}
|
}
|
||||||
|
|
||||||
function editableColumns() {
|
const editableColumns = computed(() => {
|
||||||
return props.columns!.filter((c: any) => {
|
return props.columns!.filter(c => {
|
||||||
return c.edit
|
return c.edit
|
||||||
})
|
})
|
||||||
}
|
}) as ComputedRef<Column[]>
|
||||||
|
|
||||||
function add() {
|
function add() {
|
||||||
Object.keys(data).forEach(v => {
|
Object.keys(data).forEach(v => {
|
||||||
|
@ -86,11 +49,9 @@ function add() {
|
||||||
clear_error()
|
clear_error()
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}
|
}
|
||||||
|
const table = ref()
|
||||||
function get_list() {
|
function get_list() {
|
||||||
const t: Table = table.value!
|
table.value?.get_list()
|
||||||
|
|
||||||
t!.get_list()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
@ -99,12 +60,6 @@ defineExpose({
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
|
||||||
const table = ref(null)
|
|
||||||
|
|
||||||
interface Table {
|
|
||||||
get_list(): void
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear_error() {
|
function clear_error() {
|
||||||
Object.keys(error).forEach(v => {
|
Object.keys(error).forEach(v => {
|
||||||
delete error[v]
|
delete error[v]
|
||||||
|
@ -114,12 +69,12 @@ function clear_error() {
|
||||||
const ok = async () => {
|
const ok = async () => {
|
||||||
clear_error()
|
clear_error()
|
||||||
await props?.beforeSave?.(data)
|
await props?.beforeSave?.(data)
|
||||||
props.api!.save(data.id, data).then((r: any) => {
|
props.api!.save(data.id, data).then(r => {
|
||||||
message.success($gettext('Save Successfully'))
|
message.success($gettext('Save Successfully'))
|
||||||
Object.assign(data, r)
|
Object.assign(data, r)
|
||||||
get_list()
|
get_list()
|
||||||
visible.value = false
|
visible.value = false
|
||||||
}).catch((e: any) => {
|
}).catch(e => {
|
||||||
message.error($gettext(e?.message ?? 'Server error'), 5)
|
message.error($gettext(e?.message ?? 'Server error'), 5)
|
||||||
Object.assign(error, e.errors)
|
Object.assign(error, e.errors)
|
||||||
})
|
})
|
||||||
|
@ -131,15 +86,15 @@ function cancel() {
|
||||||
clear_error()
|
clear_error()
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(id: any) {
|
function edit(id) {
|
||||||
props.api!.get(id).then(async (r: any) => {
|
props.api!.get(id).then(async r => {
|
||||||
Object.keys(data).forEach(k => {
|
Object.keys(data).forEach(k => {
|
||||||
delete data[k]
|
delete data[k]
|
||||||
})
|
})
|
||||||
data.id = null
|
data.id = null
|
||||||
Object.assign(data, r)
|
Object.assign(data, r)
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}).catch((e: any) => {
|
}).catch(e => {
|
||||||
message.error($gettext(e?.message ?? 'Server error'), 5)
|
message.error($gettext(e?.message ?? 'Server error'), 5)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -151,7 +106,7 @@ const selectedRowKeys = ref([])
|
||||||
<div class="std-curd">
|
<div class="std-curd">
|
||||||
<ACard :title="title || $gettext('Table')">
|
<ACard :title="title || $gettext('Table')">
|
||||||
<template
|
<template
|
||||||
v-if="!disable_add"
|
v-if="!disableAdd"
|
||||||
#extra
|
#extra
|
||||||
>
|
>
|
||||||
<a @click="add">{{ $gettext('Add') }}</a>
|
<a @click="add">{{ $gettext('Add') }}</a>
|
||||||
|
@ -162,7 +117,7 @@ const selectedRowKeys = ref([])
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
:key="update"
|
:key="update"
|
||||||
v-model:selected-row-keys="selectedRowKeys"
|
v-model:selected-row-keys="selectedRowKeys"
|
||||||
@clickEdit="edit"
|
@click-edit="edit"
|
||||||
@selected="onSelect"
|
@selected="onSelect"
|
||||||
>
|
>
|
||||||
<template #actions="slotProps">
|
<template #actions="slotProps">
|
||||||
|
@ -177,11 +132,11 @@ const selectedRowKeys = ref([])
|
||||||
<AModal
|
<AModal
|
||||||
class="std-curd-edit-modal"
|
class="std-curd-edit-modal"
|
||||||
:mask="false"
|
:mask="false"
|
||||||
:title="edit_text ? edit_text : (data.id ? $gettext('Modify') : $gettext('Add'))"
|
:title="data.id ? $gettext('Modify') : $gettext('Add')"
|
||||||
:open="visible"
|
:open="visible"
|
||||||
:cancel-text="$gettext('Cancel')"
|
:cancel-text="$gettext('Cancel')"
|
||||||
:ok-text="$gettext('OK')"
|
:ok-text="$gettext('OK')"
|
||||||
:width="modalWidth"
|
:width="modalMaxWidth"
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
@ok="ok"
|
@ok="ok"
|
||||||
|
@ -197,8 +152,7 @@ const selectedRowKeys = ref([])
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StdDataEntry
|
<StdDataEntry
|
||||||
ref="std_data_entry"
|
:data-list="editableColumns"
|
||||||
:data-list="editableColumns()"
|
|
||||||
:data-source="data"
|
:data-source="data"
|
||||||
:error="error"
|
:error="error"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type { Pagination } from '@/api/curd'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
pagination: Pagination
|
pagination: Pagination
|
||||||
size?: 'small' | 'default'
|
size?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'changePageSize', 'update:pagination'])
|
const emit = defineEmits(['change', 'changePageSize', 'update:pagination'])
|
||||||
|
|
|
@ -1,103 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, reactive, ref, toRaw, watch } from 'vue'
|
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import Sortable from 'sortablejs'
|
|
||||||
import { HolderOutlined } from '@ant-design/icons-vue'
|
import { HolderOutlined } from '@ant-design/icons-vue'
|
||||||
import _ from 'lodash'
|
import { useGettext } from 'vue3-gettext'
|
||||||
|
import type { ComputedRef } from 'vue'
|
||||||
|
import type { SorterResult } from 'ant-design-vue/lib/table/interface'
|
||||||
import StdPagination from './StdPagination.vue'
|
import StdPagination from './StdPagination.vue'
|
||||||
import { downloadCsv } from '@/lib/helper'
|
|
||||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||||
import gettext from '@/gettext'
|
import type { Pagination } from '@/api/curd'
|
||||||
|
import type { Column } from '@/components/StdDesign/types'
|
||||||
|
import exportCsvHandler from '@/components/StdDesign/StdDataDisplay/methods/exportCsv'
|
||||||
|
import useSortable from '@/components/StdDesign/StdDataDisplay/methods/sortable'
|
||||||
|
import type Curd from '@/api/curd'
|
||||||
|
|
||||||
const props = defineProps({
|
export interface StdTableProps {
|
||||||
api: Object,
|
title?: string
|
||||||
columns: Array,
|
mode?: string
|
||||||
data_key: {
|
rowKey?: string
|
||||||
type: String,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
default: 'data',
|
api: Curd<any>
|
||||||
},
|
columns: Column[]
|
||||||
disable_search: {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
type: Boolean,
|
getParams?: Record<string, any>
|
||||||
default: false,
|
size?: string
|
||||||
},
|
disableQueryParams?: boolean
|
||||||
disable_query_params: {
|
disableSearch?: boolean
|
||||||
type: Boolean,
|
pithy?: boolean
|
||||||
default: false,
|
exportCsv?: boolean
|
||||||
},
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
disable_add: {
|
overwriteParams?: Record<string, any>
|
||||||
type: Boolean,
|
disabledModify?: boolean
|
||||||
default: false,
|
selectionType?: string
|
||||||
},
|
sortable?: boolean
|
||||||
edit_text: String,
|
disableDelete?: boolean
|
||||||
deletable: {
|
disablePagination?: boolean
|
||||||
type: Boolean,
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
default: true,
|
selectedRowKeys?: any | any[]
|
||||||
},
|
sortableMoveHook?: (oldRow: number[], newRow: number[]) => boolean
|
||||||
get_params: {
|
scrollX?: string | number
|
||||||
type: Object,
|
}
|
||||||
default() {
|
|
||||||
return {}
|
const props = withDefaults(defineProps<StdTableProps>(), {
|
||||||
},
|
rowKey: 'id',
|
||||||
},
|
|
||||||
editable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
selectionType: {
|
|
||||||
type: String,
|
|
||||||
validator(value: string) {
|
|
||||||
return ['checkbox', 'radio'].includes(value)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pithy: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
scrollX: {
|
|
||||||
type: [Number, Boolean],
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
rowKey: {
|
|
||||||
type: String,
|
|
||||||
default: 'id',
|
|
||||||
},
|
|
||||||
exportCsv: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
size: String,
|
|
||||||
selectedRowKeys: {
|
|
||||||
type: Array,
|
|
||||||
},
|
|
||||||
useSortable: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['onSelected', 'onSelectedRecord', 'clickEdit', 'update:selectedRowKeys', 'clickBatchModify'])
|
const emit = defineEmits(['onSelected', 'onSelectedRecord', 'clickEdit', 'update:selectedRowKeys', 'clickBatchModify'])
|
||||||
|
const { $gettext } = useGettext()
|
||||||
const { $gettext, interpolate } = gettext
|
const route = useRoute()
|
||||||
|
const dataSource = ref([])
|
||||||
const data_source: any = ref([])
|
const expandKeysList = ref([])
|
||||||
const expand_keys_list: any = ref([])
|
const rowsKeyIndexMap = ref({})
|
||||||
const rows_key_index_map: any = ref({})
|
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
|
|
||||||
const pagination = reactive({
|
// This can be useful if there are more than one StdTable in the same page.
|
||||||
|
const randomId = ref(Math.random().toString(36).substring(2, 8))
|
||||||
|
|
||||||
|
const pagination: Pagination = reactive({
|
||||||
total: 1,
|
total: 1,
|
||||||
per_page: 10,
|
per_page: 10,
|
||||||
current_page: 1,
|
current_page: 1,
|
||||||
total_pages: 1,
|
total_pages: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const params = reactive({
|
const params = reactive({
|
||||||
...props.get_params,
|
...props.getParams,
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedKeysLocalBuffer: any = ref([])
|
const selectedKeysLocalBuffer = ref([])
|
||||||
|
|
||||||
const selectedRowKeysBuffer = computed({
|
const selectedRowKeysBuffer = computed({
|
||||||
get() {
|
get() {
|
||||||
|
@ -109,17 +77,47 @@ const selectedRowKeysBuffer = computed({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const searchColumns = getSearchColumns()
|
const searchColumns = computed(() => {
|
||||||
const pithyColumns = getPithyColumns()
|
const _searchColumns = []
|
||||||
const batchColumns = getBatchEditColumns()
|
|
||||||
|
props.columns?.forEach(column => {
|
||||||
|
if (column.search)
|
||||||
|
_searchColumns.push(column)
|
||||||
|
})
|
||||||
|
|
||||||
|
return _searchColumns
|
||||||
|
})
|
||||||
|
|
||||||
|
const pithyColumns = computed(() => {
|
||||||
|
if (props.pithy) {
|
||||||
|
return props.columns?.filter(c => {
|
||||||
|
return c.pithy === true && !c.hidden
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.columns?.filter(c => {
|
||||||
|
return !c.hidden
|
||||||
|
})
|
||||||
|
}) as ComputedRef<Column[]>
|
||||||
|
|
||||||
|
const batchColumns = computed(() => {
|
||||||
|
const batch = []
|
||||||
|
|
||||||
|
props.columns?.forEach(column => {
|
||||||
|
if (column.batch)
|
||||||
|
batch.push(column)
|
||||||
|
})
|
||||||
|
|
||||||
|
return batch
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!props.disable_query_params)
|
if (!props.disableQueryParams)
|
||||||
Object.assign(params, route.query)
|
Object.assign(params, route.query)
|
||||||
|
|
||||||
get_list()
|
get_list()
|
||||||
|
|
||||||
if (props.useSortable)
|
if (props.sortable)
|
||||||
initSortable()
|
initSortable()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -127,11 +125,11 @@ defineExpose({
|
||||||
get_list,
|
get_list,
|
||||||
})
|
})
|
||||||
|
|
||||||
function destroy(id: any) {
|
function destroy(id) {
|
||||||
props.api!.destroy(id).then(() => {
|
props.api!.destroy(id).then(() => {
|
||||||
get_list()
|
get_list()
|
||||||
message.success(interpolate($gettext('Delete ID: %{id}'), { id }))
|
message.success($gettext('Deleted successfully'))
|
||||||
}).catch((e: any) => {
|
}).catch(e => {
|
||||||
message.error($gettext(e?.message ?? 'Server error'))
|
message.error($gettext(e?.message ?? 'Server error'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -142,37 +140,35 @@ function get_list(page_num = null, page_size = 20) {
|
||||||
params.page = page_num
|
params.page = page_num
|
||||||
params.page_size = page_size
|
params.page_size = page_size
|
||||||
}
|
}
|
||||||
props.api!.get_list(params).then(async (r: any) => {
|
props.api?.get_list(params).then(async r => {
|
||||||
data_source.value = r.data
|
dataSource.value = r.data
|
||||||
rows_key_index_map.value = {}
|
rowsKeyIndexMap.value = {}
|
||||||
if (props.useSortable) {
|
if (props.sortable)
|
||||||
function buildIndexMap(data: any, level: number = 0, index: number = 0, total: number[] = []) {
|
|
||||||
if (data && data.length > 0) {
|
|
||||||
data.forEach((v: any) => {
|
|
||||||
v.level = level
|
|
||||||
|
|
||||||
const current_index = [...total, index++]
|
|
||||||
|
|
||||||
rows_key_index_map.value[v.id] = current_index
|
|
||||||
if (v.children)
|
|
||||||
buildIndexMap(v.children, level + 1, 0, current_index)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildIndexMap(r.data)
|
buildIndexMap(r.data)
|
||||||
}
|
|
||||||
|
|
||||||
if (r.pagination !== undefined)
|
if (r.pagination)
|
||||||
Object.assign(pagination, r.pagination)
|
Object.assign(pagination, r.pagination)
|
||||||
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}).catch((e: any) => {
|
}).catch(e => {
|
||||||
message.error(e?.message ?? $gettext('Server error'))
|
message.error(e?.message ?? $gettext('Server error'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function buildIndexMap(data, level: number = 0, index: number = 0, total: number[] = []) {
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
data.forEach(v => {
|
||||||
|
v.level = level
|
||||||
|
|
||||||
function stdChange(pagination: any, filters: any, sorter: any) {
|
const current_indexes = [...total, index++]
|
||||||
|
|
||||||
|
rowsKeyIndexMap.value[v.id] = current_indexes
|
||||||
|
if (v.children)
|
||||||
|
buildIndexMap(v.children, level + 1, 0, current_indexes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function orderPaginationChange(_pagination: Pagination, filters, sorter: SorterResult) {
|
||||||
if (sorter) {
|
if (sorter) {
|
||||||
selectedRowKeysBuffer.value = []
|
selectedRowKeysBuffer.value = []
|
||||||
params.order_by = sorter.field
|
params.order_by = sorter.field
|
||||||
|
@ -189,67 +185,29 @@ function stdChange(pagination: any, filters: any, sorter: any) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pagination)
|
if (_pagination)
|
||||||
selectedRowKeysBuffer.value = []
|
selectedRowKeysBuffer.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
function expandedTable(keys: any) {
|
function expandedTable(keys) {
|
||||||
expand_keys_list.value = keys
|
expandKeysList.value = keys
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSearchColumns() {
|
const crossPageSelect = {}
|
||||||
const searchColumns: any = []
|
|
||||||
|
|
||||||
props.columns!.forEach((column: any) => {
|
async function onSelectChange(_selectedRowKeys) {
|
||||||
if (column.search)
|
|
||||||
searchColumns.push(column)
|
|
||||||
})
|
|
||||||
|
|
||||||
return searchColumns
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBatchEditColumns() {
|
|
||||||
const batch: any = []
|
|
||||||
|
|
||||||
props.columns!.forEach((column: any) => {
|
|
||||||
if (column.batch)
|
|
||||||
batch.push(column)
|
|
||||||
})
|
|
||||||
|
|
||||||
return batch
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPithyColumns() {
|
|
||||||
if (props.pithy) {
|
|
||||||
return props.columns!.filter((c: any, index: any, columns: any) => {
|
|
||||||
return c.pithy === true && c.display !== false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return props.columns!.filter((c: any, index: any, columns: any) => {
|
|
||||||
return c.display !== false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function checked(c: any) {
|
|
||||||
params[c.target.value] = c.target.checked
|
|
||||||
}
|
|
||||||
|
|
||||||
const crossPageSelect: any = {}
|
|
||||||
|
|
||||||
async function onSelectChange(_selectedRowKeys: any) {
|
|
||||||
const page = params.page || 1
|
const page = params.page || 1
|
||||||
|
|
||||||
crossPageSelect[page] = await _selectedRowKeys
|
crossPageSelect[page] = await _selectedRowKeys
|
||||||
|
|
||||||
let t: any = []
|
let t = []
|
||||||
Object.keys(crossPageSelect).forEach(v => {
|
Object.keys(crossPageSelect).forEach(v => {
|
||||||
t.push(...crossPageSelect[v])
|
t.push(...crossPageSelect[v])
|
||||||
})
|
})
|
||||||
|
|
||||||
const n: any = [..._selectedRowKeys]
|
const n = [..._selectedRowKeys]
|
||||||
|
|
||||||
t = await t.concat(n)
|
t = t.concat(n)
|
||||||
|
|
||||||
// console.log(crossPageSelect)
|
// console.log(crossPageSelect)
|
||||||
const set = new Set(t)
|
const set = new Set(t)
|
||||||
|
@ -258,7 +216,7 @@ async function onSelectChange(_selectedRowKeys: any) {
|
||||||
emit('onSelected', selectedRowKeysBuffer.value)
|
emit('onSelected', selectedRowKeysBuffer.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSelect(record: any) {
|
function onSelect(record) {
|
||||||
emit('onSelectedRecord', record)
|
emit('onSelectedRecord', record)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +228,7 @@ const reset_search = async () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.assign(params, {
|
Object.assign(params, {
|
||||||
...props.get_params,
|
...props.getParams,
|
||||||
})
|
})
|
||||||
|
|
||||||
router.push({ query: {} }).catch(() => {
|
router.push({ query: {} }).catch(() => {
|
||||||
|
@ -278,19 +236,19 @@ const reset_search = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(params, () => {
|
watch(params, () => {
|
||||||
if (!props.disable_query_params)
|
if (!props.disableQueryParams)
|
||||||
router.push({ query: params })
|
router.push({ query: params })
|
||||||
|
|
||||||
get_list()
|
get_list()
|
||||||
})
|
})
|
||||||
|
|
||||||
const rowSelection = computed(() => {
|
const rowSelection = computed(() => {
|
||||||
if (batchColumns.length > 0 || props.selectionType) {
|
if (batchColumns.value.length > 0 || props.selectionType) {
|
||||||
return {
|
return {
|
||||||
selectedRowKeys: selectedRowKeysBuffer.value,
|
selectedRowKeys: selectedRowKeysBuffer.value,
|
||||||
onChange: onSelectChange,
|
onChange: onSelectChange,
|
||||||
onSelect,
|
onSelect,
|
||||||
type: batchColumns.length > 0 ? 'checkbox' : props.selectionType,
|
type: batchColumns.value.length > 0 ? 'checkbox' : props.selectionType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -298,188 +256,27 @@ const rowSelection = computed(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const fn = _.get
|
|
||||||
|
|
||||||
async function export_csv() {
|
|
||||||
const header = []
|
|
||||||
const headerKeys: any[] = []
|
|
||||||
const showColumnsMap: any = {}
|
|
||||||
|
|
||||||
for (const showColumnsKey in pithyColumns) {
|
|
||||||
if (pithyColumns[showColumnsKey].dataIndex === 'action')
|
|
||||||
continue
|
|
||||||
|
|
||||||
let t = pithyColumns[showColumnsKey].title
|
|
||||||
|
|
||||||
if (typeof t === 'function')
|
|
||||||
t = t()
|
|
||||||
|
|
||||||
header.push({
|
|
||||||
title: t,
|
|
||||||
|
|
||||||
key: pithyColumns[showColumnsKey].dataIndex,
|
|
||||||
})
|
|
||||||
|
|
||||||
headerKeys.push(pithyColumns[showColumnsKey].dataIndex)
|
|
||||||
|
|
||||||
showColumnsMap[pithyColumns[showColumnsKey].dataIndex] = pithyColumns[showColumnsKey]
|
|
||||||
}
|
|
||||||
|
|
||||||
let dataSource: any = []
|
|
||||||
let hasMore = true
|
|
||||||
let page = 1
|
|
||||||
while (hasMore) {
|
|
||||||
// 准备 DataSource
|
|
||||||
await props.api!.get_list({ page }).then((response: any) => {
|
|
||||||
if (response.data.length === 0) {
|
|
||||||
hasMore = false
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (response[props.data_key] === undefined)
|
|
||||||
dataSource = dataSource.concat(...response.data)
|
|
||||||
else
|
|
||||||
dataSource = dataSource.concat(...response[props.data_key])
|
|
||||||
}).catch((e: any) => {
|
|
||||||
message.error(e.message ?? $gettext('Server error'))
|
|
||||||
hasMore = false
|
|
||||||
})
|
|
||||||
page += 1
|
|
||||||
}
|
|
||||||
const data: any[] = []
|
|
||||||
|
|
||||||
dataSource.forEach((row: Object) => {
|
|
||||||
const obj: any = {}
|
|
||||||
|
|
||||||
headerKeys.forEach(key => {
|
|
||||||
let data = fn(row, key)
|
|
||||||
const c = showColumnsMap[key]
|
|
||||||
|
|
||||||
data = c?.customRender?.({ text: data }) ?? data
|
|
||||||
obj[c.dataIndex] = data
|
|
||||||
})
|
|
||||||
data.push(obj)
|
|
||||||
})
|
|
||||||
|
|
||||||
downloadCsv(header, data,
|
|
||||||
`${$gettext('Export')}-${dayjs().format('YYYYMMDDHHmmss')}.csv`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasSelectedRow = computed(() => {
|
const hasSelectedRow = computed(() => {
|
||||||
return batchColumns.length > 0 && selectedRowKeysBuffer.value.length > 0
|
return batchColumns.value.length > 0 && selectedRowKeysBuffer.value.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
function click_batch_edit() {
|
function clickBatchEdit() {
|
||||||
emit('clickBatchModify', batchColumns, selectedRowKeysBuffer.value)
|
emit('clickBatchModify', batchColumns.value, selectedRowKeysBuffer.value)
|
||||||
}
|
|
||||||
|
|
||||||
function getLeastIndex(index: number) {
|
|
||||||
return index >= 1 ? index : 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTargetData(data: any, indexList: number[]): any {
|
|
||||||
let target: any = { children: data }
|
|
||||||
indexList.forEach((index: number) => {
|
|
||||||
target.children[index].parent = target
|
|
||||||
target = target.children[index]
|
|
||||||
})
|
|
||||||
|
|
||||||
return target
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initSortable() {
|
function initSortable() {
|
||||||
const table: any = document.querySelector('#std-table tbody')
|
useSortable(props, randomId, dataSource, rowsKeyIndexMap, expandKeysList)
|
||||||
|
|
||||||
new Sortable(table, {
|
|
||||||
handle: '.ant-table-drag-icon',
|
|
||||||
animation: 150,
|
|
||||||
sort: true,
|
|
||||||
forceFallback: true,
|
|
||||||
setData(dataTransfer) {
|
|
||||||
dataTransfer.setData('Text', '')
|
|
||||||
},
|
|
||||||
onStart({ item }) {
|
|
||||||
const targetRowKey = Number(item.dataset.rowKey)
|
|
||||||
if (targetRowKey)
|
|
||||||
expand_keys_list.value = expand_keys_list.value.filter((item: number) => item !== targetRowKey)
|
|
||||||
},
|
|
||||||
onMove({ dragged, related }) {
|
|
||||||
const oldRow: number[] = rows_key_index_map.value?.[Number(dragged.dataset.rowKey)]
|
|
||||||
const newRow: number[] = rows_key_index_map.value?.[Number(related.dataset.rowKey)]
|
|
||||||
if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] != newRow[newRow.length - 2])
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
async onEnd({ item, newIndex, oldIndex }) {
|
|
||||||
if (newIndex === oldIndex)
|
|
||||||
return
|
|
||||||
|
|
||||||
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
|
||||||
const direction: number = indexDelta > 0 ? +1 : -1
|
|
||||||
|
|
||||||
const rowIndex: number[] = rows_key_index_map.value?.[Number(item.dataset.rowKey)]
|
|
||||||
const newRow = getTargetData(data_source.value, rowIndex)
|
|
||||||
const newRowParent = newRow.parent
|
|
||||||
const level: number = newRow.level
|
|
||||||
|
|
||||||
const currentRowIndex: number[] = [...rows_key_index_map.value?.
|
|
||||||
[Number(table.children[Number(newIndex) + direction].dataset.rowKey)]]
|
|
||||||
|
|
||||||
const currentRow: any = getTargetData(data_source.value, currentRowIndex)
|
|
||||||
|
|
||||||
// Reset parent
|
|
||||||
currentRow.parent = newRow.parent = null
|
|
||||||
newRowParent.children.splice(rowIndex[level], 1)
|
|
||||||
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
|
||||||
|
|
||||||
const changeIds: number[] = []
|
|
||||||
|
|
||||||
function processChanges(row: any, children: boolean = false, newIndex: number | undefined = undefined) {
|
|
||||||
// Build changes ID list expect new row
|
|
||||||
if (children || newIndex === undefined)
|
|
||||||
changeIds.push(row.id)
|
|
||||||
|
|
||||||
if (newIndex !== undefined)
|
|
||||||
rows_key_index_map.value[row.id][level] = newIndex
|
|
||||||
else if (children)
|
|
||||||
rows_key_index_map.value[row.id][level] += direction
|
|
||||||
|
|
||||||
row.parent = null
|
|
||||||
if (row.children)
|
|
||||||
row.children.forEach((v: any) => processChanges(v, true, newIndex))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace row index for new row
|
|
||||||
processChanges(newRow, false, currentRowIndex[level])
|
|
||||||
|
|
||||||
// Rebuild row index maps for changes row
|
|
||||||
for (let i = Number(oldIndex); i != newIndex; i -= direction) {
|
|
||||||
const rowIndex: number[] = rows_key_index_map.value?.[table.children[i].dataset.rowKey]
|
|
||||||
|
|
||||||
rowIndex[level] += direction
|
|
||||||
processChanges(getTargetData(data_source.value, rowIndex))
|
|
||||||
}
|
|
||||||
console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
|
||||||
', changes IDs:', changeIds)
|
|
||||||
|
|
||||||
props.api!.update_order({
|
|
||||||
target_id: newRow.id,
|
|
||||||
direction,
|
|
||||||
affected_ids: changeIds,
|
|
||||||
}).then(() => {
|
|
||||||
message.success($gettext('Updated successfully'))
|
|
||||||
}).catch((e: any) => {
|
|
||||||
message.error(e?.message ?? $gettext('Server error'))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function export_csv() {
|
||||||
|
exportCsvHandler(props, pithyColumns)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="std-table">
|
<div class="std-table">
|
||||||
<StdDataEntry
|
<StdDataEntry
|
||||||
v-if="!disable_search && searchColumns.length"
|
v-if="!disableSearch && searchColumns.length"
|
||||||
:data-list="searchColumns"
|
:data-list="searchColumns"
|
||||||
:data-source="params"
|
:data-source="params"
|
||||||
layout="inline"
|
layout="inline"
|
||||||
|
@ -487,7 +284,7 @@ function initSortable() {
|
||||||
<template #action>
|
<template #action>
|
||||||
<ASpace class="action-btn">
|
<ASpace class="action-btn">
|
||||||
<AButton
|
<AButton
|
||||||
v-if="exportCsv"
|
v-if="props.exportCsv"
|
||||||
type="primary"
|
type="primary"
|
||||||
ghost
|
ghost
|
||||||
@click="export_csv"
|
@click="export_csv"
|
||||||
|
@ -499,7 +296,7 @@ function initSortable() {
|
||||||
</AButton>
|
</AButton>
|
||||||
<AButton
|
<AButton
|
||||||
v-if="hasSelectedRow"
|
v-if="hasSelectedRow"
|
||||||
@click="click_batch_edit"
|
@click="clickBatchEdit"
|
||||||
>
|
>
|
||||||
{{ $gettext('Batch Modify') }}
|
{{ $gettext('Batch Modify') }}
|
||||||
</AButton>
|
</AButton>
|
||||||
|
@ -509,36 +306,36 @@ function initSortable() {
|
||||||
<ATable
|
<ATable
|
||||||
id="std-table"
|
id="std-table"
|
||||||
:columns="pithyColumns"
|
:columns="pithyColumns"
|
||||||
:data-source="data_source"
|
:data-source="dataSource"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:row-key="rowKey"
|
:row-key="rowKey"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
:scroll="{ x: scrollX }"
|
:scroll="{ x: scrollX }"
|
||||||
:size="size"
|
:size="size"
|
||||||
:expanded-row-keys="expand_keys_list"
|
:expanded-row-keys="expandKeysList"
|
||||||
@change="stdChange"
|
@change="orderPaginationChange"
|
||||||
@expandedRowsChange="expandedTable"
|
@expanded-rows-change="expandedTable"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ text, record, index, column }">
|
<template #bodyCell="{ text, record, column }">
|
||||||
<template v-if="column.handle === true">
|
<template v-if="column.handle === true">
|
||||||
<span class="ant-table-drag-icon"><HolderOutlined /></span>
|
<span class="ant-table-drag-icon"><HolderOutlined /></span>
|
||||||
{{ text }}
|
{{ text }}
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.dataIndex === 'action'">
|
<template v-if="column.dataIndex === 'action'">
|
||||||
<AButton
|
<AButton
|
||||||
v-if="props.editable"
|
v-if="!props.disabledModify"
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
@click="$emit('clickEdit', record[props.rowKey], record)"
|
@click="$emit('clickEdit', record[props.rowKey], record)"
|
||||||
>
|
>
|
||||||
{{ props.edit_text || $gettext('Modify') }}
|
{{ $gettext('Modify') }}
|
||||||
</AButton>
|
</AButton>
|
||||||
<slot
|
<slot
|
||||||
name="actions"
|
name="actions"
|
||||||
:record="record"
|
:record="record"
|
||||||
/>
|
/>
|
||||||
<template v-if="props.deletable">
|
<template v-if="!props.disableDelete">
|
||||||
<ADivider type="vertical" />
|
<ADivider type="vertical" />
|
||||||
<APopconfirm
|
<APopconfirm
|
||||||
:cancel-text="$gettext('No')"
|
:cancel-text="$gettext('No')"
|
||||||
|
@ -561,7 +358,7 @@ function initSortable() {
|
||||||
:size="size"
|
:size="size"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="get_list"
|
@change="get_list"
|
||||||
@changePageSize="stdChange"
|
@change-page-size="orderPaginationChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import StdTable from './StdTable.vue'
|
||||||
|
import StdCurd from './StdCurd.vue'
|
||||||
|
import StdBatchEdit from './StdBatchEdit.vue'
|
||||||
|
|
||||||
|
export {
|
||||||
|
StdTable,
|
||||||
|
StdCurd,
|
||||||
|
StdBatchEdit,
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import type { ComputedRef } from 'vue'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { downloadCsv } from '@/lib/helper'
|
||||||
|
import type { Column, StdTableResponse } from '@/components/StdDesign/types'
|
||||||
|
import gettext from '@/gettext'
|
||||||
|
import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||||
|
|
||||||
|
const { $gettext } = gettext
|
||||||
|
async function exportCsv(props: StdTableProps, pithyColumns: ComputedRef<Column[]>) {
|
||||||
|
const header: { title?: string; key: string }[] = []
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const headerKeys: any[] = []
|
||||||
|
const showColumnsMap: Record<string, Column> = {}
|
||||||
|
|
||||||
|
pithyColumns.value.forEach((column: Column) => {
|
||||||
|
if (column.dataIndex === 'action')
|
||||||
|
return
|
||||||
|
let t = column.title
|
||||||
|
if (typeof t === 'function')
|
||||||
|
t = t()
|
||||||
|
header.push({
|
||||||
|
title: t,
|
||||||
|
key: column.dataIndex,
|
||||||
|
})
|
||||||
|
headerKeys.push(column.dataIndex)
|
||||||
|
showColumnsMap[column.dataIndex] = column
|
||||||
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const dataSource: any[] = []
|
||||||
|
let hasMore = true
|
||||||
|
let page = 1
|
||||||
|
while (hasMore) {
|
||||||
|
// 准备 DataSource
|
||||||
|
await props.api!.get_list({ page }).then((r: StdTableResponse) => {
|
||||||
|
if (r.data.length === 0) {
|
||||||
|
hasMore = false
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dataSource.push(...r.data)
|
||||||
|
}).catch((e: { message?: string }) => {
|
||||||
|
message.error(e.message ?? $gettext('Server error'))
|
||||||
|
hasMore = false
|
||||||
|
})
|
||||||
|
page += 1
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const data: any[] = []
|
||||||
|
|
||||||
|
dataSource.forEach(row => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const obj: Record<string, any> = {}
|
||||||
|
|
||||||
|
headerKeys.forEach(key => {
|
||||||
|
let _data = _.get(row, key)
|
||||||
|
const c = showColumnsMap[key]
|
||||||
|
|
||||||
|
_data = c?.customRender?.({ text: _data }) ?? _data
|
||||||
|
obj[c.dataIndex] = _data
|
||||||
|
})
|
||||||
|
data.push(obj)
|
||||||
|
})
|
||||||
|
|
||||||
|
downloadCsv(header, data,
|
||||||
|
`${$gettext('Export')}-${props.title}-${dayjs().format('YYYYMMDDHHmmss')}.csv`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default exportCsv
|
132
app/src/components/StdDesign/StdDataDisplay/methods/sortable.ts
Normal file
132
app/src/components/StdDesign/StdDataDisplay/methods/sortable.ts
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
import SortableJs from 'sortablejs'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
import gettext from '@/gettext'
|
||||||
|
import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||||
|
|
||||||
|
const { $gettext } = gettext
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function getRowKey(item: any) {
|
||||||
|
return item.children[0].children[0].dataset.rowKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function getTargetData(data: any, indexList: number[]): any {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
let target: any = { children: data }
|
||||||
|
indexList.forEach((index: number) => {
|
||||||
|
target.children[index].parent = target
|
||||||
|
target = target.children[index]
|
||||||
|
})
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function useSortable(props: StdTableProps, randomId: Ref<string>, dataSource: Ref<any[]>,
|
||||||
|
rowsKeyIndexMap: Ref<Record<number, number[]>>, expandKeysList: Ref<number[]>) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const table: any = document.querySelector(`#std-table-${randomId.value} tbody`)
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-new
|
||||||
|
new SortableJs(table, {
|
||||||
|
handle: '.table-drag-icon',
|
||||||
|
animation: 150,
|
||||||
|
sort: true,
|
||||||
|
forceFallback: true,
|
||||||
|
setData(dataTransfer) {
|
||||||
|
dataTransfer.setData('Text', '')
|
||||||
|
},
|
||||||
|
onStart({ item }) {
|
||||||
|
const targetRowKey = Number(getRowKey(item))
|
||||||
|
if (targetRowKey)
|
||||||
|
expandKeysList.value = expandKeysList.value.filter((_item: number) => _item !== targetRowKey)
|
||||||
|
},
|
||||||
|
onMove({
|
||||||
|
dragged,
|
||||||
|
related,
|
||||||
|
}) {
|
||||||
|
const oldRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(dragged))]
|
||||||
|
const newRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(related))]
|
||||||
|
|
||||||
|
if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] !== newRow[newRow.length - 2])
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (props.sortableMoveHook)
|
||||||
|
return props.sortableMoveHook(oldRow, newRow)
|
||||||
|
},
|
||||||
|
async onEnd({
|
||||||
|
item,
|
||||||
|
newIndex,
|
||||||
|
oldIndex,
|
||||||
|
}) {
|
||||||
|
if (newIndex === oldIndex)
|
||||||
|
return
|
||||||
|
|
||||||
|
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
||||||
|
const direction: number = indexDelta > 0 ? +1 : -1
|
||||||
|
|
||||||
|
const rowIndex: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(item))]
|
||||||
|
const newRow = getTargetData(dataSource.value, rowIndex)
|
||||||
|
const newRowParent = newRow.parent
|
||||||
|
const level: number = newRow.level
|
||||||
|
|
||||||
|
const currentRowIndex: number[] = [...rowsKeyIndexMap.value?.
|
||||||
|
[Number(getRowKey(table.children[Number(newIndex) + direction]))]]
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const currentRow: any = getTargetData(dataSource.value, currentRowIndex)
|
||||||
|
|
||||||
|
// Reset parent
|
||||||
|
currentRow.parent = newRow.parent = null
|
||||||
|
newRowParent.children.splice(rowIndex[level], 1)
|
||||||
|
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
||||||
|
|
||||||
|
const changeIds: number[] = []
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function processChanges(row: any, children = false, _newIndex: number | undefined = undefined) {
|
||||||
|
// Build changes ID list expect new row
|
||||||
|
if (children || _newIndex === undefined)
|
||||||
|
changeIds.push(row.id)
|
||||||
|
|
||||||
|
if (_newIndex !== undefined)
|
||||||
|
rowsKeyIndexMap.value[row.id][level] = _newIndex
|
||||||
|
else if (children)
|
||||||
|
rowsKeyIndexMap.value[row.id][level] += direction
|
||||||
|
|
||||||
|
row.parent = null
|
||||||
|
if (row.children) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
row.children.forEach((v: any) => processChanges(v, true, _newIndex))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace row index for new row
|
||||||
|
processChanges(newRow, false, currentRowIndex[level])
|
||||||
|
|
||||||
|
// Rebuild row index maps for changes row
|
||||||
|
for (let i = Number(oldIndex); i !== newIndex; i -= direction) {
|
||||||
|
const _rowIndex: number[] = rowsKeyIndexMap.value?.[getRowKey(table.children[i])]
|
||||||
|
|
||||||
|
_rowIndex[level] += direction
|
||||||
|
processChanges(getTargetData(dataSource.value, _rowIndex))
|
||||||
|
}
|
||||||
|
console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
||||||
|
', changes IDs:', changeIds)
|
||||||
|
|
||||||
|
props.api.update_order({
|
||||||
|
target_id: newRow.id,
|
||||||
|
direction,
|
||||||
|
affected_ids: changeIds,
|
||||||
|
}).then(() => {
|
||||||
|
message.success($gettext('Updated successfully'))
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
}).catch((e: any) => {
|
||||||
|
message.error(e?.message ?? $gettext('Server error'))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSortable
|
|
@ -1,54 +0,0 @@
|
||||||
import { defineComponent } from 'vue'
|
|
||||||
import { Form } from 'ant-design-vue'
|
|
||||||
import StdFormItem from '@/components/StdDesign/StdDataEntry/StdFormItem.vue'
|
|
||||||
import './style.less'
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
dataList: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
dataSource: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ['update:dataSource'],
|
|
||||||
setup(props, { slots }) {
|
|
||||||
return () => {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const template: any = []
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
props.dataList.forEach((v: any) => {
|
|
||||||
let show = true
|
|
||||||
if (v.edit.show) {
|
|
||||||
if (typeof v.edit.show === 'boolean')
|
|
||||||
show = v.edit.show
|
|
||||||
else if (typeof v.edit.show === 'function')
|
|
||||||
show = v.edit.show(props.dataSource)
|
|
||||||
}
|
|
||||||
if (v.edit.type && show) {
|
|
||||||
template.push(<StdFormItem dataIndex={v.dataIndex} label={v.title()} extra={v.extra} error={props.error}>
|
|
||||||
{v.edit.type(v.edit, props.dataSource, v.dataIndex)}
|
|
||||||
</StdFormItem>,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (slots.action)
|
|
||||||
template.push(<div class={'std-data-entry-action'}>{slots.action()}</div>)
|
|
||||||
|
|
||||||
return <Form layout={props.layout || 'vertical'}>{template}</Form>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
83
app/src/components/StdDesign/StdDataEntry/StdDataEntry.vue
Normal file
83
app/src/components/StdDesign/StdDataEntry/StdDataEntry.vue
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { Form } from 'ant-design-vue'
|
||||||
|
import type { Column } from '@/components/StdDesign/types'
|
||||||
|
import StdFormItem from '@/components/StdDesign/StdDataEntry/StdFormItem.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
dataList: Column[]
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
dataSource: Record<string, any>
|
||||||
|
errors?: Record<string, string>
|
||||||
|
layout?: 'horizontal' | 'vertical'
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
'update:dataSource': (v: any[]) => void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const dataSource = computed({
|
||||||
|
get() {
|
||||||
|
return props.dataSource
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
emit('update:dataSource', v)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const slots = useSlots()
|
||||||
|
|
||||||
|
function labelRender(title?: string | (() => string)) {
|
||||||
|
if (typeof title === 'function')
|
||||||
|
return title()
|
||||||
|
|
||||||
|
return title
|
||||||
|
}
|
||||||
|
|
||||||
|
function extraRender(extra?: string | (() => string)) {
|
||||||
|
if (typeof extra === 'function')
|
||||||
|
return extra()
|
||||||
|
|
||||||
|
return extra
|
||||||
|
}
|
||||||
|
|
||||||
|
function Render() {
|
||||||
|
const template = []
|
||||||
|
|
||||||
|
props.dataList.forEach((v: Column) => {
|
||||||
|
let show = true
|
||||||
|
if (v.edit?.show && typeof v.edit.show === 'function')
|
||||||
|
show = v.edit.show(props.dataSource)
|
||||||
|
|
||||||
|
if (v.edit?.type && show) {
|
||||||
|
template.push(<StdFormItem
|
||||||
|
dataIndex={v.dataIndex}
|
||||||
|
label={labelRender(v.title)}
|
||||||
|
extra={extraRender(v.extra)}
|
||||||
|
error={props.errors}>
|
||||||
|
{v.edit.type(v.edit, dataSource.value, v.dataIndex)}
|
||||||
|
</StdFormItem>,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (slots.action)
|
||||||
|
template.push(<div class={'std-data-entry-action'}>{slots.action()}</div>)
|
||||||
|
|
||||||
|
return <Form layout={props.layout || 'vertical'}>{template}</Form>
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Render />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.std-data-entry-action {
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,6 +2,7 @@
|
||||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||||
import gettext from '@/gettext'
|
import gettext from '@/gettext'
|
||||||
import type Curd from '@/api/curd'
|
import type Curd from '@/api/curd'
|
||||||
|
import type { Column } from '@/components/StdDesign/types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
selectedKey: string | number
|
selectedKey: string | number
|
||||||
|
@ -10,7 +11,7 @@ const props = defineProps<{
|
||||||
selectionType: 'radio' | 'checkbox'
|
selectionType: 'radio' | 'checkbox'
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
api: Curd<any>
|
api: Curd<any>
|
||||||
columns: any[]
|
columns: Column[]
|
||||||
dataKey: string
|
dataKey: string
|
||||||
disableSearch: boolean
|
disableSearch: boolean
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { Input, InputNumber, Switch, Textarea } from 'ant-design-vue'
|
import { Input, InputNumber, Switch, Textarea } from 'ant-design-vue'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import StdDataEntry from './StdDataEntry'
|
import StdDataEntry from './StdDataEntry.vue'
|
||||||
import StdSelector from './components/StdSelector.vue'
|
import StdSelector from './components/StdSelector.vue'
|
||||||
import StdSelect from './components/StdSelect.vue'
|
import StdSelect from './components/StdSelect.vue'
|
||||||
import StdPassword from './components/StdPassword.vue'
|
import StdPassword from './components/StdPassword.vue'
|
||||||
|
|
50
app/src/components/StdDesign/types.d.ts
vendored
50
app/src/components/StdDesign/types.d.ts
vendored
|
@ -1,10 +1,13 @@
|
||||||
import Curd from '@/api/curd'
|
import Curd, {Pagination} from '@/api/curd'
|
||||||
import {IKeyEvt} from '@/components/StdDesign/StdDataDisplay/types'
|
import { Ref } from 'vue'
|
||||||
import {Ref} from 'vue'
|
|
||||||
|
|
||||||
export interface StdDesignEdit {
|
export interface StdDesignEdit {
|
||||||
type?: function // component type
|
type?: function // component type
|
||||||
|
|
||||||
|
show?: function // show component
|
||||||
|
|
||||||
|
batch?: boolean // batch edit
|
||||||
|
|
||||||
mask?: {
|
mask?: {
|
||||||
[key: string]: () => string
|
[key: string]: () => string
|
||||||
} // use for select-option
|
} // use for select-option
|
||||||
|
@ -39,7 +42,6 @@ export interface StdDesignEdit {
|
||||||
flex?: Flex
|
flex?: Flex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Flex {
|
export interface Flex {
|
||||||
sm?: string | number | boolean
|
sm?: string | number | boolean
|
||||||
md?: string | number | boolean
|
md?: string | number | boolean
|
||||||
|
@ -47,3 +49,43 @@ export interface Flex {
|
||||||
xl?: string | number | boolean
|
xl?: string | number | boolean
|
||||||
xxl?: string | number | boolean
|
xxl?: string | number | boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Column {
|
||||||
|
title?: string | (() => string);
|
||||||
|
dataIndex: string;
|
||||||
|
edit?: StdDesignEdit;
|
||||||
|
customRender?: function;
|
||||||
|
extra?: string | (() => string);
|
||||||
|
pithy?: boolean;
|
||||||
|
search?: boolean | StdDesignEdit;
|
||||||
|
sortable?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
|
width?: string | number;
|
||||||
|
handle?: boolean;
|
||||||
|
hiddenInTrash?: boolean;
|
||||||
|
hiddenInCreate?: boolean;
|
||||||
|
hiddenInModify?: boolean;
|
||||||
|
batch?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface StdTableProvideData {
|
||||||
|
displayColumns: Column[];
|
||||||
|
pithyColumns: Column[];
|
||||||
|
columnsMap: { [key: string]: Column };
|
||||||
|
displayKeys: string[];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
editItem: (id: number, data: any, index: string | number) => void;
|
||||||
|
deleteItem: (id: number, index: string | number) => void;
|
||||||
|
recoverItem: (id: number) => {};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
params: any;
|
||||||
|
dataSource: any;
|
||||||
|
get_list: () => void;
|
||||||
|
loading: Ref<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StdTableResponse {
|
||||||
|
data: any[]
|
||||||
|
pagination: Pagination
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
|
||||||
name: 'BaseRouterView',
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
defineProps<{
|
||||||
name: 'Loading',
|
loading: boolean | string
|
||||||
props: {
|
}>()
|
||||||
loading: {
|
|
||||||
type: [Boolean, String],
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":"2.0.0-beta.4","build_id":53,"total_build":257}
|
{"version":"2.0.0-beta.4","build_id":56,"total_build":260}
|
|
@ -97,7 +97,7 @@ function handle_uptime(t: number) {
|
||||||
uptime.value = `${uptime_days}d ${uptime_hours}h ${Math.floor(_uptime / 60)}m`
|
uptime.value = `${uptime_days}d ${uptime_hours}h ${Math.floor(_uptime / 60)}m`
|
||||||
}
|
}
|
||||||
|
|
||||||
function wsOnMessage(m: { data: any }) {
|
function wsOnMessage(m) {
|
||||||
const r = JSON.parse(m.data)
|
const r = JSON.parse(m.data)
|
||||||
|
|
||||||
const cpu_usage = r.cpu.system + r.cpu.user
|
const cpu_usage = r.cpu.system + r.cpu.user
|
||||||
|
|
|
@ -5,7 +5,25 @@ import memory from '@/assets/svg/memory.svg'
|
||||||
import { bytesToSize } from '@/lib/helper'
|
import { bytesToSize } from '@/lib/helper'
|
||||||
import UsageProgressLine from '@/components/Chart/UsageProgressLine.vue'
|
import UsageProgressLine from '@/components/Chart/UsageProgressLine.vue'
|
||||||
|
|
||||||
defineProps(['item'])
|
defineProps<{
|
||||||
|
item: {
|
||||||
|
avg_load: {
|
||||||
|
load1: number
|
||||||
|
load5: number
|
||||||
|
load15: number
|
||||||
|
}
|
||||||
|
network: {
|
||||||
|
bytesSent: number
|
||||||
|
bytesRecv: number
|
||||||
|
}
|
||||||
|
cpu_percent: number
|
||||||
|
cpu_num: number
|
||||||
|
memory_percent: number
|
||||||
|
memory_total: string
|
||||||
|
disk_percent: number
|
||||||
|
disk_total: string
|
||||||
|
}
|
||||||
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -52,10 +52,6 @@ const columns = [{
|
||||||
|
|
||||||
const table = ref()
|
const table = ref()
|
||||||
|
|
||||||
interface Table {
|
|
||||||
get_list(): void
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable(name) {
|
function enable(name) {
|
||||||
domain.enable(name).then(() => {
|
domain.enable(name).then(() => {
|
||||||
message.success($gettext('Enabled successfully'))
|
message.success($gettext('Enabled successfully'))
|
||||||
|
@ -76,9 +72,7 @@ function disable(name) {
|
||||||
|
|
||||||
function destroy(site_name) {
|
function destroy(site_name) {
|
||||||
domain.destroy(site_name).then(() => {
|
domain.destroy(site_name).then(() => {
|
||||||
const t: Table | null = table.value
|
table.value.get_list()
|
||||||
|
|
||||||
t!.get_list()
|
|
||||||
message.success($gettext('Delete site: %{site_name}', { site_name }))
|
message.success($gettext('Delete site: %{site_name}', { site_name }))
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
message.error(e?.message ?? $gettext('Server error'))
|
message.error(e?.message ?? $gettext('Server error'))
|
||||||
|
@ -163,7 +157,7 @@ watch(route, () => {
|
||||||
<SiteDuplicate
|
<SiteDuplicate
|
||||||
v-model:visible="show_duplicator"
|
v-model:visible="show_duplicator"
|
||||||
:name="target"
|
:name="target"
|
||||||
@duplicated="table.get_list()"
|
@duplicated="() => table.get_list()"
|
||||||
/>
|
/>
|
||||||
</ACard>
|
</ACard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,7 +11,7 @@ const this_year = new Date().getFullYear()
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ACard
|
<ACard
|
||||||
style="text-align: center"
|
class="text-center"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
>
|
>
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
|
@ -34,26 +34,23 @@ const this_year = new Date().getFullYear()
|
||||||
Star
|
Star
|
||||||
</GithubButton>
|
</GithubButton>
|
||||||
</div>
|
</div>
|
||||||
<h3 v-translate>
|
<h3>
|
||||||
Project Team
|
{{ $gettext('Project Team') }}
|
||||||
</h3>
|
</h3>
|
||||||
<p><a href="https://jackyu.cn/">@0xJacky</a> <a href="https://blog.kugeek.com/">@Hintay</a></p>
|
<p><a href="https://jackyu.cn/">@0xJacky</a> <a href="https://blog.kugeek.com/">@Hintay</a></p>
|
||||||
<h3 v-translate>
|
<h3>
|
||||||
Build with
|
{{ $gettext('Build with') }}
|
||||||
</h3>
|
</h3>
|
||||||
<p>❤️</p>
|
<p>❤️</p>
|
||||||
<p>Go</p>
|
<p>Go</p>
|
||||||
<p>Gin</p>
|
<p>Gin</p>
|
||||||
<p>Vue3 + Vite + TypeScript</p>
|
<p>Vue3 + Vite + TypeScript</p>
|
||||||
<p>Websocket</p>
|
<p>Websocket</p>
|
||||||
<h3
|
<h3>
|
||||||
v-translate
|
{{ $gettext('License') }}
|
||||||
translate-context="Project"
|
|
||||||
>
|
|
||||||
License
|
|
||||||
</h3>
|
</h3>
|
||||||
<p>GNU General Public License v3.0</p>
|
<p>GNU General Public License v3.0</p>
|
||||||
<p>Copyright © 2020 - {{ this_year }} Nginx UI </p>
|
<p>Copyright © 2020 - {{ this_year }} Nginx UI Team</p>
|
||||||
</ACard>
|
</ACard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -64,14 +61,6 @@ const this_year = new Date().getFullYear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.egg {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-btn {
|
|
||||||
margin: 10px 10px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.star-on-github {
|
.star-on-github {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@ import gettext from '@/gettext'
|
||||||
import user from '@/api/user'
|
import user from '@/api/user'
|
||||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||||
import { input, password } from '@/components/StdDesign/StdDataEntry'
|
import { input, password } from '@/components/StdDesign/StdDataEntry'
|
||||||
|
import type { Column } from '@/components/StdDesign/types'
|
||||||
|
|
||||||
const { $gettext } = gettext
|
const { $gettext } = gettext
|
||||||
|
|
||||||
const columns = [{
|
const columns: Column[] = [{
|
||||||
title: () => $gettext('Username'),
|
title: () => $gettext('Username'),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
sorter: true,
|
sortable: true,
|
||||||
pithy: true,
|
pithy: true,
|
||||||
edit: {
|
edit: {
|
||||||
type: input,
|
type: input,
|
||||||
|
@ -19,25 +20,27 @@ const columns = [{
|
||||||
}, {
|
}, {
|
||||||
title: () => $gettext('Password'),
|
title: () => $gettext('Password'),
|
||||||
dataIndex: 'password',
|
dataIndex: 'password',
|
||||||
sorter: true,
|
sortable: true,
|
||||||
pithy: true,
|
pithy: true,
|
||||||
edit: {
|
edit: {
|
||||||
type: password,
|
type: password,
|
||||||
placeholder: () => $gettext('Leave blank for no change'),
|
config: {
|
||||||
generate: true,
|
placeholder: () => $gettext('Leave blank for no change'),
|
||||||
|
generate: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
display: false,
|
hidden: true,
|
||||||
}, {
|
}, {
|
||||||
title: () => $gettext('Created at'),
|
title: () => $gettext('Created at'),
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
customRender: datetime,
|
customRender: datetime,
|
||||||
sorter: true,
|
sortable: true,
|
||||||
pithy: true,
|
pithy: true,
|
||||||
}, {
|
}, {
|
||||||
title: () => $gettext('Updated at'),
|
title: () => $gettext('Updated at'),
|
||||||
dataIndex: 'updated_at',
|
dataIndex: 'updated_at',
|
||||||
customRender: datetime,
|
customRender: datetime,
|
||||||
sorter: true,
|
sortable: true,
|
||||||
pithy: true,
|
pithy: true,
|
||||||
}, {
|
}, {
|
||||||
title: () => $gettext('Action'),
|
title: () => $gettext('Action'),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
|
@ -20,9 +21,11 @@
|
||||||
"@/*": [
|
"@/*": [
|
||||||
"./src/*"
|
"./src/*"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"types": ["vite/client"]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
"env.d.ts",
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.d.ts",
|
"src/**/*.d.ts",
|
||||||
"src/**/*.tsx",
|
"src/**/*.tsx",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":"2.0.0-beta.4","build_id":53,"total_build":257}
|
{"version":"2.0.0-beta.4","build_id":56,"total_build":260}
|
Loading…
Add table
Add a link
Reference in a new issue