提交 17692dfa authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 f77be006
# VITE_API_URL_WORD = https://zijingebook.ezijing.com/file/
VITE_API_URL_WORD = https://book-admin-web.ezijing.com/api
VITE_API_URL_WORD = https://zijingebook.ezijing.com/api
VITE_API_BASE_API_PREFFIX = /api
# VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com
VITE_API_WEBSOCKET_URL = wss://book-admin-web.ezijing.com/ws
VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com/ws
VITE_API_OPENAI_URL = https://model-platform-skyagents.tiangong.cn
\ No newline at end of file
# VITE_API_URL_WORD = https://zijingebook.ezijing.com/file/
VITE_API_URL_WORD = https://book-admin-web.ezijing.com/api
# VITE_API_URL_WORD = http://ebook-pc.ezijing.com:7419
VITE_API_URL_WORD = https://zijingebook.ezijing.com/api
VITE_API_BASE_API_PREFFIX = /api
# VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com
VITE_API_WEBSOCKET_URL = wss://book-admin-web.ezijing.com/ws
VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com/ws
VITE_API_OPENAI_URL = https://model-platform-skyagents.tiangong.cn
\ No newline at end of file
......@@ -8,7 +8,7 @@
"name": "center-book",
"version": "1.0.0",
"dependencies": {
"@ant-design/icons": "^5.3.7",
"@ant-design/icons": "^5.4.0",
"@chuangkit/chuangkit-design": "^2.0.8",
"@fortaine/fetch-event-source": "^3.0.6",
"@reduxjs/toolkit": "^1.9.7",
......@@ -17,7 +17,7 @@
"@wangeditor/plugin-link-card": "^1.0.0",
"ahooks": "^3.8.0",
"ali-oss": "^6.20.0",
"antd": "^5.18.1",
"antd": "^5.20.6",
"axios": "^1.6.2",
"dayjs": "^1.11.11",
"easy-formula-editor": "^0.0.2-alpha.1",
......@@ -29,7 +29,7 @@
"lodash-es": "^4.17.21",
"qs": "^6.11.2",
"rc-slider-captcha": "^1.3.0",
"react": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.0.13",
"react-redux": "^8.1.3",
......@@ -39,32 +39,34 @@
"xml-formatter": "^3.6.2"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.7.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react": "^7.35.2",
"eslint-plugin-react-hooks": "^4.6.2",
"less": "^4.2.0",
"vite": "^5.3.1",
"vite-plugin-mkcert": "^1.17.5"
"vite": "^5.4.4",
"vite-plugin-mkcert": "^1.17.6"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.18.0"
"@rollup/rollup-linux-x64-gnu": "^4.21.2"
}
},
"node_modules/@ant-design/colors": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.2.tgz",
"integrity": "sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==",
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz",
"integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^3.6.1"
}
},
"node_modules/@ant-design/cssinjs": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.20.0.tgz",
"integrity": "sha512-uG3iWzJxgNkADdZmc6W0Ci3iQAUOvLMcM8SnnmWq3r6JeocACft4ChnY/YWvI2Y+rG/68QBla/O+udke1yH3vg==",
"version": "1.21.1",
"resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.21.1.tgz",
"integrity": "sha512-tyWnlK+XH7Bumd0byfbCiZNK43HEubMoCcu9VxwsAwiHdHTgWa+tMN0/yvxa+e8EzuFP1WdUNNPclRpVtD33lg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.1",
"@emotion/hash": "^0.8.0",
......@@ -72,21 +74,49 @@
"classnames": "^2.3.1",
"csstype": "^3.1.3",
"rc-util": "^5.35.0",
"stylis": "^4.0.13"
"stylis": "^4.3.3"
},
"peerDependencies": {
"react": ">=16.0.0",
"react-dom": ">=16.0.0"
}
},
"node_modules/@ant-design/cssinjs-utils": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.0.3.tgz",
"integrity": "sha512-BrztZZKuoYcJK8uEH40ylBemf/Mu/QPiDos56g2bv6eUoniQkgQHOCOvA3+pncoFO1TaS8xcUCIqGzDA0I+ZVQ==",
"license": "MIT",
"dependencies": {
"@ant-design/cssinjs": "^1.21.0",
"@babel/runtime": "^7.23.2",
"rc-util": "^5.38.0"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
}
},
"node_modules/@ant-design/fast-color": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz",
"integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.7"
},
"engines": {
"node": ">=8.x"
}
},
"node_modules/@ant-design/icons": {
"version": "5.3.7",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.7.tgz",
"integrity": "sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.4.0.tgz",
"integrity": "sha512-QZbWC5xQYexCI5q4/fehSEkchJr5UGtvAJweT743qKUQQGs9IH2DehNLP49DJ3Ii9m9CijD2HN6fNy3WKhIFdA==",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^7.0.0",
"@ant-design/icons-svg": "^4.4.0",
"@babel/runtime": "^7.11.2",
"@babel/runtime": "^7.24.8",
"classnames": "^2.2.6",
"rc-util": "^5.31.1"
},
......@@ -119,9 +149,10 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz",
"integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==",
"version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
"integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
......@@ -149,12 +180,14 @@
"node_modules/@emotion/hash": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==",
"license": "MIT"
},
"node_modules/@emotion/unitless": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==",
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
......@@ -886,6 +919,7 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz",
"integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.4"
},
......@@ -894,12 +928,13 @@
}
},
"node_modules/@rc-component/color-picker": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.3.tgz",
"integrity": "sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz",
"integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==",
"license": "MIT",
"dependencies": {
"@ant-design/fast-color": "^2.0.6",
"@babel/runtime": "^7.23.6",
"@ctrl/tinycolor": "^3.6.1",
"classnames": "^2.2.6",
"rc-util": "^5.38.1"
},
......@@ -925,6 +960,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz",
"integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.0"
},
......@@ -966,10 +1002,29 @@
"react-dom": ">=16.9.0"
}
},
"node_modules/@rc-component/qrcode": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz",
"integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.7",
"classnames": "^2.3.2",
"rc-util": "^5.38.0"
},
"engines": {
"node": ">=8.x"
},
"peerDependencies": {
"react": ">=16.9.0",
"react-dom": ">=16.9.0"
}
},
"node_modules/@rc-component/tour": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.0.tgz",
"integrity": "sha512-h6hyILDwL+In9GAgRobwRWihLqqsD7Uft3fZGrJ7L4EiyCoxbnNYwzPXDfz7vNDhWeVyvAWQJj9fJCzpI4+b4g==",
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz",
"integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.0",
"@rc-component/portal": "^1.0.0-9",
......@@ -986,9 +1041,10 @@
}
},
"node_modules/@rc-component/trigger": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.0.tgz",
"integrity": "sha512-QarBCji02YE9aRFhZgRZmOpXBj0IZutRippsVBv85sxvG4FGk/vRxwAlkn3MS9zK5mwbETd86mAVg2tKqTkdJA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.3.tgz",
"integrity": "sha512-X1oFIpKoXAMXNDYCviOmTfuNuYxE4h5laBsyCqVAVMjNHxoF3/uiyA7XdegK1XbCvBbCZ6P6byWrEoDRpKL8+A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.2",
"@rc-component/portal": "^1.1.0",
......@@ -1037,207 +1093,223 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
"integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz",
"integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
"integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz",
"integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
"integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz",
"integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
"integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz",
"integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
"integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz",
"integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz",
"integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz",
"integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
"integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz",
"integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
"integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz",
"integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz",
"integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz",
"integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
"integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz",
"integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz",
"integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz",
"integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
"integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz",
"integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
"integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz",
"integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
"integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz",
"integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
"integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz",
"integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
"integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz",
"integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
......@@ -1321,7 +1393,8 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/@types/event-emitter": {
"version": "0.3.5",
......@@ -1348,9 +1421,10 @@
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
},
"node_modules/@types/react": {
"version": "18.3.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
"integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==",
"version": "18.3.5",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz",
"integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
......@@ -1949,58 +2023,60 @@
}
},
"node_modules/antd": {
"version": "5.18.1",
"resolved": "https://registry.npmjs.org/antd/-/antd-5.18.1.tgz",
"integrity": "sha512-l762vsoIpA3xsVsbIExlce3hgFgiLdflGEgdo8NFnq17Qq3fHIMJklGzM8WNpdJJ4iUk4FzritmSSnHk0Y5kZA==",
"version": "5.20.6",
"resolved": "https://registry.npmjs.org/antd/-/antd-5.20.6.tgz",
"integrity": "sha512-TZFmNenHlh26DelHCJbkB+x1OVulIKsN1f/CnAd2NxZLysXqRvSuLUeHcgccqAnxTy7B03GZ6i1tocGxPCNjgA==",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^7.0.2",
"@ant-design/cssinjs": "^1.19.1",
"@ant-design/icons": "^5.3.7",
"@ant-design/colors": "^7.1.0",
"@ant-design/cssinjs": "^1.21.0",
"@ant-design/cssinjs-utils": "^1.0.3",
"@ant-design/icons": "^5.4.0",
"@ant-design/react-slick": "~1.1.2",
"@babel/runtime": "^7.24.5",
"@babel/runtime": "^7.24.8",
"@ctrl/tinycolor": "^3.6.1",
"@rc-component/color-picker": "~1.5.3",
"@rc-component/color-picker": "~2.0.1",
"@rc-component/mutate-observer": "^1.1.0",
"@rc-component/tour": "~1.15.0",
"@rc-component/trigger": "^2.2.0",
"@rc-component/qrcode": "~1.0.0",
"@rc-component/tour": "~1.15.1",
"@rc-component/trigger": "^2.2.2",
"classnames": "^2.5.1",
"copy-to-clipboard": "^3.3.3",
"dayjs": "^1.11.10",
"qrcode.react": "^3.1.0",
"rc-cascader": "~3.26.0",
"dayjs": "^1.11.11",
"rc-cascader": "~3.28.1",
"rc-checkbox": "~3.3.0",
"rc-collapse": "~3.7.3",
"rc-dialog": "~9.5.2",
"rc-drawer": "~7.2.0",
"rc-dropdown": "~4.2.0",
"rc-field-form": "~2.2.1",
"rc-field-form": "~2.4.0",
"rc-image": "~7.9.0",
"rc-input": "~1.5.1",
"rc-input-number": "~9.1.0",
"rc-mentions": "~2.14.0",
"rc-menu": "~9.14.0",
"rc-motion": "^2.9.1",
"rc-input": "~1.6.3",
"rc-input-number": "~9.2.0",
"rc-mentions": "~2.15.0",
"rc-menu": "~9.14.1",
"rc-motion": "^2.9.2",
"rc-notification": "~5.6.0",
"rc-pagination": "~4.0.4",
"rc-picker": "~4.5.0",
"rc-pagination": "~4.2.0",
"rc-picker": "~4.6.14",
"rc-progress": "~4.0.0",
"rc-rate": "~2.13.0",
"rc-resize-observer": "^1.4.0",
"rc-segmented": "~2.3.0",
"rc-select": "~14.14.0",
"rc-slider": "~10.6.2",
"rc-select": "~14.15.2",
"rc-slider": "~11.1.5",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
"rc-table": "~7.45.7",
"rc-tabs": "~15.1.0",
"rc-textarea": "~1.7.0",
"rc-tabs": "~15.1.1",
"rc-textarea": "~1.8.1",
"rc-tooltip": "~6.2.0",
"rc-tree": "~5.8.7",
"rc-tree-select": "~5.21.0",
"rc-upload": "~4.5.2",
"rc-util": "^5.41.0",
"rc-tree": "~5.9.0",
"rc-tree-select": "~5.23.0",
"rc-upload": "~4.7.0",
"rc-util": "^5.43.0",
"scroll-into-view-if-needed": "^3.1.0",
"throttle-debounce": "^5.0.0"
"throttle-debounce": "^5.0.2"
},
"funding": {
"type": "opencollective",
......@@ -2120,7 +2196,8 @@
"node_modules/array-tree-filter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==",
"license": "MIT"
},
"node_modules/array-unique": {
"version": "0.3.2",
......@@ -2187,29 +2264,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array.prototype.toreversed": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz",
"integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.2.0",
"es-abstract": "^1.22.1",
"es-shim-unscopables": "^1.0.0"
}
},
"node_modules/array.prototype.tosorted": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz",
"integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
"integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.5",
"call-bind": "^1.0.7",
"define-properties": "^1.2.1",
"es-abstract": "^1.22.3",
"es-errors": "^1.1.0",
"es-abstract": "^1.23.3",
"es-errors": "^1.3.0",
"es-shim-unscopables": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/arraybuffer.prototype.slice": {
......@@ -2331,9 +2400,10 @@
}
},
"node_modules/axios": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
......@@ -3218,11 +3288,12 @@
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "2.1.2"
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
......@@ -3814,35 +3885,36 @@
}
},
"node_modules/eslint-plugin-react": {
"version": "7.34.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz",
"integrity": "sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==",
"version": "7.35.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz",
"integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"array-includes": "^3.1.8",
"array.prototype.findlast": "^1.2.5",
"array.prototype.flatmap": "^1.3.2",
"array.prototype.toreversed": "^1.1.2",
"array.prototype.tosorted": "^1.1.3",
"array.prototype.tosorted": "^1.1.4",
"doctrine": "^2.1.0",
"es-iterator-helpers": "^1.0.19",
"estraverse": "^5.3.0",
"hasown": "^2.0.2",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
"object.entries": "^1.1.8",
"object.fromentries": "^2.0.8",
"object.hasown": "^1.1.4",
"object.values": "^1.2.0",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.5",
"semver": "^6.3.1",
"string.prototype.matchall": "^4.0.11"
"string.prototype.matchall": "^4.0.11",
"string.prototype.repeat": "^1.0.0"
},
"engines": {
"node": ">=4"
},
"peerDependencies": {
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
"node_modules/eslint-plugin-react-hooks": {
......@@ -5971,9 +6043,10 @@
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/mz": {
"version": "2.7.0",
......@@ -6290,23 +6363,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.hasown": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz",
"integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==",
"dev": true,
"dependencies": {
"define-properties": "^1.2.1",
"es-abstract": "^1.23.2",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
......@@ -6704,9 +6760,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"version": "8.4.45",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz",
"integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==",
"dev": true,
"funding": [
{
......@@ -6722,9 +6778,10 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
},
"engines": {
......@@ -6853,14 +6910,6 @@
"node": ">=6"
}
},
"node_modules/qrcode.react": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
"integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/qs": {
"version": "6.12.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
......@@ -6924,15 +6973,16 @@
}
},
"node_modules/rc-cascader": {
"version": "3.26.0",
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.26.0.tgz",
"integrity": "sha512-L1dml383TPSJD1I11YwxuVbmqaJY64psZqFp1ETlgl3LEOwDu76Cyl11fw5dmjJhMlUWwM5dECQfqJgfebhUjg==",
"version": "3.28.1",
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.28.1.tgz",
"integrity": "sha512-9+8oHIMWVLHxuaapDiqFNmD9KSyKN/P4bo9x/MBuDbyTqP8f2/POmmZxdXWBO3yq/uE3pKyQCXYNUxrNfHRv2A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"array-tree-filter": "^2.1.0",
"classnames": "^2.3.1",
"rc-select": "~14.14.0",
"rc-tree": "~5.8.1",
"rc-select": "~14.15.0",
"rc-tree": "~5.9.0",
"rc-util": "^5.37.0"
},
"peerDependencies": {
......@@ -7005,6 +7055,7 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz",
"integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@rc-component/trigger": "^2.0.0",
......@@ -7017,9 +7068,10 @@
}
},
"node_modules/rc-field-form": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.2.1.tgz",
"integrity": "sha512-uoNqDoR7A4tn4QTSqoWPAzrR7ZwOK5I+vuZ/qdcHtbKx+ZjEsTg7QXm2wk/jalDiSksAQmATxL0T5LJkRREdIA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.4.0.tgz",
"integrity": "sha512-XZ/lF9iqf9HXApIHQHqzJK5v2w4mkUMsVqAzOyWVzoiwwXEavY6Tpuw7HavgzIoD+huVff4JghSGcgEfX6eycg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.0",
"@rc-component/async-validator": "^5.0.3",
......@@ -7069,9 +7121,10 @@
}
},
"node_modules/rc-input": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.5.1.tgz",
"integrity": "sha512-+nOzQJDeIfIpNP/SgY45LXSKbuMlp4Yap2y8c+ZpU7XbLmNzUd6+d5/S75sA/52jsVE6S/AkhkkDEAOjIu7i6g==",
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz",
"integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.1",
"classnames": "^2.2.1",
......@@ -7083,14 +7136,15 @@
}
},
"node_modules/rc-input-number": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.1.0.tgz",
"integrity": "sha512-NqJ6i25Xn/AgYfVxynlevIhX3FuKlMwIFpucGG1h98SlK32wQwDK0zhN9VY32McOmuaqzftduNYWWooWz8pXQA==",
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.2.0.tgz",
"integrity": "sha512-5XZFhBCV5f9UQ62AZ2hFbEY8iZT/dm23Q1kAg0H8EvOgD3UDbYYJAayoVIkM3lQaCqYAW5gV0yV3vjw1XtzWHg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"@rc-component/mini-decimal": "^1.0.1",
"classnames": "^2.2.5",
"rc-input": "~1.5.0",
"rc-input": "~1.6.0",
"rc-util": "^5.40.1"
},
"peerDependencies": {
......@@ -7099,16 +7153,17 @@
}
},
"node_modules/rc-mentions": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.14.0.tgz",
"integrity": "sha512-qKR59FMuF8PK4ZqsbWX3UuA5P1M/snzyqV6Yt3y1DCFbCEdqUGIBgQp6vEfLCO6Z0RoRFlzXtCeSlBTcDDpg1A==",
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.15.0.tgz",
"integrity": "sha512-f5v5i7VdqvBDXbphoqcQWmXDif2Msd2arritVoWybrVDuHE6nQ7XCYsybHbV//WylooK52BFDouFvyaRDtXZEw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.22.5",
"@rc-component/trigger": "^2.0.0",
"classnames": "^2.2.6",
"rc-input": "~1.5.0",
"rc-input": "~1.6.0",
"rc-menu": "~9.14.0",
"rc-textarea": "~1.7.0",
"rc-textarea": "~1.8.0",
"rc-util": "^5.34.1"
},
"peerDependencies": {
......@@ -7117,9 +7172,10 @@
}
},
"node_modules/rc-menu": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.0.tgz",
"integrity": "sha512-La3LBCDMLMs9Q/8mTGbnscb+ZeJ26ebkLz9xJFHd2SD8vfsCKl1Z/k3mwbxyKL01lB40fel1s9Nn9LAv/nmVJQ==",
"version": "9.14.1",
"resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.1.tgz",
"integrity": "sha512-5wlRb3M8S4yGlWhSoEYJ7ZVRElyScdcpUHxgiLxkeig1tEdyKrnED3B2fhpN0Rrpdp9jyhnmZR/Lwq2fH5VvDQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"@rc-component/trigger": "^2.0.0",
......@@ -7134,13 +7190,14 @@
}
},
"node_modules/rc-motion": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.1.tgz",
"integrity": "sha512-QD4bUqByjVQs7PhUT1d4bNxvtTcK9ETwtg7psbDfo6TmYalH/1hhjj4r2hbhW7g5OOEqYHhfwfj4noIvuOVRtQ==",
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.2.tgz",
"integrity": "sha512-fUAhHKLDdkAXIDLH0GYwof3raS58dtNUmzLF2MeiR8o6n4thNpSDQhOqQzWE4WfFZDCi9VEN8n7tiB7czREcyw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.1",
"classnames": "^2.2.1",
"rc-util": "^5.39.3"
"rc-util": "^5.43.0"
},
"peerDependencies": {
"react": ">=16.9.0",
......@@ -7169,6 +7226,7 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz",
"integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.1",
"classnames": "^2.2.1",
......@@ -7181,9 +7239,10 @@
}
},
"node_modules/rc-pagination": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.0.4.tgz",
"integrity": "sha512-GGrLT4NgG6wgJpT/hHIpL9nELv27A1XbSZzECIuQBQTVSf4xGKxWr6I/jhpRPauYEWEbWVw22ObG6tJQqwJqWQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.2.0.tgz",
"integrity": "sha512-V6qeANJsT6tmOcZ4XiUmj8JXjRLbkusuufpuoBw2GiAn94fIixYjFLmbruD1Sbhn8fPLDnWawPp4CN37zQorvw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "^2.3.2",
......@@ -7195,16 +7254,17 @@
}
},
"node_modules/rc-picker": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.5.0.tgz",
"integrity": "sha512-suqz9bzuhBQlf7u+bZd1bJLPzhXpk12w6AjQ9BTPTiFwexVZgUKViG1KNLyfFvW6tCUZZK0HmCCX7JAyM+JnCg==",
"version": "4.6.14",
"resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.6.14.tgz",
"integrity": "sha512-7DuTfUFdkxmsNpWQ0TWv6FPGna5e6KKC4nxtx3x9xhumLz7jb3fhlDdWQvqEL6tpt9DOb1+N5j+wB+lDOSS9kg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"@babel/runtime": "^7.24.7",
"@rc-component/trigger": "^2.0.0",
"classnames": "^2.2.1",
"rc-overflow": "^1.3.2",
"rc-resize-observer": "^1.4.0",
"rc-util": "^5.38.1"
"rc-util": "^5.43.0"
},
"engines": {
"node": ">=8.x"
......@@ -7294,9 +7354,10 @@
}
},
"node_modules/rc-select": {
"version": "14.14.0",
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.14.0.tgz",
"integrity": "sha512-Uo2wulrjoPPRLCPd7zlK4ZFVJxlTN//yp1xWP/U+TUOQCyXrT+Duvq/Si5OzVcmQyWAUSbsplc2OwNNhvbOeKQ==",
"version": "14.15.2",
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.15.2.tgz",
"integrity": "sha512-oNoXlaFmpqXYcQDzcPVLrEqS2J9c+/+oJuGrlXeVVX/gVgrbHa5YcyiRUXRydFjyuA7GP3elRuLF7Y3Tfwltlw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"@rc-component/trigger": "^2.1.1",
......@@ -7315,9 +7376,10 @@
}
},
"node_modules/rc-slider": {
"version": "10.6.2",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz",
"integrity": "sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw==",
"version": "11.1.5",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.5.tgz",
"integrity": "sha512-b77H5PbjMKsvkYXAYIkn50QuFX6ICQmCTibDinI9q+BHx65/TV4TeU25+oadhSRzykxs0/vBWeKBwRyySOeWlg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "^2.2.5",
......@@ -7401,9 +7463,10 @@
}
},
"node_modules/rc-tabs": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.0.tgz",
"integrity": "sha512-xTNz4Km1025emtkv1q7xKhjPwAtXr/wycuXVTAcFJg+DKhnPDDbnwbA9KRW0SawAVOGvVEj8ZrBlU0u0FGLrbg==",
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.1.tgz",
"integrity": "sha512-Tc7bJvpEdkWIVCUL7yQrMNBJY3j44NcyWS48jF/UKMXuUlzaXK+Z/pEL5LjGcTadtPvVmNqA40yv7hmr+tCOAw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.2",
"classnames": "2.x",
......@@ -7422,13 +7485,14 @@
}
},
"node_modules/rc-textarea": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.7.0.tgz",
"integrity": "sha512-UxizYJkWkmxP3zofXgc487QiGyDmhhheDLLjIWbFtDmiru1ls30KpO8odDaPyqNUIy9ugj5djxTEuezIn6t3Jg==",
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.1.tgz",
"integrity": "sha512-bm36N2ZqwZAP60ZQg2OY9mPdqWC+m6UTjHc+CqEZOxb3Ia29BGHazY/s5bI8M4113CkqTzhtFUDNA078ZiOx3Q==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "^2.2.1",
"rc-input": "~1.5.0",
"rc-input": "~1.6.0",
"rc-resize-observer": "^1.0.0",
"rc-util": "^5.27.0"
},
......@@ -7452,9 +7516,10 @@
}
},
"node_modules/rc-tree": {
"version": "5.8.7",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.7.tgz",
"integrity": "sha512-cpsIQZ4nNYwpj6cqPRt52e/69URuNdgQF9wZ10InmEf8W3+i0A41OVmZWwHuX9gegQSqj+DPmaDkZFKQZ+ZV1w==",
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.9.0.tgz",
"integrity": "sha512-CPrgOvm9d/9E+izTONKSngNzQdIEjMox2PBufWjS1wf7vxtvmCWzK1SlpHbRY6IaBfJIeZ+88RkcIevf729cRg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
......@@ -7471,14 +7536,15 @@
}
},
"node_modules/rc-tree-select": {
"version": "5.21.0",
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.21.0.tgz",
"integrity": "sha512-w+9qEu6zh0G3wt9N/hzWNSnqYH1i9mH1Nqxo0caxLRRFXF5yZWYmpCDoDTMdQM1Y4z3Q5yj08qyrPH/d4AtumA==",
"version": "5.23.0",
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.23.0.tgz",
"integrity": "sha512-aQGi2tFSRw1WbXv0UVXPzHm09E0cSvUVZMLxQtMv3rnZZpNmdRXWrnd9QkLNlVH31F+X5rgghmdSFF3yZW0N9A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-select": "~14.14.0",
"rc-tree": "~5.8.1",
"rc-select": "~14.15.0",
"rc-tree": "~5.9.0",
"rc-util": "^5.16.1"
},
"peerDependencies": {
......@@ -7487,9 +7553,10 @@
}
},
"node_modules/rc-upload": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.5.2.tgz",
"integrity": "sha512-QO3ne77DwnAPKFn0bA5qJM81QBjQi0e0NHdkvpFyY73Bea2NfITiotqJqVjHgeYPOJu5lLVR32TNGP084aSoXA==",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.7.0.tgz",
"integrity": "sha512-eUwxYNHlsYe5vYhKFAUGrQG95JrnPzY+BmPi1Daq39fWNl/eOc7v4UODuWrVp2LFkQBuV3cMCG/I68iub6oBrg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"classnames": "^2.2.5",
......@@ -7501,9 +7568,10 @@
}
},
"node_modules/rc-util": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.41.0.tgz",
"integrity": "sha512-xtlCim9RpmVv0Ar2Nnc3WfJCxjQkTf3xHPWoFdjp1fSs2NirQwqiQrfqdU9HUe0kdfb168M/T8Dq0IaX50xeKg==",
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz",
"integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"react-is": "^18.2.0"
......@@ -7916,10 +7984,11 @@
}
},
"node_modules/rollup": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
"integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz",
"integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.5"
},
......@@ -7931,38 +8000,25 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.17.2",
"@rollup/rollup-android-arm64": "4.17.2",
"@rollup/rollup-darwin-arm64": "4.17.2",
"@rollup/rollup-darwin-x64": "4.17.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
"@rollup/rollup-linux-arm-musleabihf": "4.17.2",
"@rollup/rollup-linux-arm64-gnu": "4.17.2",
"@rollup/rollup-linux-arm64-musl": "4.17.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
"@rollup/rollup-linux-riscv64-gnu": "4.17.2",
"@rollup/rollup-linux-s390x-gnu": "4.17.2",
"@rollup/rollup-linux-x64-gnu": "4.17.2",
"@rollup/rollup-linux-x64-musl": "4.17.2",
"@rollup/rollup-win32-arm64-msvc": "4.17.2",
"@rollup/rollup-win32-ia32-msvc": "4.17.2",
"@rollup/rollup-win32-x64-msvc": "4.17.2",
"@rollup/rollup-android-arm-eabi": "4.21.2",
"@rollup/rollup-android-arm64": "4.21.2",
"@rollup/rollup-darwin-arm64": "4.21.2",
"@rollup/rollup-darwin-x64": "4.21.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.2",
"@rollup/rollup-linux-arm-musleabihf": "4.21.2",
"@rollup/rollup-linux-arm64-gnu": "4.21.2",
"@rollup/rollup-linux-arm64-musl": "4.21.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.2",
"@rollup/rollup-linux-riscv64-gnu": "4.21.2",
"@rollup/rollup-linux-s390x-gnu": "4.21.2",
"@rollup/rollup-linux-x64-gnu": "4.21.2",
"@rollup/rollup-linux-x64-musl": "4.21.2",
"@rollup/rollup-win32-arm64-msvc": "4.21.2",
"@rollup/rollup-win32-ia32-msvc": "4.21.2",
"@rollup/rollup-win32-x64-msvc": "4.21.2",
"fsevents": "~2.3.2"
}
},
"node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
"integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
......@@ -8395,10 +8451,11 @@
}
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
......@@ -8625,6 +8682,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/string.prototype.repeat": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
"integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
"dev": true,
"license": "MIT",
"dependencies": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
}
},
"node_modules/string.prototype.trim": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
......@@ -8699,9 +8767,10 @@
}
},
"node_modules/stylis": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz",
"integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==",
"license": "MIT"
},
"node_modules/supports-color": {
"version": "7.2.0",
......@@ -8845,9 +8914,10 @@
}
},
"node_modules/throttle-debounce": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
"integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==",
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
"integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==",
"license": "MIT",
"engines": {
"node": ">=12.22"
}
......@@ -9422,14 +9492,15 @@
}
},
"node_modules/vite": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz",
"integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==",
"version": "5.4.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.4.tgz",
"integrity": "sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.38",
"rollup": "^4.13.0"
"postcss": "^8.4.43",
"rollup": "^4.20.0"
},
"bin": {
"vite": "bin/vite.js"
......@@ -9448,6 +9519,7 @@
"less": "*",
"lightningcss": "^1.21.0",
"sass": "*",
"sass-embedded": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
......@@ -9465,6 +9537,9 @@
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"stylus": {
"optional": true
},
......@@ -9477,15 +9552,16 @@
}
},
"node_modules/vite-plugin-mkcert": {
"version": "1.17.5",
"resolved": "https://registry.npmjs.org/vite-plugin-mkcert/-/vite-plugin-mkcert-1.17.5.tgz",
"integrity": "sha512-KKGY3iHx/9zb7ow8JJ+nLN2HiNIBuPBwj34fJ+jAJT89/8qfk7msO7G7qipR8VDEm9xMCys0xT11QOJbZcg3/Q==",
"version": "1.17.6",
"resolved": "https://registry.npmjs.org/vite-plugin-mkcert/-/vite-plugin-mkcert-1.17.6.tgz",
"integrity": "sha512-4JR1RN0HEg/w17eRQJ/Ve2pSa6KCVQcQO6yKtIaKQCFDyd63zGfXHWpygBkvvRSpqa0GcqNKf0fjUJ0HiJQXVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@octokit/rest": "^20.0.2",
"axios": "^1.6.8",
"debug": "^4.3.4",
"picocolors": "^1.0.0"
"@octokit/rest": "^20.1.1",
"axios": "^1.7.4",
"debug": "^4.3.6",
"picocolors": "^1.0.1"
},
"engines": {
"node": ">=v16.7.0"
......
......@@ -11,7 +11,7 @@
"lint": "eslint --ext .js,.jsx,.ts,.tsx --fix --ignore-path .gitignore ./src"
},
"dependencies": {
"@ant-design/icons": "^5.3.7",
"@ant-design/icons": "^5.4.0",
"@chuangkit/chuangkit-design": "^2.0.8",
"@fortaine/fetch-event-source": "^3.0.6",
"@reduxjs/toolkit": "^1.9.7",
......@@ -20,7 +20,7 @@
"@wangeditor/plugin-link-card": "^1.0.0",
"ahooks": "^3.8.0",
"ali-oss": "^6.20.0",
"antd": "^5.18.1",
"antd": "^5.20.6",
"axios": "^1.6.2",
"dayjs": "^1.11.11",
"easy-formula-editor": "^0.0.2-alpha.1",
......@@ -32,7 +32,7 @@
"lodash-es": "^4.17.21",
"qs": "^6.11.2",
"rc-slider-captcha": "^1.3.0",
"react": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.0.13",
"react-redux": "^8.1.3",
......@@ -42,15 +42,15 @@
"xml-formatter": "^3.6.2"
},
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.7.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react": "^7.35.2",
"eslint-plugin-react-hooks": "^4.6.2",
"less": "^4.2.0",
"vite": "^5.3.1",
"vite-plugin-mkcert": "^1.17.5"
"vite": "^5.4.4",
"vite-plugin-mkcert": "^1.17.6"
},
"browserslist": [
"> 1%",
......@@ -58,6 +58,6 @@
"not ie <= 10"
],
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.18.0"
"@rollup/rollup-linux-x64-gnu": "^4.21.2"
}
}
......@@ -52,9 +52,6 @@ dd {
width: 25% !important;
min-width: 475px;
}
.ant-modal .ant-modal-close {
inset-inline-end: initial;
}
.submit {
background: #aa1941;
......@@ -108,7 +105,7 @@ dd {
margin-bottom: 15px;
}
}
.ant-space {
.ant-space {
align-items: flex-start;
}
}
......@@ -139,28 +136,28 @@ dd {
// }
@font-face {
font-family: "思源黑体";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131326219-q886x58lgm.ttf") format('truetype');
font-family: '思源黑体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131326219-q886x58lgm.ttf') format('truetype');
}
@font-face {
font-family: "思源宋体";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131348680-t3miidf3sxs.ttf") format('truetype');
font-family: '思源宋体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131348680-t3miidf3sxs.ttf') format('truetype');
}
@font-face {
font-family: "楷体";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131272079-k30tgmq5m7.ttf") format('truetype');
font-family: '楷体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131272079-k30tgmq5m7.ttf') format('truetype');
}
@font-face {
font-family: "仿宋";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131169707-0x5pgjxiburq.ttf") format('truetype');
font-family: '仿宋';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131169707-0x5pgjxiburq.ttf') format('truetype');
}
@font-face {
font-family: "宋体";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131298815-mogsisbs1vl.ttf") format('truetype');
font-family: '宋体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131298815-mogsisbs1vl.ttf') format('truetype');
}
@font-face {
font-family: "黑体";
src: url("https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131247994-gp497hgawyb.ttf") format('truetype');
font-family: '黑体';
src: url('https://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131247994-gp497hgawyb.ttf') format('truetype');
}
// 仿宋 http://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131169707-0x5pgjxiburq.ttf
......@@ -170,13 +167,14 @@ dd {
// 思源黑体 http://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131326219-q886x58lgm.ttf
// 思源宋体 http://zxts-book-file.zijingebook.com/2024/04/03/fonts-1712131348680-t3miidf3sxs.ttf
.ant-table-wrapper .ant-table-container table>thead>tr:first-child >*:first-child {
.ant-table-wrapper .ant-table-container table > thead > tr:first-child > *:first-child {
border-start-start-radius: 0;
}
.ant-table-wrapper table, .ant-table-wrapper .ant-table .ant-table-header {
.ant-table-wrapper table,
.ant-table-wrapper .ant-table .ant-table-header {
border-radius: 0;
}
.ant-table-wrapper .ant-table-container table>thead>tr:first-child >*:last-child {
.ant-table-wrapper .ant-table-container table > thead > tr:first-child > *:last-child {
border-start-end-radius: 0;
&.ant-table-cell-scrollbar {
background-color: #f5f5f5;
......
import axios from '@/utils/axios'
// 获取教师列表
export function getTeacherList(data) {
return axios.post('/api/user/teacher/getList', data)
}
import { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react'
import { Button, Divider, Space, Modal, Drawer } from 'antd'
import { Button, Divider, Space, Modal } from 'antd'
import { EyeOutlined, SaveOutlined, CloseOutlined, HistoryOutlined } from '@ant-design/icons'
import AliOSS from 'ali-oss'
import dayjs from 'dayjs'
......@@ -161,7 +161,6 @@ const WangEditorCustomer = (props, ref) => {
const [content, setContent] = useState(html)
const saveRef = useRef()
const [selectText, setSelectText] = useState('') //
const [titleVisible, setTitleVisible] = useState(false) // 章头
const [titleInfo, setTitleInfo] = useState({})
const [sectionVisible, setSectionVisible] = useState(false)
......@@ -179,8 +178,6 @@ const WangEditorCustomer = (props, ref) => {
const [expandVisible, setExpandVisible] = useState(false) // 扩展阅读
const [expandInfo, setExpandInfo] = useState({}) // 扩展阅读内容
const [aiVisible, setAIVisible] = useState(false) // ai对话弹窗
const [priviewVisible, setPreviewVisible] = useState(false)
const [historyVisible, setHistoryVisible] = useState(false) //点击历史
......@@ -437,7 +434,7 @@ const WangEditorCustomer = (props, ref) => {
}, 50)
}
editorConfig.onFocus = editor => {
editorConfig.onFocus = () => {
clearTimeout(saveRef.current)
}
editorConfig.onBlur = editor => {
......@@ -536,9 +533,7 @@ const WangEditorCustomer = (props, ref) => {
let info = {}
for (let nodeEntry of nodeEntries) {
const [node, path] = nodeEntry
// console.log('选中了 paragraph 节点', node)
// console.log('节点 path 是', path)
node.children.forEach((item, index) => {
node.children.forEach(item => {
if (item.type === 'image') {
info.image = item
}
......@@ -572,12 +567,6 @@ const WangEditorCustomer = (props, ref) => {
setExpandVisible(true)
})
// ai对话
editor.on('AISelectTextClick', () => {
setSelectText(editor.getSelectionText())
setAIVisible(true)
})
editor.addMark('fontSize', '18px')
editor.addMark('fontFamily', '黑体')
editor.addMark('lineHeight', 1.5)
......
import { useRef, useState } from 'react';
const useWebsocket = ({}) => {
const ws = useRef();
const [wsMessage, setWsMessage] = useState({});
const [wsReadyState, setWsReadyState] = useState({ key: 0, value: '正在连接中' });
const createWebSocket = (url) => {
const stateArr = [
{ key: 0, value: '正在连接中' },
{ key: 1, value: '已经连接并且可以通讯' },
{ key: 2, value: '连接正在关闭' },
{ key: 3, value: '连接已关闭或者没有连接成功' },
];
try {
ws.current = new WebSocket(url);
ws.current.onopen = () => {
console.log('websocket open');
setWsReadyState(stateArr[ws.current?.readyState ?? 0]);
};
ws.current.onclose = () => {
console.log('websocket close');
setWsReadyState(stateArr[ws.current?.readyState ?? 0]);
};
ws.current.onerror = () => {
console.log('websocket error');
setWsReadyState(stateArr[ws.current?.readyState ?? 0]);
};
ws.current.onmessage = (e) => {
console.log('onmessage', e);
setWsMessage(JSON.parse(e.data));
};
} catch (error) {
console.log(error);
}
};
const webSocketInit = (url) => {
if (!ws.current || ws.current.readyState === 3) {
createWebSocket(url);
}
};
// 关闭 WebSocket
const closeWebSocket = () => {
ws.current?.close();
};
// 发送数据
const sendMessage = (str) => {
ws.current?.send(str);
};
//重连
const reconnect = () => {
try {
closeWebSocket();
ws.current = null;
createWebSocket();
} catch (e) {
console.log(e);
}
};
// useEffect(() => {
// webSocketInit();
// return () => {
// ws.current?.close(1000);
// };
// }, [ws]);
return {
webSocketInit,
wsMessage,
setWsMessage,
wsReadyState,
reconnect,
sendMessage,
closeWebSocket,
};
};
export default useWebsocket;
import { useState, useEffect } from 'react'
import { Spin } from 'antd'
import { Editor, Toolbar } from '@wangeditor/editor-for-react'
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import './styles.less'
import { fontFamilyList, fontSizeList, lineHeightList } from '@/common/wangeditor-customer/utils/setting'
import { uploadFile } from '@/utils/oss'
function WangEditorCustomer() {
export default function WangEditor({ value, onChange }) {
// editor 实例
const [editor, setEditor] = useState(null) // JS 语法
// 编辑器内容
const [html, setHtml] = useState('<p>hello</p>')
// 模拟 ajax 请求,异步设置 html
useEffect(() => {
setTimeout(() => {
setHtml('<p>hello world</p>')
}, 1500)
}, [])
const [loading, setLoading] = useState(false)
// 工具栏配置
const toolbarConfig = {
toolbarKeys: [
'redo',
'undo',
'|',
'fontFamily',
'fontSize',
'lineHeight',
'color',
'bold',
'italic',
'through',
'underline',
'bgColor',
'bulletedList',
'numberedList',
'indent',
'delIndent',
'sub',
'sup',
'justifyLeft',
'justifyCenter',
'justifyRight',
'justifyJustify',
'divider',
'|',
'insertTable',
'|',
'codeBlock', // 代码块
'blockquote' // 引用
]
excludeKeys: ['insertVideo', 'insertImage', 'emotion', 'table', 'codeBlock', 'blockquote', 'code', 'group-more-style', 'insertTable'] //删除工具栏
}
// 编辑器配置
const editorConfig = {
placeholder: '请输入内容...'
// JS 语法
placeholder: '请输入内容...',
MENU_CONF: {
// 配置默认字号
fontSize: { fontSizeList },
fontFamily: { fontFamilyList },
lineHeight: { lineHeightList },
// 配置上传图片
uploadImage: {
timeout: 5 * 1000, // 5s
fieldName: 'image',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token') || ''
},
maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 // 用户自定义上传图片
customUpload: async (file, insertFn) => {
setLoading(true)
const url = await uploadFile(file)
insertFn(url, '图片')
setLoading(false)
}
},
uploadVideo: {
timeout: 15 * 1000, // 5s
fieldName: 'video',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token') || ''
},
allowedFileTypes: ['video/mp4', 'video/ogg', 'video/webm'],
maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 // 用户自定义上传图片
customUpload: async (file, insertFn) => {
setLoading(true)
const url = await uploadFile(file)
insertFn(url, '视频')
setLoading(false)
}
}
},
hoverbarKeys: {
image: {
menuKeys: ['imageWidth30', 'imageWidth50', 'imageWidth100', 'deleteImage']
},
text: {
menuKeys: ['headerSelect', 'insertLink', '|', 'bold', 'underline', 'italic', '|', 'color', 'bgColor', 'clearStyle']
}
}
}
useEffect(() => {
return () => {
if (editor === null) return
......@@ -64,52 +78,14 @@ function WangEditorCustomer() {
}
}, [editor])
const onCreated = editor => {
setEditor(editor)
setTimeout(() => {
const editorToolbar = document.querySelector('.editor-toolbar')
// 设置菜单模块标题
const dividerElements = editorToolbar.querySelectorAll('.w-e-bar-divider')
const dividerTitles = ['常用格式', '媒体资源', '高级模块', 'AI辅助', 'AI数字人']
dividerElements.forEach((element, index) => {
element.innerHTML = dividerTitles[index]
})
// 设置菜单标题
const menuButtonElements = editorToolbar.querySelectorAll('.w-e-bar-item button')
menuButtonElements.forEach((element, index) => {
if (index > 1 && index < 22) return
element.classList.add('has-title')
const title = element.getAttribute('data-tooltip')
const span = document.createElement('span')
span.innerHTML = title
span.className = 'title'
element.appendChild(span)
})
}, 50)
}
return (
<>
<div className="editor-wrapper">
<div className="editor-left">
<div className="editor-header"></div>
<div className="editor-main">
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={onCreated}
onChange={editor => setHtml(editor.getHtml())}
mode="default"
style={{ height: '500px', overflowY: 'hidden' }}
/>
</div>
</div>
<div className="editor-right">
<Spin spinning={loading}>
<Toolbar editor={editor} defaultConfig={toolbarConfig} mode="default" className="editor-toolbar" />
</div>
<Editor defaultConfig={editorConfig} value={value} onChange={onChange} onCreated={setEditor} mode="default" className="editor-main" />
</Spin>
</div>
</>
)
}
export default WangEditorCustomer
.editor-wrapper {
display: flex;
}
.editor-left {
flex: 1;
border: 1px solid #ccc;
}
.editor-right {
flex: 0 0 300px;
background: #fafafa;
border: 1px solid #e5e5e5;
min-width: 300px;
margin-left: 10px;
border: 1px solid #d9d9d9;
border-radius: 6px;
}
.editor-toolbar {
margin: 10px;
.w-e-bar {
padding: 0;
svg {
width: 18px;
height: 18px;
}
}
.w-e-bar-divider {
margin: 0;
padding-top: 10px;
width: 100%;
height: auto;
background: #fafafa;
font-size: 14px;
font-weight: 600;
line-height: 40px;
overflow: hidden;
.editor-toolbar {
border-bottom: 1px solid #d9d9d9;
}
.w-e-bar-item {
height: auto;
button {
svg:nth-child(2) {
display: none;
}
&.has-title {
width: 100%;
height: auto;
padding: 10px;
flex-direction: column;
align-items: center;
.title {
margin: 5px 0 0 0;
}
}
}
.editor-main {
height: 400px;
overflow-y: hidden;
}
}
import { useMemo, useRef, useState } from 'react'
import { Select, Spin } from 'antd'
import { debounce } from 'lodash-es'
import { getTeacherList } from '@/api/user'
function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
const [fetching, setFetching] = useState(false)
const [options, setOptions] = useState([])
const fetchRef = useRef(0)
const debounceFetcher = useMemo(() => {
const loadOptions = value => {
fetchRef.current += 1
const fetchId = fetchRef.current
setOptions([])
setFetching(true)
fetchOptions(value).then(newOptions => {
if (fetchId !== fetchRef.current) {
// for fetch callback order
return
}
setOptions(newOptions)
setFetching(false)
})
}
return debounce(loadOptions, debounceTimeout)
}, [fetchOptions, debounceTimeout])
return (
<Select
labelInValue
filterOption={false}
onSearch={debounceFetcher}
notFoundContent={fetching ? <Spin size="small" /> : null}
{...props}
options={options}
/>
)
}
// Usage of DebounceSelect
async function fetchUserList(username) {
console.log('fetching user', username)
return getTeacherList({ real_name: username, page_size: 40 }).then(res => {
return res.data.list
})
}
const SelectTeacher = props => {
const [value, setValue] = useState([])
return (
<DebounceSelect
mode="multiple"
value={value}
placeholder="Select users"
fetchOptions={fetchUserList}
fieldNames={{ label: 'real_name', value: 'id' }}
onChange={newValue => {
setValue(newValue)
}}
style={{ width: '100%' }}
{...props}
/>
)
}
export default SelectTeacher
import { Button, Upload, message } from 'antd'
import { useState } from 'react'
import { uploadFile } from '@/utils/oss'
import './index.less'
export default function UploadImage({ value, onChange }) {
const [uploading, setUploading] = useState(false)
const uploadProps = {
name: 'file',
accept: '.jpg,.png',
showUploadList: false,
beforeUpload: async file => {
const suffixArr = ['jpg', 'png']
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1)
if (!suffixArr.includes(suffix)) {
message.error(`请上传以${suffixArr.join('、')}格式的书籍`)
return false
} else if (file.size >= 1024 * 1024) {
message.error(`请上传大小在1M以内的图片`)
return false
}
},
customRequest: async ({ file }) => {
try {
setUploading(true)
const url = await uploadFile(file)
setUploading(false)
onChange(url)
return true
} catch (error) {
message.error('上传文件失败,请重试')
setUploading(false)
return false
}
}
}
return (
<div className="upload-image">
{value && <img src={value} width={88} height={88} style={{ borderRadius: 5 }} />}
<div className="upload-image-main">
<Upload {...uploadProps}>
<Button type="primary" ghost loading={uploading}>
点击上传
</Button>
</Upload>
<span className="tips">尺寸:只能上传jpg/png文件,且不超过1M</span>
</div>
</div>
)
}
.upload-image {
.upload-image-main {
display: flex;
align-items: center;
gap: 10px;
.tips {
font-size: 10px;
font-family: 'PingFangSC, PingFang SC';
font-weight: 400;
color: #999999;
line-height: 1;
font-size: 12px;
}
}
}
import { useState, useEffect } from 'react'
import { getTeacherList } from '@/api/user'
export function useTeachers() {
const [teachers, setTeachers] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
const fetchTeachers = async () => {
try {
const response = await getTeacherList({ page_size: 40 })
setTeachers(response.data.list)
} catch (err) {
setError(err)
} finally {
setLoading(false)
}
}
fetchTeachers()
}, [])
return { teachers, loading, error }
}
.ant-modal .ant-modal-close {
inset-inline-end: initial;
}
.delModal,
.footer {
.ant-btn-primary {
......
import { Button, Form, Input, Upload, Space, Spin, Image, message } from 'antd';
import { useState, useEffect, useRef } from 'react';
const { TextArea } = Input;
import './index.less';
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
import { Editor, Toolbar } from '@wangeditor/editor-for-react';
import { useLocation, useNavigate } from 'react-router-dom';
import { addUser, editUser, getInfo } from '../request';
import { uploadFiles } from '@/utils/upload';
import { fontFamilyList } from '@/common/wangeditor-customer/utils/setting';
import AliOSS from 'ali-oss';
import dayjs from 'dayjs';
import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet';
// import { LeftOutlined } from '@ant-design/icons';
import add from '@/assets/images/icon/add.png';
import { useState, useEffect } from 'react'
import { Button, Form, Input, Flex, message } from 'antd'
import WangEditor from '@/components/editor'
import UploadImage from '@/components/uploadImage'
import { useLocation, useNavigate } from 'react-router-dom'
import { addBook, updateBook, getBook } from '../api'
import SelectTeacher from '@/components/selectTeacher'
const BookAddEdit = () => {
const location = useLocation();
const [isEdit, setIsEdit] = useState(false);
const [initialValues, setinitialValues] = useState({});
const navigate = useNavigate();
const flag = useRef(true);
const [form] = Form.useForm();
const [showimg, setshowimg] = useState(false);
const [img, setImg] = useState('');
// 上传图片是否超过限制
const [bool, setBool] = useState(false);
const handleGoBack = () => {
navigate(-1);
};
const navigate = useNavigate()
const location = useLocation()
const isEdit = !!location.state?.id
// oss
const [ossClient, setOssClient] = useState(null); // oss 操作
const [STSToken, setSTSToken] = useState(null); // oss 过期设置
const [file, setFile] = useState({}); // oss 过期设置
const [uploading, setUploading] = useState(false);
let ossClientTemp;
const getStsAuthToken = async () => {
const data = await getAliOSSSTSToken();
if (data) {
window.sessionStorage.setItem('sts', JSON.stringify(data));
setSTSToken(data);
ossClientTemp = await new AliOSS({
accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret,
stsToken: data.SecurityToken,
endpoint: data.endpoint,
bucket: 'zxts-book-file',
const [form] = Form.useForm()
const [img, setImg] = useState('')
// 编辑器内容
const [html, setHtml] = useState('')
timeout: 180000,
refreshSTSToken: async () => {
const info = await getAliOSSSTSToken();
return {
AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken,
};
},
refreshSTSTokenInterval: 14 * 60 * 1000,
});
setOssClient(ossClientTemp);
}
};
// 详情信息
const getInfor = async () => {
const data = await getInfo({ id: location.state.id });
setshowimg(true);
setImg(data.img);
setHtml(data.content);
form.setFieldsValue(data);
};
// 图片上传
const uploadImg = async (file) => {
const { url } = await uploadFiles({ file, file_type: 'book' });
setImg(url);
};
const onFinish = async (obj) => {
let bool;
if (isEdit) {
bool = await editUser({ id: location.state.id, ...obj, content: html, img });
} else {
bool = await addUser({ ...obj, img });
const fetchInfo = async () => {
const { data } = await getBook({ id: location.state.id })
setImg(data.img)
setHtml(data.content)
const formFields = {
...data,
editors: data.editors_list.map(item => {
return { label: item.real_name, value: item.editor_id }
})
}
bool && navigate(-1);
};
const props = {
name: 'file',
accept: '.jpg,.png',
showUploadList: false,
beforeUpload: async (file) => {
const suffixArr = ['jpg', 'png'];
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
if (!suffixArr.includes(suffix)) {
message.error(`请上传以${suffixArr.join('、')}格式的书籍`);
return false;
} else if (file.size >= 1024 * 1024) {
message.error(`请上传大小在1M以内的图片`);
return false;
}
setFile(file);
},
customRequest: async () => {
if (!ossClient) {
message.error('ossClient还未初始化', ossClient);
return false;
}
try {
setUploading(true);
const fileExt = file.name.substring(file.name.lastIndexOf('.'));
const fileName = `banner-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`;
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`;
const result = await ossClient.put(filePath, file);
console.log('result', result);
// 假设 result 中包含了文件的 URL
const imageUrl = result.url;
// 更新图片 URL 状态
setImg(imageUrl);
setshowimg(true);
form.setFieldsValue({ img: imageUrl });
setUploading(false);
// 上传成功,返回 true 表示可以继续上传
return true;
} catch (error) {
// 上传失败,处理错误
console.error('上传文件失败:', error);
message.error('上传文件失败,请重试');
return false;
}
},
};
form.setFieldsValue(formFields)
}
useEffect(() => {
getStsAuthToken();
if (location.state && location.state.id) {
setIsEdit(true);
// if(!flag.current){
getInfor();
// }else{
// flag.current=false
// }
}
}, []);
// editor 实例
const [editor, setEditor] = useState(null);
// 编辑器内容
const [html, setHtml] = useState('');
const [loading, setLoading] = useState(false);
// 工具栏配置
const toolbarConfig = {
excludeKeys: [
'insertVideo',
'insertImage',
'emotion',
'table',
'codeBlock',
'blockquote',
'code',
'group-more-style',
'insertTable',
], //删除工具栏
}; // JS 语法
// 编辑器配置
const editorConfig = {
// JS 语法
placeholder: '请输入内容...',
MENU_CONF: {
// 配置默认字号
fontSize: {
fontSizeList: [
{ name: '初号', value: '56px' },
{ name: '小初', value: '48px' },
{ name: '一号', value: '34px' },
{ name: '小一', value: '32px' },
{ name: '二号', value: '29px' },
{ name: '小二', value: '24px' },
{ name: '三号', value: '21px' },
{ name: '小三', value: '20px' },
{ name: '四号', value: '18px' },
{ name: '小四', value: '16px' },
{ name: '五号', value: '14px' },
{ name: '小五', value: '12px' },
{ name: '六号', value: '10px' },
{ name: '小六', value: '8px' },
{ name: '七号', value: '7px' },
{ name: '八号', value: '6px' },
],
},
fontFamily: {
fontFamilyList: fontFamilyList,
},
lineHeight: {
lineHeightList: ['1', '1.25', '1.5', '2', '2.5', '3'],
},
// 配置上传图片
uploadImage: {
timeout: 5 * 1000, // 5s
if (isEdit) fetchInfo()
}, [isEdit])
fieldName: 'image',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token') || '',
},
maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 // 用户自定义上传图片
customUpload: async (file, insertFn) => {
setLoading(true);
if (!ossClient) {
console.error('ossClient还未初始化', ossClient);
return false;
}
const fileExt = file.name.substring(file.name.lastIndexOf('.'));
const fileName = `banner-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`;
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`;
const result = await ossClient.put(filePath, file);
console.log('result', result);
insertFn(result.url, '题库图片');
// const { url } = await uploadFiles({ file, file_type: 'question' });
// insertFn(url, '题库图片');
setLoading(false);
},
},
uploadVideo: {
timeout: 15 * 1000, // 5s
fieldName: 'video',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer ' + localStorage.getItem('token') || '',
},
allowedFileTypes: ['video/mp4', 'video/ogg', 'video/webm'],
maxFileSize: 10 * 1024 * 1024, // 10M
base64LimitSize: 5 * 1024, // 5kb 以下插入 base64 // 用户自定义上传图片
customUpload: async (file, insertFn) => {
setLoading(true);
if (!ossClient) {
console.error('ossClient还未初始化', ossClient);
return false;
}
const fileExt = file.name.substring(file.name.lastIndexOf('.'));
const fileName = `banner-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`;
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`;
const result = await ossClient.put(filePath, file);
console.log('result', result);
insertFn(result.url, '题库视频');
// const { url } = await uploadFiles({ file, file_type: 'question' });
// insertFn(url, '题库视频');
setLoading(false);
},
},
},
hoverbarKeys: {
image: {
menuKeys: ['imageWidth30', 'imageWidth50', 'imageWidth100', 'deleteImage'],
},
text: {
menuKeys: [
'headerSelect',
'insertLink',
// 'bulletedList',
// 'numberedList',
'|',
'bold',
'underline',
'italic',
'|',
'color',
'bgColor',
'clearStyle',
],
},
},
};
// 及时销毁 editor ,重要!
useEffect(() => {
return () => {
if (editor == null) return;
editor.destroy();
setEditor(null);
};
}, [editor]);
const onFinish = async values => {
const editors = values.editors?.map(item => item.value) || []
const res = isEdit ? await updateBook({ id: location.state.id, ...values, img, editors }) : await addBook({ ...values, img, editors })
message.success(res.message)
navigate(-1)
}
return (
<div style={{ padding: 10 }}>
<div className='back-icon' onClick={handleGoBack}>
<span
style={{
display: 'inline-block',
width: '11px',
height: '10px',
pointerEvents: 'none',
}}
>
<Image src={add} />
</span>
</div>
<Form form={form} onFinish={onFinish} labelCol={{ span: 2 }} initialValues={initialValues}>
<Form.Item
label='书籍名称'
name='name'
rules={[
{ required: true, message: '请输入书籍名称' },
{ max: 30, message: '最大30字符' },
]}
>
<Input autoComplete='off' placeholder='请输入书籍名称' style={{ width: 260 }}></Input>
</Form.Item>
<Form.Item
label='作者'
name='authors'
rules={[
{ required: true, message: '请输入作者' },
{ max: 30, message: '最大30字符' },
]}
>
<Input autoComplete='off' placeholder='请输入作者' style={{ width: 260 }}></Input>
</Form.Item>
<Form.Item
name='img'
label='缩略图'
className='uploadPar'
rules={[
{
validator: () => {
return new Promise((resolve, reject) => {
if (!img || !bool) {
resolve();
}
reject('最大150字符');
});
},
},
]}
>
<div>
{showimg && (
<img id='img' src={img} width={80} height={80} style={{ borderRadius: 5 }} />
)}
<div className='descBox'>
<Spin spinning={uploading}>
<Upload {...props}>
<Button className='upload'>点击上传</Button>
</Upload>
<span className='desc'>尺寸:只能上传jpg/png文件,且不超过1M</span>
</Spin>
</div>
</div>
</Form.Item>
<Form.Item
label='编辑推荐'
name='introduction'
rules={[{ max: 65535, message: '最多65535字符' }]}
>
<TextArea
placeholder='请输入编辑推荐'
autoSize={{
maxRows: 8,
minRows: 5,
}}
style={{ width: 910 }}
/>
</Form.Item>
<Form.Item label='简介' name='content' rules={[{ max: 65535, message: '最多65535字符' }]}>
<Spin spinning={loading}>
{ossClient && (
<div
className='editor-box'
style={{
border: '1px solid #d9d9d9',
borderRadius: '6px',
overflow: 'hidden',
zIndex: 100,
}}
>
<Toolbar
editor={editor}
defaultConfig={toolbarConfig}
mode='default'
style={{ borderBottom: '1px solid #d9d9d9' }}
/>
<Editor
defaultConfig={editorConfig}
value={html}
onCreated={setEditor}
onChange={(editor) => {
form.setFieldValue('content', editor.getHtml());
setHtml(editor.getHtml());
}}
mode='default'
className='w-e-text'
style={{ height: '400px', overflowY: 'hidden' }}
/>
</div>
)}
</Spin>
</Form.Item>
<Form.Item
wrapperCol={{
span: 24,
}}
>
<div style={{ textAlign: 'center' }}>
<Space size={20}>
<Button
className='cancel'
onClick={() => {
navigate(-1);
}}
>
取消
</Button>
<Button className='submit' htmlType='submit' style={{ borderColor: '#aa1941' }}>
确认
</Button>
</Space>
</div>
</Form.Item>
</Form>
</div>
);
};
export default BookAddEdit;
<Form form={form} onFinish={onFinish} labelCol={{ span: 2 }}>
<Form.Item
label="书籍名称"
name="name"
rules={[
{ required: true, message: '请输入书籍名称' },
{ max: 30, message: '最大30字符' }
]}>
<Input autoComplete="off" placeholder="请输入书籍名称" style={{ width: 260 }}></Input>
</Form.Item>
<Form.Item
label="作者"
name="authors"
rules={[
{ required: true, message: '请输入作者' },
{ max: 30, message: '最大30字符' }
]}>
<Input autoComplete="off" placeholder="请输入作者" style={{ width: 260 }}></Input>
</Form.Item>
<Form.Item name="img" label="缩略图" className="uploadPar">
<UploadImage value={img} onChange={url => setImg(url)}></UploadImage>
</Form.Item>
<Form.Item label="编辑推荐" name="introduction" rules={[{ max: 65535, message: '最多65535字符' }]}>
<Input.TextArea placeholder="请输入编辑推荐" autoSize={{ maxRows: 8, minRows: 5 }} style={{ width: 910 }} />
</Form.Item>
<Form.Item label="编写者" name="editors">
<SelectTeacher placeholder="请选择编写者" style={{ width: 260 }}></SelectTeacher>
</Form.Item>
<Form.Item label="简介" name="content">
<WangEditor value={html} onChange={editor => form.setFieldValue('content', editor.getHtml())}></WangEditor>
</Form.Item>
<Form.Item wrapperCol={{ span: 24 }}>
<Flex gap={20} justify="center">
<Button
onClick={() => {
navigate(-1)
}}>
取消
</Button>
<Button type="primary" htmlType="submit">
确认
</Button>
</Flex>
</Form.Item>
</Form>
)
}
export default BookAddEdit
.upload {
background: rgba(170, 25, 65, 0.03);
border-radius: 4px;
border: 1px solid #aa1941;
color: #aa1941;
font-size: 12px;
&:hover {
background: rgba(170, 25, 65, 0.03) !important;
border-radius: 4px !important;
opacity: 0.7;
border: 1px solid #aa1941 !important;
color: #aa1941 !important;
font-size: 12px !important;
}
}
.uploadPar {
.descBox {
display: flex;
align-items: flex-end; /* 让子元素底部对齐 */
.desc {
font-size: 10px;
font-family: 'PingFangSC, PingFang SC';
font-weight: 400;
color: #999999;
line-height: 14px;
font-size: 12px;
margin-left: 6px;
margin-bottom: 2px;
}
}
}
.back-icon {
position: absolute;
top: 10px;
left: 10px;
cursor: pointer;
display: none;
}
.editor-box {
.w-e-scroll {
font-family: "黑体";
font-size: 18px;
line-height: 1.5;
}
}
\ No newline at end of file
import axios from '@/utils/axios'
// 获取教师书籍列表
export function getBookList(data) {
return axios.post('/api/book/teacher/getList', data)
}
// 获取教师书籍详情
export function getBook(data) {
return axios.post('/api/book/teacher/getInfoById', data)
}
// 添加教师书籍
export function addBook(data) {
return axios.post('/api/book/teacher/add', data)
}
// 添加教师书籍
export function updateBook(data) {
return axios.post('/api/book/teacher/edit', data)
}
// 删除教师书籍
export function deleteBook(data) {
return axios.post('/api/book/teacher/del', data)
}
import axios from '@/utils/axios'
// 获取章节编辑者信息
export function getChapterEditors(data) {
return axios.post('/api/book/teacher/chapter/getEditors', data)
}
// 保存章节编辑者
export function updateChapterEditors(data) {
return axios.post('/api/book/teacher/chapter/saveEditors', data)
}
import { useState, useEffect } from 'react'
import { Modal, Form, Radio, Space, message } from 'antd'
import { getChapterEditors, updateChapterEditors } from '../api'
const EditChapterEditors = ({ chapter = {}, onChange, ...props }) => {
const [editors, setEditors] = useState([])
const [value, setValue] = useState('')
useEffect(() => {
getChapterEditors({ book_id: chapter.book_id, chapter_id: chapter.id }).then(res => {
setEditors(res.data.editors || [])
const value = res.data.selected_editor_ids[0] || ''
setValue(value)
})
}, [chapter])
const handleSubmit = async () => {
await updateChapterEditors({ book_id: chapter.book_id, chapter_id: chapter.id, editor_id: value })
message.success('设置成功')
onChange && onChange()
}
return (
<Modal title="设置章节编写者" {...props} onOk={handleSubmit}>
<Form labelCol={{ span: 8 }}>
<Form.Item label="当前章节">{chapter.title}</Form.Item>
<Form.Item label="编写者">
<Radio.Group value={value} onChange={e => setValue(e.target.value)}>
<Space direction="vertical">
{editors.map(item => {
return (
<Radio value={item.editor_id} key={item.editor_id}>
{item.real_name}
</Radio>
)
})}
</Space>
</Radio.Group>
</Form.Item>
</Form>
</Modal>
)
}
export default EditChapterEditors
import React, { useState, useEffect, useRef } from 'react';
import { Form, Button, Space, Input, message } from 'antd';
import { setTreeChapter } from '@/store/modules/user';
import { useDispatch, useSelector } from 'react-redux';
import { chapterEdit, chapterAdd, sectionAdd } from '../request';
import { useState, useEffect, useRef } from 'react'
import { Form, Button, Space, Input } from 'antd'
import { setTreeChapter } from '@/store/modules/user'
import { useDispatch } from 'react-redux'
import { chapterEdit, chapterAdd, sectionAdd } from '../request'
const EditChapterTitle = (props) => {
const {
editValue,
setEditValue,
editKey,
setEditKey,
parentId,
bookId,
getChapterTreeList,
expandedKeys,
setExpandedKeys,
editorLoading,
newChapterChange,
} = props;
const dispatch = useDispatch();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [initValues, setInitValues] = useState({ title: editValue });
const inputRef = useRef();
const EditChapterTitle = props => {
const { editValue, setEditValue, editKey, setEditKey, parentId, bookId, getChapterTreeList, expandedKeys, setExpandedKeys, editorLoading, newChapterChange } =
props
const dispatch = useDispatch()
const [form] = Form.useForm()
const [loading, setLoading] = useState(false)
const [initValues, setInitValues] = useState({ title: editValue })
const inputRef = useRef()
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.focus()
}
}, []);
}, [])
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.focus()
}
}, [editorLoading]);
}, [editorLoading])
useEffect(() => {
form.setFieldsValue({ title: editValue });
setInitValues({ title: editValue });
}, [editValue]);
form.setFieldsValue({ title: editValue })
setInitValues({ title: editValue })
}, [editValue])
const onFinish = async (values) => {
setLoading(true);
let data = null;
const onFinish = async values => {
setLoading(true)
let data = null
if (parentId) {
data = await chapterAdd({
pid: parentId === -1 ? 0 : parentId,
book_id: bookId,
name: values.title,
});
name: values.title
})
} else {
data = await chapterEdit({ id: editKey, name: values.title });
data = await chapterEdit({ id: editKey, name: values.title })
}
await dispatch(setTreeChapter({ saveBookId: bookId, saveChapterId: data.id }));
await dispatch(setTreeChapter({ saveBookId: bookId, saveChapterId: data.id }))
if (data) {
if (parentId) {
await sectionAdd({ book_id: bookId, chapter_id: data.id, content: '', word_count: 0 });
await sectionAdd({ book_id: bookId, chapter_id: data.id, content: '', word_count: 0 })
}
setEditKey(false);
setEditValue(null);
await getChapterTreeList();
setEditKey(false)
setEditValue(null)
await getChapterTreeList()
if (parentId) {
let temp = [...expandedKeys, parentId];
setExpandedKeys(temp);
let temp = [...expandedKeys, parentId]
setExpandedKeys(temp)
await newChapterChange(data.id, values.title);
await newChapterChange(data.id, values.title)
}
}
setLoading(false);
};
setLoading(false)
}
return (
<Form layout='vertical' form={form} onFinish={onFinish} initialValues={initValues}>
<Form.Item
label='章节标题'
name='title'
rules={[{ required: true, message: '请输入章节标题' }]}
extra='最多30个字符'
>
<Input ref={inputRef} autoFocus maxLength={30} placeholder='' allowClear />
<Form layout="vertical" form={form} onFinish={onFinish} initialValues={initValues}>
<Form.Item label="章节标题" name="title" rules={[{ required: true, message: '请输入章节标题' }]} extra="最多30个字符">
<Input ref={inputRef} autoFocus maxLength={30} placeholder="" allowClear />
</Form.Item>
<Form.Item className='editor-form-buttons' wrapperCol={{ offset: 9, span: 16 }}>
<Form.Item className="editor-form-buttons" wrapperCol={{ offset: 9, span: 16 }}>
<Space size={20}>
<Button type='default' disabled={loading} onClick={() => setEditKey(false)}>
<Button type="default" disabled={loading} onClick={() => setEditKey(false)}>
取消
</Button>
<Button type='primary' loading={loading} htmlType='submit'>
<Button type="primary" loading={loading} htmlType="submit">
确认
</Button>
</Space>
</Form.Item>
</Form>
);
};
)
}
export default EditChapterTitle;
export default EditChapterTitle
import React, { useState, useEffect, useRef } from 'react'
import { Divider, Button, Row, Col, Descriptions, Tree, Tooltip, Dropdown, Space, Input, Popconfirm, Modal, Spin } from 'antd'
import {
DiffOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
EyeOutlined,
DashOutlined,
CloseOutlined,
CheckOutlined,
EllipsisOutlined
} from '@ant-design/icons'
import { useState, useEffect, useRef } from 'react'
import { Divider, Button, Row, Col, Descriptions, Tree, Dropdown, Space, Modal, Spin } from 'antd'
import { EllipsisOutlined, DiffOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
import WangEditorCustomer from '@/common/wangeditor-customer'
import { useLocation, useNavigate } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { setAutosaveTime } from '@/store/modules/editor'
import { setTreeChapter } from '@/store/modules/user'
import EditChapterTitle from './components/form-chapter-title'
import EditChapterEditors from './components/EditChapterEditors'
import { get } from 'lodash-es'
import md5 from 'js-md5'
......@@ -34,7 +26,6 @@ const Examine = () => {
const [gData, setGData] = useState([])
const [chapterId, setChapterId] = useState(0)
const [bookId, setBookId] = useState(0)
const [nameList, setNameList] = useState([])
const [openDel, setOpenDel] = useState(false)
const [delNode, setDelNode] = useState({})
const [recordList, setRecordList] = useState([])
......@@ -53,6 +44,12 @@ const Examine = () => {
const [contentMd5, setContentMd5] = useState('')
const [quanXian, setQuanXian] = useState(false)
// 设置编者
const [currentChapter, setCurrentChapter] = useState(null)
const [editChapterEditorsIsOpen, setEditChapterEditorsIsOpen] = useState(false)
const onChapterEditorsChange = () => {
setEditChapterEditorsIsOpen(false)
}
// 编辑器内容
const editorRef = useRef()
const saveInterRef = useRef()
......@@ -262,36 +259,6 @@ const Examine = () => {
setEditValue('')
setParentId(-1)
}
const dropDownMenuHandler = async (e, node) => {
e.domEvent.stopPropagation()
e.domEvent.preventDefault()
if (parseInt(e.key) === 1) {
// 展开
const ids = findNodeById(gData, 'key', node.key)
const expandedKeysTemp = [...expandedKeys, node.key]
ids.forEach((item, index) => {
if (!expandedKeysTemp.includes(item)) {
expandedKeysTemp.push(item)
}
})
setExpandedKeys(expandedKeysTemp)
} else if (parseInt(e.key) === 2) {
// 插入子节
// 编辑
setEditKey(-1)
setEditValue('')
setParentId(node.key)
} else if (parseInt(e.key) === 3) {
// 编辑
setEditKey(node.key)
setEditValue(node.title)
setParentId(false)
} else if (parseInt(e.key) === 4) {
setDelNode(node)
setOpenDel(true)
}
}
const delChapter = async node => {
setDelLoading(true)
......@@ -350,90 +317,48 @@ const Examine = () => {
}
}, [gData, treeChapter])
useEffect(() => {
console.log(expandedKeys)
}, [expandedKeys])
const chapterMenuItems = [
{ key: '1', label: '展开全部' },
{ key: '2', label: '添加子节' },
{ key: '5', label: '设置编者' },
{ key: '3', label: '编辑' },
{ key: '4', label: '删除' }
]
// 编辑章节名称
const titleRenderDom = node => {
const handleMenuClick = async (e, node) => {
e.domEvent.stopPropagation()
setCurrentChapter(node)
if (parseInt(e.key) === 1) {
// 展开全部
const ids = findNodeById([node], 'key', node.key)
const expandedKeysTemp = [...expandedKeys, node.key, ...ids]
setExpandedKeys(expandedKeysTemp)
} else if (parseInt(e.key) === 2) {
// 添加子节
setEditKey(-1)
setEditValue('')
setParentId(node.key)
} else if (parseInt(e.key) === 3) {
// 编辑
setEditKey(node.key)
setEditValue(node.title)
setParentId(false)
} else if (parseInt(e.key) === 4) {
setDelNode(node)
setOpenDel(true)
} else if (e.key == 5) {
setEditChapterEditorsIsOpen(true)
}
}
// 章节名称
const chapterTitleRender = node => {
return (
<div className="tree-customer-item">
<div className="title">
<div className="title-node">{node.title}</div>
</div>
<div className="opaeration">
{quanXian ? (
<Dropdown
trigger={['click']}
overlayClassName="dropmenu_list"
destroyPopupOnHide={true}
menu={{
items: [
{
key: '1',
label: <Button type="text">展开全部</Button>
},
{
key: '2',
label: <Button type="text">添加子节</Button>
},
{
key: '5',
label: <Button type="text">设置编者</Button>
},
{
key: '3',
label: <Button type="text">重命名</Button>
},
{
key: '4',
label: <Button type="text">删除</Button>
}
],
onClick: e => dropDownMenuHandler(e, node)
}}>
<div className="dashed">
<span></span>
<span></span>
<span></span>
</div>
{/* <EllipsisOutlined /> */}
</Dropdown>
) : (
<Dropdown
trigger={['click']}
overlayClassName="dropmenu_list"
destroyPopupOnHide={true}
menu={{
items: [
{
key: '1',
label: <Button type="text">展开全部</Button>
},
{
key: '2',
label: <Button type="text">添加子节</Button>
},
{
key: '3',
label: <Button type="text">编辑</Button>
},
{
key: '4',
label: <Button type="text">删除</Button>
}
],
onClick: e => dropDownMenuHandler(e, node)
}}>
<div className="dashed">
<span></span>
<span></span>
<span></span>
</div>
{/* <EllipsisOutlined /> */}
</Dropdown>
)}
</div>
<div className="chapter-tree-item">
<p className="title">{node.title}</p>
<Dropdown trigger={['click']} menu={{ items: chapterMenuItems, onClick: e => handleMenuClick(e, node) }}>
<EllipsisOutlined onClick={e => e.stopPropagation()} />
</Dropdown>
</div>
)
}
......@@ -534,7 +459,7 @@ const Examine = () => {
disabled={loading}
treeData={gData}
onExpand={onExpand}
titleRender={nodeData => titleRenderDom(nodeData)}
titleRender={nodeData => chapterTitleRender(nodeData)}
/>
)}
</>
......@@ -623,8 +548,8 @@ const Examine = () => {
wrapper: 'chapter-title-modal'
}}>
<Divider />
<div className="">确认删除子节【{delNode.title}】?</div>
<div className="" style={{ display: 'flex', justifyContent: 'flex-end' }}>
<div>确认删除子节【{delNode.title}】?</div>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Space>
<Button type="primary" danger loading={delLoading} onClick={() => delChapter(delNode)}>
确定
......@@ -640,6 +565,15 @@ const Examine = () => {
</Space>
</div>
</Modal>
{/* 设置章节编写者 */}
{currentChapter && editChapterEditorsIsOpen && (
<EditChapterEditors
open={editChapterEditorsIsOpen}
chapter={currentChapter}
onCancel={() => setEditChapterEditorsIsOpen(false)}
onChange={onChapterEditorsChange}></EditChapterEditors>
)}
</div>
)
}
......
......@@ -30,7 +30,7 @@
.section-left-top {
height: 85px;
}
.ant-descriptions.ant-descriptions-bordered >.ant-descriptions-view .ant-descriptions-row {
.ant-descriptions.ant-descriptions-bordered > .ant-descriptions-view .ant-descriptions-row {
border-bottom: 1px solid #e5e5e5;
&:nth-of-type(2) {
display: none;
......@@ -39,13 +39,14 @@
}
.editor-right {
height: 100%;
.ant-spin-nested-loading, .ant-spin-container {
.ant-spin-nested-loading,
.ant-spin-container {
height: 100%;
}
}
}
.draggable-tree {
flex:1;
flex: 1;
height: calc(100vh - 285px);
overflow-y: auto;
overflow-x: hidden;
......@@ -61,11 +62,10 @@
overflow: hidden;
}
}
.tree-customer-item {
.chapter-tree-item {
display: flex;
justify-content: space-between;
overflow: hidden;
width: 100%;
.title {
flex: 1;
overflow: hidden;
......@@ -74,46 +74,10 @@
max-height: 24px;
line-height: 24px;
white-space: nowrap;
.title-node {
overflow: hidden;
text-overflow: ellipsis;
padding-right: 10px;
max-height: 24px;
line-height: 24px;
}
}
.opaeration {
flex: 0 0 20px;
width: 20px;
align-items: center;
.dashed {
height: 24px;
line-height: 24px;
text-align: center;
align-items: center;
display: flex;
span {
margin: 0 1px;
display: inline-block;
width: 2px;
height: 2px;
// border: 1px solid #999;
background-color: #999;
border-radius: 50%;
}
}
}
}
}
.dropmenu_list {
.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item:hover {
}
.ant-btn-text:not(:disabled):not(.ant-btn-disabled):hover {
background: transparent !important;
}
}
.chapter-title-modal {
.ant-modal {
.ant-modal-close {
......
import { useEffect, useState, useRef } from 'react';
import { Input, Button, Space, Popover, Switch, Image, App } from 'antd';
import { getCoupon, setCoupon } from './request';
import Add from '@/assets/images/icon/add.png';
import coupon from '@/assets/images/icon/coupon.png';
import coupon2 from '@/assets/images/icon/coupon2.png';
import { useSelector } from 'react-redux';
import AppList from '@/components/AppList';
import FormDrawer from './components/FormDrawer';
import SendCouponDrawer from './components/SendCouponDrawer';
import * as api from './api';
import { useEffect, useState, useRef } from 'react'
import { Input, Button, Space, Popover, Switch, Image, App } from 'antd'
import { getCoupon, setCoupon } from './request'
import Add from '@/assets/images/icon/add.png'
import coupon from '@/assets/images/icon/coupon.png'
import coupon2 from '@/assets/images/icon/coupon2.png'
import { useSelector } from 'react-redux'
import AppList from '@/components/list'
import FormDrawer from './components/FormDrawer'
import SendCouponDrawer from './components/SendCouponDrawer'
import * as api from './api'
const Coupon = () => {
const { modal } = App.useApp();
const { modal } = App.useApp()
const appListRef = useRef(null);
const appListRef = useRef(null)
const reload = async () => {
await appListRef.current.handleReload(true);
};
const [drawerOpen, setDrawerOpen] = useState(false);
await appListRef.current.handleReload(true)
}
const [drawerOpen, setDrawerOpen] = useState(false)
// 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user);
const { operationPermissionsList } = useSelector(state => state.user)
// 操作某一项的id
const [id, setId] = useState('');
const [id, setId] = useState('')
const [switchFlag, setSwitchFlag] = useState(false);
const [couponList, setCouponList] = useState([]);
const [sendCouponDrawerOpen, setSendCouponDrawerOpen] = useState(false);
const [switchFlag, setSwitchFlag] = useState(false)
const [couponList, setCouponList] = useState([])
const [sendCouponDrawerOpen, setSendCouponDrawerOpen] = useState(false)
// 添加
const handleAdd = () => {
setId('');
setDrawerOpen(true);
};
setId('')
setDrawerOpen(true)
}
// 编辑
const handleEdit = async (id) => {
setId(id);
setDrawerOpen(true);
};
const handleEdit = async id => {
setId(id)
setDrawerOpen(true)
}
const onClose = () => {
setDrawerOpen(false);
};
setDrawerOpen(false)
}
// 删除
const handleDelete = async (id) => {
const handleDelete = async id => {
modal.confirm({
title: '提示',
content: '优惠券将永久删除,是否继续?',
onOk: async () => {
await api.delCoupon({ id });
reload();
},
});
};
await api.delCoupon({ id })
reload()
}
})
}
// 获取优惠券开关状态
const handleCoupon = async () => {
const { coupon_switch } = await getCoupon();
coupon_switch == '1' ? setSwitchFlag(true) : setSwitchFlag(false);
};
const [swithcLoad, setSwitchLoad] = useState(false);
const { coupon_switch } = await getCoupon()
coupon_switch == '1' ? setSwitchFlag(true) : setSwitchFlag(false)
}
const [swithcLoad, setSwitchLoad] = useState(false)
// 改变优惠券开关
const changeCoupon = async (val) => {
setSwitchLoad(true);
let coupon_switch = val ? '1' : '0';
const bool = await setCoupon({ coupon_switch });
const changeCoupon = async val => {
setSwitchLoad(true)
let coupon_switch = val ? '1' : '0'
const bool = await setCoupon({ coupon_switch })
setTimeout(() => {
setSwitchLoad(false);
}, 500);
handleCoupon();
};
setSwitchLoad(false)
}, 500)
handleCoupon()
}
useEffect(() => {
handleCoupon();
}, []);
handleCoupon()
}, [])
const remote = {
request: api.getList,
afterRequest(data) {
setCouponList(data.list);
return data;
},
};
setCouponList(data.list)
return data
}
}
const filters = [
{
label: '优惠券名称',
name: 'name',
element: <Input placeholder='请输入优惠券名称' allowClear />,
},
];
element: <Input placeholder="请输入优惠券名称" allowClear />
}
]
const columns = [
{
title: 'ID',
key: 'id',
align: 'center',
dataIndex: 'id',
dataIndex: 'id'
},
{
title: '优惠券名称',
......@@ -100,7 +100,7 @@ const Coupon = () => {
align: 'center',
dataIndex: 'name',
width: 200,
render: (text) => (
render: text => (
<Popover content={text} overlayStyle={{ maxWidth: '400px' }}>
<div
style={{
......@@ -109,49 +109,48 @@ const Coupon = () => {
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis',
textAlign: 'center',
}}
>
textAlign: 'center'
}}>
{text}
</div>
</Popover>
),
)
},
{
title: '达标金额',
key: 'norm_price',
align: 'center',
dataIndex: 'norm_price',
dataIndex: 'norm_price'
},
{
title: '满减金额',
key: 'reduced_price',
align: 'center',
dataIndex: 'reduced_price',
dataIndex: 'reduced_price'
},
{
title: '有效期开始时间',
key: 'start_time',
align: 'center',
dataIndex: 'start_time',
dataIndex: 'start_time'
},
{
title: '有效期结束时间',
key: 'end_time',
align: 'center',
dataIndex: 'end_time',
dataIndex: 'end_time'
},
{
title: '领取人数',
key: 'receive_num',
align: 'center',
dataIndex: 'receive_num',
dataIndex: 'receive_num'
},
{
title: '使用人数',
key: 'use_num',
align: 'center',
dataIndex: 'use_num',
dataIndex: 'use_num'
},
{
title: '操作',
......@@ -161,30 +160,25 @@ const Coupon = () => {
render: (_, { id }) => {
return (
<Space>
{operationPermissionsList.includes('/setting/coupon/getInfoById') && (
<Button onClick={() => handleEdit(id)}>编辑</Button>
)}
{operationPermissionsList.includes('/setting/coupon/del') && (
<Button onClick={() => handleDelete(id)}>删除</Button>
)}
{operationPermissionsList.includes('/setting/coupon/getInfoById') && <Button onClick={() => handleEdit(id)}>编辑</Button>}
{operationPermissionsList.includes('/setting/coupon/del') && <Button onClick={() => handleDelete(id)}>删除</Button>}
</Space>
);
},
},
];
)
}
}
]
const filterAside = (
<Space>
<label htmlFor='coupon'>优惠券开关</label>
<label htmlFor="coupon">优惠券开关</label>
<Switch
checked={switchFlag}
loading={swithcLoad}
onChange={changeCoupon}
disabled={!operationPermissionsList.includes('/setting/coupon/getCoupon')}
></Switch>
disabled={!operationPermissionsList.includes('/setting/coupon/getCoupon')}></Switch>
{operationPermissionsList.includes('/setting/coupon/add') && (
<Button
type='primary'
type="primary"
disabled={!switchFlag}
ghost
icon={
......@@ -194,19 +188,18 @@ const Coupon = () => {
display: 'inline-block',
width: '13px',
height: '11px',
pointerEvents: 'none',
pointerEvents: 'none'
}}
src={!switchFlag ? coupon2 : coupon}
/>
}
onClick={() => setSendCouponDrawerOpen(true)}
>
onClick={() => setSendCouponDrawerOpen(true)}>
优惠券发放
</Button>
)}
{operationPermissionsList.includes('/setting/coupon/give') && (
<Button
type='primary'
type="primary"
ghost
icon={
<span
......@@ -214,33 +207,27 @@ const Coupon = () => {
display: 'inline-block',
width: '13px',
height: '12px',
pointerEvents: 'none',
}}
>
pointerEvents: 'none'
}}>
<Image src={Add} />
</span>
}
onClick={handleAdd}
>
onClick={handleAdd}>
添加
</Button>
)}
</Space>
);
)
return (
<div className='classify'>
<div className="classify">
<AppList {...{ remote, filters, columns, filterAside }} ref={appListRef}></AppList>
{/* 添加编辑 */}
<FormDrawer open={drawerOpen} id={id} onClose={onClose} onComplete={reload}></FormDrawer>
{/* 优惠券发送 */}
<SendCouponDrawer
open={sendCouponDrawerOpen}
couponList={couponList}
onClose={() => setSendCouponDrawerOpen(false)}
></SendCouponDrawer>
<SendCouponDrawer open={sendCouponDrawerOpen} couponList={couponList} onClose={() => setSendCouponDrawerOpen(false)}></SendCouponDrawer>
</div>
);
};
)
}
export default Coupon;
export default Coupon
import { Input, DatePicker, Popover } from 'antd';
import AppList from '@/components/AppList';
import { getList } from './api';
const { RangePicker } = DatePicker;
import { Input, DatePicker, Popover } from 'antd'
import AppList from '@/components/list'
import { getList } from './api'
const { RangePicker } = DatePicker
export default function FeedBack() {
const remote = {
request: getList,
beforeRequest(params) {
const { time, ...rest } = params;
const { time, ...rest } = params
if (time) {
rest.start_time = new Date(time[0]).getTime() / 1000;
rest.end_time = new Date(time[1]).getTime() / 1000;
rest.start_time = new Date(time[0]).getTime() / 1000
rest.end_time = new Date(time[1]).getTime() / 1000
}
return rest;
},
};
return rest
}
}
const filters = [
{
label: '用户名称',
name: 'name',
element: <Input placeholder='请输入用户名称' allowClear />,
element: <Input placeholder="请输入用户名称" allowClear />
},
{
label: '手机号',
name: 'phone',
element: <Input placeholder='请输入手机号' allowClear />,
element: <Input placeholder="请输入手机号" allowClear />
},
{
label: '反馈时间',
name: 'time',
element: <RangePicker allowClear />,
},
];
element: <RangePicker allowClear />
}
]
const columns = [
{
title: 'ID',
key: 'id',
dataIndex: 'id',
dataIndex: 'id'
},
{
title: '用户名称',
key: 'name',
dataIndex: 'name',
align: 'center',
align: 'center'
},
{
title: '手机号',
key: 'phone',
dataIndex: 'phone',
align: 'center',
align: 'center'
},
{
title: '反馈时间',
key: 'create_time',
dataIndex: 'create_time',
align: 'center',
align: 'center'
},
{
title: '反馈内容',
......@@ -62,7 +62,7 @@ export default function FeedBack() {
dataIndex: 'proposal',
align: 'center',
width: 400,
render: (text) => (
render: text => (
<Popover content={text} overlayStyle={{ maxWidth: '400px' }}>
<div
style={{
......@@ -71,15 +71,14 @@ export default function FeedBack() {
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis',
textAlign: 'center',
}}
>
textAlign: 'center'
}}>
{text}
</div>
</Popover>
),
},
];
)
}
]
return <AppList {...{ remote, filters, columns }}></AppList>;
return <AppList {...{ remote, filters, columns }}></AppList>
}
import React, { useState, useEffect } from 'react';
import { Form, Input, Button, Upload, Space, Row, Col, Drawer, message } from 'antd';
import users from '@/assets/images/icon/userinfo.png';
import { changePass, changeInfo, getUserInfo } from '@/layout/request';
import AliOSS from 'ali-oss';
import { useNavigate } from 'react-router-dom';
import dayjs from 'dayjs';
import { getAliOSSSTSToken } from '@/pages/setting/help/addedit/requet';
import { useState, useEffect } from 'react'
import { Form, Input, Button, Space, Row, Col, Drawer } from 'antd'
import users from '@/assets/images/icon/userinfo.png'
import { changePass, changeInfo, getUserInfo } from '@/layout/request'
import { useNavigate } from 'react-router-dom'
import UploadImage from '@/components/uploadImage'
const UserInfo = () => {
const navigator = useNavigate();
const [file, setFile] = useState('');
const navigator = useNavigate()
const [imageUrl, setImageUrl] = useState('');
const [form] = Form.useForm();
const [form2] = Form.useForm();
const [showModal, setShowModal] = useState(false);
const [imageUrl, setImageUrl] = useState('')
const [form] = Form.useForm()
const [form2] = Form.useForm()
const [showModal, setShowModal] = useState(false)
const [ossClient, setOssClient] = useState(null); // oss 操作
const [STSToken, setSTSToken] = useState(null); // oss 过期设置
let ossClientTemp;
const getStsAuthToken = () => {
return new Promise(async (resolve) => {
const data = await getAliOSSSTSToken();
if (data) {
window.sessionStorage.setItem('sts', JSON.stringify(data));
setSTSToken(data);
ossClientTemp = await new AliOSS({
accessKeyId: data.AccessKeyId,
accessKeySecret: data.AccessKeySecret,
stsToken: data.SecurityToken,
endpoint: data.endpoint,
bucket: 'zxts-user-file',
timeout: 180000,
refreshSTSToken: async () => {
const info = await getAliOSSSTSToken();
return {
AccessKeyId: info.AccessKeyId,
AccessKeySecret: info.AccessKeySecret,
SecurityToken: info.SecurityToken,
};
},
refreshSTSTokenInterval: 14 * 60 * 1000,
});
setOssClient(ossClientTemp);
}
resolve();
});
};
// const props = {
// name: 'file',
// accept: '.jpg,.png',
// showUploadList: false,
// beforeUpload: async (file) => {
// const suffixArr = ['png', 'jpg'];
// const suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
// if (!suffixArr.includes(suffix)) {
// message.error(`请上传以${suffixArr.join('、')}的图片`);
// return false;
// }
// setFile(file);
// },
// customRequest: async () => {
// if (!ossClient) {
// message.error('ossClient还未初始化', ossClient);
// return false;
// }
// try {
// const result = await ossClient.put(file.name, file);
// console.log('result', result);
// // 假设 result 中包含了文件的 URL
// const imageUrl = result.url;
// // 更新图片 URL 状态
// setImageUrl(imageUrl);
// form.setFieldsValue({ pic: imageUrl });
// // 上传成功,返回 true 表示可以继续上传
// return true;
// } catch (error) {
// // 上传失败,处理错误
// console.error('上传文件失败:', error);
// message.error('上传文件失败,请重试');
// return false;
// }
// },
// // ... 其他属性
// };
const props = {
name: 'file',
accept: '.jpg,.png',
showUploadList: false,
beforeUpload: async (file) => {
const suffixArr = ['png', 'jpg'];
const suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
if (!suffixArr.includes(suffix)) {
message.error(`请上传以${suffixArr.join('、')}的图片`);
return false;
}
// 检查文件大小是否超过1MB
if (file.size > 1024 * 1024) {
message.error('图片大小不能超过1MB');
return false;
}
setFile(file);
},
customRequest: async () => {
if (!ossClient) {
message.error('ossClient还未初始化', ossClient);
return false;
}
try {
const fileExt = file.name.substring(file.name.lastIndexOf('.'));
const fileName = `user-${dayjs().valueOf()}-${Math.random().toString(36).substring(2)}${fileExt}`;
const filePath = `${dayjs().format('YYYY/MM/DD')}/${fileName}`;
const result = await ossClient.put(filePath, file);
console.log('result', result);
// 假设 result 中包含了文件的 URL
const imageUrl = result.url;
// 更新图片 URL 状态
setImageUrl(imageUrl);
form.setFieldsValue({ pic: imageUrl });
// 上传成功,返回 true 表示可以继续上传
return true;
} catch (error) {
// 上传失败,处理错误
console.error('上传文件失败:', error);
message.error('上传文件失败,请重试');
return false;
}
},
// ... 其他属性
};
const fetchData = async (obj) => {
const fetchData = async obj => {
try {
const userData = await getUserInfo(obj);
const userData = await getUserInfo(obj)
form.setFieldsValue({
real_name: userData.real_name,
tel: userData.tel,
pic: userData.pic,
});
const imageUrl = userData.pic;
setImageUrl(imageUrl);
pic: userData.pic
})
const imageUrl = userData.pic
setImageUrl(imageUrl)
} catch (error) {
console.error('Error fetching user data:', error);
console.error('Error fetching user data:', error)
}
};
}
useEffect(() => {
getStsAuthToken();
fetchData();
}, []);
fetchData()
}, [])
const changePasswrd = async (obj) => {
const bool = await changePass(obj);
setShowModal(false);
};
const changePasswrd = async obj => {
await changePass(obj)
setShowModal(false)
}
const submitForm = async (obj) => {
const updatedData = await changeInfo({ ...obj });
const submitForm = async obj => {
const updatedData = await changeInfo({ ...obj })
if (updatedData) {
await fetchData();
await fetchData()
}
};
}
return (
<div style={{ padding: '20px 0' }}>
<Form form={form} labelCol={{ span: 2 }} onFinish={submitForm}>
<Form.Item label='头像' className='uploadPar' name='pic'>
<div>
<img
src={imageUrl ? imageUrl : users}
style={{ borderRadius: '50%' }}
width={80}
height={80}
/>
<div>
<Upload {...props} valuePropName='file'>
<Button className='upload'>点击上传</Button>
</Upload>
<span className='desc' style={{ marginLeft: 19, color: '#999', fontSize: '14px' }}>
尺寸:只能上传jpg/png文件,且不超过1M
</span>
</div>
</div>
<Form.Item label="头像" className="uploadPar" name="pic">
<UploadImage value={imageUrl ? imageUrl : users} onChange={url => setImageUrl(url)}></UploadImage>
</Form.Item>
<Form.Item
label='管理员名称'
name='real_name'
rules={[{ required: true, message: '请输入管理员名称' }]}
>
<Input autoComplete='off' placeholder='请输入管理员名称' style={{ width: 200 }}></Input>
<Form.Item label="管理员名称" name="real_name" rules={[{ required: true, message: '请输入管理员名称' }]}>
<Input autoComplete="off" placeholder="请输入管理员名称" style={{ width: 200 }}></Input>
</Form.Item>
<Form.Item label='手机号' name='tel' rules={[{ required: true, message: '请输入手机号' }]}>
<Input autoComplete='off' placeholder='请输入手机号' style={{ width: 200 }}></Input>
<Form.Item label="手机号" name="tel" rules={[{ required: true, message: '请输入手机号' }]}>
<Input autoComplete="off" placeholder="请输入手机号" style={{ width: 200 }}></Input>
</Form.Item>
<Form.Item label='密码'>
<Button type='primary' ghost onClick={() => setShowModal(true)}>
<Form.Item label="密码">
<Button type="primary" ghost onClick={() => setShowModal(true)}>
修改密码
</Button>
</Form.Item>
<Form.Item wrapperCol={{ offset: 2 }}>
<Space size={20}>
<Button className='cancel' onClick={() => navigator(-1)}>
<Button className="cancel" onClick={() => navigator(-1)}>
取消
</Button>
<Button className='submit' htmlType='submit'>
<Button className="submit" htmlType="submit">
保存
</Button>
</Space>
......@@ -225,83 +76,74 @@ const UserInfo = () => {
<Drawer
open={showModal}
onClose={() => {
setShowModal(false);
setShowModal(false)
}}
mask={false}
maskClosable={false}
footer={null}
centered
destroyOnClose
keyboard={false}
>
keyboard={false}>
<Form labelCol={{ span: 5 }} form={form2} onFinish={changePasswrd}>
<Form.Item
label='旧密码'
name='old_password'
rules={[{ required: true, message: '请输入旧密码' }]}
>
<Input.Password autoComplete='off' placeholder='请输入旧密码'></Input.Password>
<Form.Item label="旧密码" name="old_password" rules={[{ required: true, message: '请输入旧密码' }]}>
<Input.Password autoComplete="off" placeholder="请输入旧密码"></Input.Password>
</Form.Item>
<Form.Item
label='新密码'
name='password'
label="新密码"
name="password"
rules={[
{ required: true, message: '请输入新密码' },
{
pattern:
/^((?=.*\d)(?=.*[A-Z])(?=.*[a-z]))|((?=.*\d)(?=.*[A-Z])(?=.*[\W_]))|((?=.*\d)(?=.*[a-z])(?=.*[\W_]))|((?=.*[A-Z])(?=.*[a-z])(?=.*[\W_]))[a-zA-Z\d\W_]{8,12}$/,
message:
'密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!',
trigger: ['change', 'blur'],
message: '密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!',
trigger: ['change', 'blur']
},
{
validator(_, value) {
if (!value || form2.getFieldValue('re_password') === value) {
form2.setFields([{ name: 're_password', errors: [''] }]);
return Promise.resolve();
form2.setFields([{ name: 're_password', errors: [''] }])
return Promise.resolve()
}
form2.setFields([{ name: 're_password', errors: ['两次输入的密码不一致'] }]);
return Promise.reject();
},
},
]}
>
<Input.Password autoComplete='off' placeholder='请输入新密码'></Input.Password>
form2.setFields([{ name: 're_password', errors: ['两次输入的密码不一致'] }])
return Promise.reject()
}
}
]}>
<Input.Password autoComplete="off" placeholder="请输入新密码"></Input.Password>
</Form.Item>
<Form.Item
label='确认新密码'
name='re_password'
label="确认新密码"
name="re_password"
rules={[
{ required: true, message: '请确认新密码' },
{
pattern:
/^((?=.*\d)(?=.*[A-Z])(?=.*[a-z]))|((?=.*\d)(?=.*[A-Z])(?=.*[\W_]))|((?=.*\d)(?=.*[a-z])(?=.*[\W_]))|((?=.*[A-Z])(?=.*[a-z])(?=.*[\W_]))[a-zA-Z\d\W_]{8,12}$/,
message:
'密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!',
trigger: ['change', 'blur'],
message: '密码至少满足三种格式(大写字母、小写字母、数字、特殊符号), 长度为8~12位字符!',
trigger: ['change', 'blur']
},
{
validator(_, value) {
if (!value || form2.getFieldValue('password') === value) {
return Promise.resolve();
return Promise.resolve()
}
return Promise.reject(new Error('两次输入的密码不一致'));
},
},
]}
>
<Input.Password autoComplete='off' placeholder='请确认新密码'></Input.Password>
return Promise.reject(new Error('两次输入的密码不一致'))
}
}
]}>
<Input.Password autoComplete="off" placeholder="请确认新密码"></Input.Password>
</Form.Item>
<Form.Item wrapperCol={{ offset: 5 }}>
<Row justify={'center'}>
<Space size={20}>
<Col>
<Button className='cancel' onClick={() => setShowModal(false)}>
<Button className="cancel" onClick={() => setShowModal(false)}>
取消
</Button>
</Col>
<Col>
<Button className='submit' htmlType='submit'>
<Button className="submit" htmlType="submit">
确认
</Button>
</Col>
......@@ -311,7 +153,7 @@ const UserInfo = () => {
</Form>
</Drawer>
</div>
);
};
)
}
export default UserInfo;
export default UserInfo
import axios from 'axios';
import md5 from 'js-md5';
import qs from 'qs';
import { Modal, notification } from 'antd';
import axios from 'axios'
import md5 from 'js-md5'
import qs from 'qs'
import { Modal, notification } from 'antd'
function getToken() {
return window.localStorage.getItem('kiwi.token') ? window.localStorage.getItem('kiwi.token') : '';
return window.localStorage.getItem('kiwi.token') ? window.localStorage.getItem('kiwi.token') : ''
}
function showLoginModal() {
Modal.warning({
title: '登录状态已过期,请重新登录',
onOk() {
localStorage.removeItem('kiwi.gpt.token');
location.href = '/login';
},
});
localStorage.removeItem('kiwi.gpt.token')
location.href = '/login'
}
})
}
// 排序
function alphabeticalSort(a, b) {
return a.localeCompare(b);
return a.localeCompare(b)
}
const httpRequest = axios.create({
// timeout: 60000,
withCredentials: true,
});
withCredentials: true
})
// 请求拦截器
httpRequest.interceptors.request.use(
(config) => {
const token = getToken();
config => {
const token = getToken()
// 应用设置
const appId = 'TzEU5jPk2tu80266';
const appSecret = '0a006048a4480481b18fef1405120b83';
const timestamp = Math.floor(Date.now() / 1000);
const appId = 'TzEU5jPk2tu80266'
const appSecret = '0a006048a4480481b18fef1405120b83'
const timestamp = Math.floor(Date.now() / 1000)
const signData = {
...config.data,
......@@ -42,60 +42,60 @@ httpRequest.interceptors.request.use(
appSecret,
timestamp,
token,
url: config.url,
};
url: config.url
}
const signStr = qs.stringify(signData, { sort: alphabeticalSort });
const signStr = qs.stringify(signData, { sort: alphabeticalSort })
const salt = '&4F6g4Y6b5L4R9';
const sign = md5(md5(signStr + salt));
const salt = '&4F6g4Y6b5L4R9'
const sign = md5(md5(signStr + salt))
const defaultHeaders = {
Authorization: token,
AppId: appId,
AppSecret: appSecret,
Timestamp: timestamp,
Sign: sign,
};
config.headers = { ...config.headers, ...defaultHeaders };
Sign: sign
}
config.headers = { ...config.headers, ...defaultHeaders }
return config;
return config
},
(error) => {
return Promise.reject(error);
},
);
error => {
return Promise.reject(error)
}
)
// 响应拦截器
httpRequest.interceptors.response.use(
(response) => {
const { data } = response;
response => {
const { data } = response
if (data.code === 401 || data.code === 403) {
if (location.pathname !== '/login') {
showLoginModal();
showLoginModal()
}
return Promise.reject(data);
return Promise.reject(data)
}
if (data.code !== 200) {
notification.error({ message: data.message || '请求错误' });
return Promise.reject(data);
notification.error({ message: data.message || '请求错误' })
return Promise.reject(data)
}
return data;
return data
},
(error) => {
error => {
if (error.response) {
const { status, data = {} } = error.response;
const { status, data = {} } = error.response
if (status === 401 || status === 403) {
showLoginModal();
showLoginModal()
} else {
notification.error({ message: data.message || '请求错误' });
console.error(`${status}: ${data.message}`);
notification.error({ message: data.message || '请求错误' })
console.error(`${status}: ${data.message}`)
}
} else {
console.log(error);
console.log(error)
}
return Promise.reject(error.response || error);
},
);
return Promise.reject(error.response || error)
}
)
export default httpRequest;
export default httpRequest
/**
* 项目的公共方法
*/
import $ from 'jquery';
import $ from 'jquery'
/**
* 对象重新排序
......@@ -9,15 +9,15 @@ import $ from 'jquery';
* @returns
*/
export function sortObjASCII(obj) {
let arr = Object.keys(obj).sort();
let arr = Object.keys(obj).sort()
if (arr.length === 0) {
return {};
return {}
}
let sortObj = {};
let sortObj = {}
for (let ii in arr) {
sortObj[arr[ii]] = obj[arr[ii]];
sortObj[arr[ii]] = obj[arr[ii]]
}
return sortObj;
return sortObj
}
/**
......@@ -27,62 +27,55 @@ export function sortObjASCII(obj) {
*/
export function formatDate(timestamp) {
// 补全为13位
let arrTimestamp = (timestamp + '').split('');
let arrTimestamp = (timestamp + '').split('')
for (let start = 0; start < 13; start++) {
if (!arrTimestamp[start]) {
arrTimestamp[start] = '0';
arrTimestamp[start] = '0'
}
}
timestamp = arrTimestamp.join('') * 1;
let minute = 1000 * 60;
let hour = minute * 60;
let day = hour * 24;
let month = day * 30;
let now = new Date().getTime();
let diffValue = now - timestamp;
timestamp = arrTimestamp.join('') * 1
let minute = 1000 * 60
let hour = minute * 60
let day = hour * 24
let month = day * 30
let now = new Date().getTime()
let diffValue = now - timestamp
// 如果本地时间反而小于变量时间
if (diffValue < 0) {
return '不久前';
return '不久前'
}
// 计算差异时间的量级
let monthC = diffValue / month;
let weekC = diffValue / (7 * day);
let dayC = diffValue / day;
let hourC = diffValue / hour;
let minC = diffValue / minute;
let monthC = diffValue / month
let weekC = diffValue / (7 * day)
let dayC = diffValue / day
let hourC = diffValue / hour
let minC = diffValue / minute
// 数值补0方法
let zero = function (value) {
if (value < 10) {
return '0' + value;
return '0' + value
}
return value;
};
return value
}
// 使用
if (monthC > 4) {
// 超过1年,直接显示年月日
return (function () {
let date = new Date(timestamp);
return (
date.getFullYear() +
'年' +
zero(date.getMonth() + 1) +
'月' +
zero(date.getDate() + 1) +
'日'
);
})();
let date = new Date(timestamp)
return date.getFullYear() + '年' + zero(date.getMonth() + 1) + '月' + zero(date.getDate() + 1) + '日'
})()
} else if (monthC >= 1) {
return parseInt(monthC) + '月前';
return parseInt(monthC) + '月前'
} else if (weekC >= 1) {
return parseInt(weekC) + '周前';
return parseInt(weekC) + '周前'
} else if (dayC >= 1) {
return parseInt(dayC) + '天前';
return parseInt(dayC) + '天前'
} else if (hourC >= 1) {
return parseInt(hourC) + '小时前';
return parseInt(hourC) + '小时前'
} else if (minC >= 1) {
return parseInt(minC) + '分钟前';
return parseInt(minC) + '分钟前'
}
return '刚刚';
return '刚刚'
}
/**
......@@ -95,8 +88,8 @@ export function getDateStr() {
month = date.getMonth() > 9 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`,
day = date.getDate() + 1 > 9 ? date.getDate() + 1 : `0${date.getDate() + 1}`,
hh = date.getHours() > 9 ? date.getHours() : `0${date.getHours()}`,
mm = date.getMinutes() > 9 ? date.getMinutes() : `0${date.getMinutes()}`;
return `${year}${month}${day}${hh}${mm}`;
mm = date.getMinutes() > 9 ? date.getMinutes() : `0${date.getMinutes()}`
return `${year}${month}${day}${hh}${mm}`
}
/**
......@@ -105,283 +98,279 @@ export function getDateStr() {
* @returns
*/
export function randomString(len) {
const length = len || 32;
const length = len || 32
let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz12345678',
maxPos = chars.length,
pwd = '';
pwd = ''
for (let i = 0; i < length; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd;
return pwd
}
// 根据id 查找树中的节点内容
export const findTreeElementByKey = (tree, key, value) => {
for (let i = 0; i < tree.length; i++) {
const bool = !isNaN(value)
? parseFloat(tree[i][key]) === parseFloat(value)
: tree[i][key] === value;
const bool = !isNaN(value) ? parseFloat(tree[i][key]) === parseFloat(value) : tree[i][key] === value
if (bool) {
// 找到元素
return tree[i];
return tree[i]
} else if (Array.isArray(tree[i].children)) {
// 递归遍历子节点
const found = findTreeElementByKey(tree[i].children, key, value);
const found = findTreeElementByKey(tree[i].children, key, value)
if (found) {
return found;
return found
}
}
}
return null; // 没有找到元素
};
return null // 没有找到元素
}
// 设置所有有children 的展开项
export const findParentsExpanded = (treeData, targetKey = 'id') => {
const keys = [];
const keys = []
function traverse(nodes) {
if (!nodes) return;
if (!nodes) return
for (const node of nodes) {
if (node.children) {
keys.push(node[targetKey]);
traverse(node.children);
keys.push(node[targetKey])
traverse(node.children)
}
}
}
traverse(treeData);
traverse(treeData)
return keys;
};
return keys
}
// 将路由菜单转为树形菜单
export const treeRouterData = (source, id = 'menuId', parentId = 'pid', children = 'children') => {
const cloneData = JSON.parse(JSON.stringify(source));
if (source.length === 0) return source;
return cloneData.filter((father) => {
const branchArr = cloneData.filter(
(child) => parseFloat(father[id]) === parseFloat(child[parentId]),
);
father[children] = branchArr.length > 0 ? branchArr : null;
return father[parentId] === 0;
});
};
const cloneData = JSON.parse(JSON.stringify(source))
if (source.length === 0) return source
return cloneData.filter(father => {
const branchArr = cloneData.filter(child => parseFloat(father[id]) === parseFloat(child[parentId]))
father[children] = branchArr.length > 0 ? branchArr : null
return father[parentId] === 0
})
}
// 将数组转换成Tree所需要的数组
export function convertToAntdTreeData(data, target = 'label') {
const antdTreeData = [];
const antdTreeData = []
const convertNode = (node) => {
const convertNode = node => {
const antdTreeNode = {
...node,
title: node[target],
key: node.id,
select: false,
edit: false,
};
edit: false
}
if (node.children && node.children.length > 0) {
antdTreeNode.children = node.children.map(convertNode);
antdTreeNode.children = node.children.map(convertNode)
}
return antdTreeNode;
};
return antdTreeNode
}
antdTreeData.push(...data.map(convertNode));
antdTreeData.push(...data.map(convertNode))
return antdTreeData;
return antdTreeData
}
// 查找树里面的所有父级节点
export const findParents = (treeData, targetKey = 'id', value) => {
for (const node of treeData) {
if (parseFloat(node[targetKey]) === parseFloat(value)) {
return [];
return []
}
if (node.children) {
const parents = findParents(node.children, targetKey, value);
const parents = findParents(node.children, targetKey, value)
if (parents) {
return [node[targetKey], ...parents];
return [node[targetKey], ...parents]
}
}
}
return null;
};
return null
}
export const findNodeById = (tree, targetKey = 'id', targetId) => {
// 递归处理树节点
for (const node of tree) {
// 如果当前节点的 id 等于目标 id,返回当前节点的所有子节点的 id
if (node[targetKey] === targetId) {
console.log(targetKey, targetId);
if (node.children && node.children.length) {
return collectChildrenIds(node.children, targetKey);
return collectChildrenIds(node.children, targetKey)
}
}
// 递归处理子节点
if (node.children && node.children.length > 0) {
const result = findNodeById(node.children, targetKey, targetId);
const result = findNodeById(node.children, targetKey, targetId)
if (result) {
return result;
return result
}
}
}
// 如果未找到目标节点,返回空数组
return [];
};
return []
}
function collectChildrenIds(children, targetKey) {
// 收集子节点的 id
const ids = [];
const ids = []
for (const child of children) {
ids.push(child[targetKey]);
ids.push(child[targetKey])
// 递归处理孙子节点
if (child.children && child.children.length > 0) {
ids.push(...collectChildrenIds(child.children, targetKey));
ids.push(...collectChildrenIds(child.children, targetKey))
}
}
return ids;
return ids
}
// 查找树里面的所有父级节点
export const findAllParents = (tree, key, value, parents = []) => {
for (const node of tree) {
const currentKey = node[key];
const children = node.children || [];
const currentKey = node[key]
const children = node.children || []
if (currentKey === value) {
return parents.concat(currentKey);
return parents.concat(currentKey)
}
if (children.length > 0) {
const result = findAllParents(children, key, value, parents.concat(currentKey));
const result = findAllParents(children, key, value, parents.concat(currentKey))
if (result.length > 0) {
return result;
return result
}
}
}
return [];
};
return []
}
// 查找树里面的所有子级节点
export const findAllChildren = (tree, key, value) => {
for (const node of tree) {
const currentKey = node[key];
const currentChildren = (node.children || []).map((child) => child[key]);
const currentKey = node[key]
const currentChildren = (node.children || []).map(child => child[key])
if (currentKey === value) {
return currentChildren;
return currentChildren
}
if (currentChildren.length > 0) {
const result = findAllChildren(node.children, key, value, currentChildren);
return result;
const result = findAllChildren(node.children, key, value, currentChildren)
return result
}
}
};
}
// 将树形结构转为一维数组
export const treeDataToArray = (source) => {
const res = [];
export const treeDataToArray = source => {
const res = []
// 第二种方式
source.length &&
source.forEach((item) => {
res.push(item);
item.children && res.push(...treeDataToArray(item.children));
});
return res;
};
source.forEach(item => {
res.push(item)
item.children && res.push(...treeDataToArray(item.children))
})
return res
}
export const getStyleValue = (elem, styleKey) => {
let res = '';
let res = ''
const styleStr = $(elem).attr('style') || ''; // 如 'line-height: 2.5; color: red;'
const styleArr = styleStr.split(';'); // 如 ['line-height: 2.5', ' color: red', '']
const length = styleArr.length;
const styleStr = $(elem).attr('style') || '' // 如 'line-height: 2.5; color: red;'
const styleArr = styleStr.split(';') // 如 ['line-height: 2.5', ' color: red', '']
const length = styleArr.length
for (let i = 0; i < length; i++) {
const styleItemStr = styleArr[i]; // 如 'line-height: 2.5'
const styleItemStr = styleArr[i] // 如 'line-height: 2.5'
if (styleItemStr) {
const arr = styleItemStr.split(':'); // ['line-height', ' 2.5']
const arr = styleItemStr.split(':') // ['line-height', ' 2.5']
if (arr[0].trim() === styleKey) {
res = arr[1].trim();
res = arr[1].trim()
}
}
}
return res;
};
return res
}
// 根据id 查找树中的节点内容
export const findFirstNotHasChildren = (tree) => {
export const findFirstNotHasChildren = tree => {
if (tree.length > 0) {
if (tree[0].children && tree[0].children.length > 0) {
return findFirstNotHasChildren(tree[0].children);
return findFirstNotHasChildren(tree[0].children)
}
return tree[0];
return tree[0]
}
return null; // 没有找到元素
};
return null // 没有找到元素
}
// 只返回父级, 只找上面第一层的父级
export const findParentLevelOne = (data, key = 'id', value) => {
for (let i = 0; i < data.length; i++) {
const item = data[i];
const item = data[i]
if (item.children) {
const child = item.children.find((c) => c[key] === value);
const child = item.children.find(c => c[key] === value)
if (child) {
// 找到目标子元素,返回其父元素
return item;
return item
} else {
// 递归查找子元素的子元素
const result = findParentLevelOne(item.children, key, value);
const result = findParentLevelOne(item.children, key, value)
if (result) {
return result;
return result
}
}
}
}
// 没有找到目标子元素,返回null
return null;
};
return null
}
// 找所在位置
export const findTreeToIndex = (data, key, value) => {
let index = data.findIndex((item) => item[key] === value);
return index > -1 ? index : -1;
};
let index = data.findIndex(item => item[key] === value)
return index > -1 ? index : -1
}
export const hexToRgb = (hex) => {
export const hexToRgb = hex => {
// 移除前缀#符号
let hexTemp = hex.replace(/^\s*#|\s*$/g, '');
let hexTemp = hex.replace(/^\s*#|\s*$/g, '')
// 将三位十六进制转为六位
if (hexTemp.length === 3) {
hexTemp = hexTemp.replace(/(.)/g, '$1$1');
hexTemp = hexTemp.replace(/(.)/g, '$1$1')
}
// 提取R、G、B各自的十六进制表示方式
const rgb = /^(\w{2})(\w{2})(\w{2})$/.exec(hexTemp);
const rgb = /^(\w{2})(\w{2})(\w{2})$/.exec(hexTemp)
// 转为10进制并返回
return rgb ? {
r: parseInt(rgb[1], 16),
g: parseInt(rgb[2], 16),
b: parseInt(rgb[3], 16)
} : null;
return rgb
? {
r: parseInt(rgb[1], 16),
g: parseInt(rgb[2], 16),
b: parseInt(rgb[3], 16)
}
: null
}
export const clacTopicText = (type, radio, checkbox, judge, fill, textarea) => {
let i = 0;
let arr = ['一', '二' , '三', '四', '五'];
let i = 0
let arr = ['一', '二', '三', '四', '五']
if (type === 'radio') {
return '一';
return '一'
}
if (type === 'checkbox') {
if (radio.length > 0) {
......@@ -403,36 +392,36 @@ export const clacTopicText = (type, radio, checkbox, judge, fill, textarea) => {
}
if (type === 'fill') {
if (radio.length > 0) {
i ++;
}
i++
}
if (checkbox.length > 0) {
i ++;
i++
}
if (judge.length > 0) {
i ++;
i++
}
return arr[i];
return arr[i]
}
if (type === 'textarea') {
if (radio.length > 0) {
i ++;
}
i++
}
if (checkbox.length > 0) {
i ++;
i++
}
if (judge.length > 0) {
i ++;
i++
}
if (fill.length > 0) {
i ++;
i++
}
return arr[i];
return arr[i]
}
}
export const downloadFile = (res = '') => {
window.open(import.meta.env.VITE_API_URL_WORD + '/' + res);
};
window.open(import.meta.env.VITE_API_URL_WORD + '/' + res)
}
// 延时函数
export const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
export const sleep = time => new Promise(resolve => setTimeout(resolve, time))
......@@ -44,7 +44,8 @@ async function createOSSInstance() {
export async function uploadFile(file) {
try {
const oss = await createOSSInstance()
const fileName = `${new Date().getTime()}-${Math.random() * 1000}.jpg`
const fileExt = file.name.substring(file.name.lastIndexOf('.'))
const fileName = `${new Date().getTime()}-${Math.random() * 1000}${fileExt}`
const result = await oss.put(fileName, file)
return result.url
} catch (error) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论