shaogen1995 %!s(int64=2) %!d(string=hai) anos
pai
achega
7b898265d9

+ 384 - 6
后台/package-lock.json

@@ -19,6 +19,8 @@
         "antd": "^5.0.4",
         "antd-mobile": "^5.30.0",
         "axios": "^1.1.3",
+        "braft-editor": "^2.3.9",
+        "braft-utils": "^3.0.12",
         "dayjs": "^1.11.7",
         "js-base64": "^3.7.3",
         "react": "^18.2.0",
@@ -5433,6 +5435,88 @@
         "node": ">=8"
       }
     },
+    "node_modules/braft-convert": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/braft-convert/-/braft-convert-2.3.0.tgz",
+      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
+      "dependencies": {
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3"
+      },
+      "peerDependencies": {
+        "react": "^16.0.0"
+      }
+    },
+    "node_modules/braft-convert/node_modules/draft-convert": {
+      "version": "2.1.13",
+      "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+      "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "immutable": "~3.7.4",
+        "invariant": "^2.2.1"
+      },
+      "peerDependencies": {
+        "draft-js": ">=0.7.0",
+        "react": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/braft-editor": {
+      "version": "2.3.9",
+      "resolved": "https://registry.npmmirror.com/braft-editor/-/braft-editor-2.3.9.tgz",
+      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
+      "dependencies": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.3.0",
+        "braft-finder": "^0.0.19",
+        "braft-utils": "^3.0.8",
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3",
+        "draft-js-multidecorators": "^1.0.0",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      },
+      "peerDependencies": {
+        "react": "^15.0.2|| ^16.0.0-rc || ^16.0.0",
+        "react-dom": "^15.0.2|| ^16.0.0-rc || ^16.0.0"
+      }
+    },
+    "node_modules/braft-editor/node_modules/braft-finder": {
+      "version": "0.0.19",
+      "resolved": "https://registry.npmmirror.com/braft-finder/-/braft-finder-0.0.19.tgz",
+      "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw==",
+      "peerDependencies": {
+        "react": "^16.4.1",
+        "react-dom": "^16.4.1"
+      }
+    },
+    "node_modules/braft-editor/node_modules/draft-convert": {
+      "version": "2.1.13",
+      "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+      "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "immutable": "~3.7.4",
+        "invariant": "^2.2.1"
+      },
+      "peerDependencies": {
+        "draft-js": ">=0.7.0",
+        "react": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^15.0.2 || ^16.0.0-rc || ^16.0.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/braft-utils": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmmirror.com/braft-utils/-/braft-utils-3.0.12.tgz",
+      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg==",
+      "peerDependencies": {
+        "braft-convert": "^2.1.4",
+        "draft-js": "^0.10.5",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      }
+    },
     "node_modules/browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -6658,6 +6742,37 @@
       "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
     },
+    "node_modules/draft-js": {
+      "version": "0.10.5",
+      "resolved": "https://registry.npmmirror.com/draft-js/-/draft-js-0.10.5.tgz",
+      "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
+      "dependencies": {
+        "fbjs": "^0.8.15",
+        "immutable": "~3.7.4",
+        "object-assign": "^4.1.0"
+      },
+      "peerDependencies": {
+        "react": "^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0",
+        "react-dom": "^0.14.0 || ^15.0.0-rc || ^16.0.0-rc || ^16.0.0"
+      }
+    },
+    "node_modules/draft-js-multidecorators": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
+      "integrity": "sha512-7qdy+YQol5iq38AoEerhgSJWhCzxvZLn1x5ODfUlGfWlg0SrZ9AXJbaxHVIjdSIZNrbVIm+WANujNxMqCmDSZQ==",
+      "dependencies": {
+        "immutable": "*"
+      }
+    },
+    "node_modules/draftjs-utils": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmmirror.com/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
+      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg==",
+      "peerDependencies": {
+        "draft-js": "^0.10.x",
+        "immutable": "3.x.x || 4.x.x"
+      }
+    },
     "node_modules/duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
@@ -6716,6 +6831,14 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/encoding": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
+      "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+      "dependencies": {
+        "iconv-lite": "^0.6.2"
+      }
+    },
     "node_modules/enhanced-resolve": {
       "version": "5.10.0",
       "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
@@ -7753,6 +7876,34 @@
         "bser": "2.1.1"
       }
     },
+    "node_modules/fbjs": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmmirror.com/fbjs/-/fbjs-0.8.18.tgz",
+      "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
+      "dependencies": {
+        "core-js": "^1.0.0",
+        "isomorphic-fetch": "^2.1.1",
+        "loose-envify": "^1.0.0",
+        "object-assign": "^4.1.0",
+        "promise": "^7.1.1",
+        "setimmediate": "^1.0.5",
+        "ua-parser-js": "^0.7.30"
+      }
+    },
+    "node_modules/fbjs/node_modules/core-js": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-1.2.7.tgz",
+      "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js."
+    },
+    "node_modules/fbjs/node_modules/promise": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
+      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+      "dependencies": {
+        "asap": "~2.0.3"
+      }
+    },
     "node_modules/file-entry-cache": {
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -8689,9 +8840,12 @@
       "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
     },
     "node_modules/immutable": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz",
-      "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
+      "version": "3.7.6",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-3.7.6.tgz",
+      "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==",
+      "engines": {
+        "node": ">=0.8.0"
+      }
     },
     "node_modules/import-fresh": {
       "version": "3.3.0",
@@ -8781,6 +8935,14 @@
       "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
       "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="
     },
+    "node_modules/invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "node_modules/ipaddr.js": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -9110,6 +9272,15 @@
       "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
     },
+    "node_modules/isomorphic-fetch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+      "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+      "dependencies": {
+        "node-fetch": "^1.0.1",
+        "whatwg-fetch": ">=0.10.0"
+      }
+    },
     "node_modules/istanbul-lib-coverage": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@@ -11660,6 +11831,23 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/node-fetch": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-1.7.3.tgz",
+      "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+      "dependencies": {
+        "encoding": "^0.1.11",
+        "is-stream": "^1.0.1"
+      }
+    },
+    "node_modules/node-fetch/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/node-forge": {
       "version": "1.3.1",
       "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -15015,6 +15203,11 @@
         }
       }
     },
+    "node_modules/sass/node_modules/immutable": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.0.tgz",
+      "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
+    },
     "node_modules/sax": {
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz",
@@ -15231,6 +15424,11 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+    },
     "node_modules/setprototypeof": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -16140,6 +16338,14 @@
         "node": ">=4.2.0"
       }
     },
+    "node_modules/ua-parser-js": {
+      "version": "0.7.35",
+      "resolved": "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz",
+      "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/unbox-primitive": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -21283,6 +21489,67 @@
         "fill-range": "^7.0.1"
       }
     },
+    "braft-convert": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/braft-convert/-/braft-convert-2.3.0.tgz",
+      "integrity": "sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==",
+      "requires": {
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3"
+      },
+      "dependencies": {
+        "draft-convert": {
+          "version": "2.1.13",
+          "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+          "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+          "requires": {
+            "@babel/runtime": "^7.5.5",
+            "immutable": "~3.7.4",
+            "invariant": "^2.2.1"
+          }
+        }
+      }
+    },
+    "braft-editor": {
+      "version": "2.3.9",
+      "resolved": "https://registry.npmmirror.com/braft-editor/-/braft-editor-2.3.9.tgz",
+      "integrity": "sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==",
+      "requires": {
+        "@babel/runtime": "^7.0.0",
+        "braft-convert": "^2.3.0",
+        "braft-finder": "^0.0.19",
+        "braft-utils": "^3.0.8",
+        "draft-convert": "^2.0.0",
+        "draft-js": "^0.10.3",
+        "draft-js-multidecorators": "^1.0.0",
+        "draftjs-utils": "^0.9.4",
+        "immutable": "~3.7.4"
+      },
+      "dependencies": {
+        "braft-finder": {
+          "version": "0.0.19",
+          "resolved": "https://registry.npmmirror.com/braft-finder/-/braft-finder-0.0.19.tgz",
+          "integrity": "sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw==",
+          "requires": {}
+        },
+        "draft-convert": {
+          "version": "2.1.13",
+          "resolved": "https://registry.npmmirror.com/draft-convert/-/draft-convert-2.1.13.tgz",
+          "integrity": "sha512-/h/n4JCfyO8aWby7wKBkccHdsuVbbDyHWXi/B3Zf2pN++lN1lDOIVt5ulXCcbH2Y5YJEFzMJw/YGfN+R0axxxg==",
+          "requires": {
+            "@babel/runtime": "^7.5.5",
+            "immutable": "~3.7.4",
+            "invariant": "^2.2.1"
+          }
+        }
+      }
+    },
+    "braft-utils": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmmirror.com/braft-utils/-/braft-utils-3.0.12.tgz",
+      "integrity": "sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg==",
+      "requires": {}
+    },
     "browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -22253,6 +22520,30 @@
       "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
       "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
     },
+    "draft-js": {
+      "version": "0.10.5",
+      "resolved": "https://registry.npmmirror.com/draft-js/-/draft-js-0.10.5.tgz",
+      "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
+      "requires": {
+        "fbjs": "^0.8.15",
+        "immutable": "~3.7.4",
+        "object-assign": "^4.1.0"
+      }
+    },
+    "draft-js-multidecorators": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz",
+      "integrity": "sha512-7qdy+YQol5iq38AoEerhgSJWhCzxvZLn1x5ODfUlGfWlg0SrZ9AXJbaxHVIjdSIZNrbVIm+WANujNxMqCmDSZQ==",
+      "requires": {
+        "immutable": "*"
+      }
+    },
+    "draftjs-utils": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmmirror.com/draftjs-utils/-/draftjs-utils-0.9.4.tgz",
+      "integrity": "sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg==",
+      "requires": {}
+    },
     "duplexer": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
@@ -22296,6 +22587,14 @@
       "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
     },
+    "encoding": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
+      "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+      "requires": {
+        "iconv-lite": "^0.6.2"
+      }
+    },
     "enhanced-resolve": {
       "version": "5.10.0",
       "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
@@ -23117,6 +23416,35 @@
         "bser": "2.1.1"
       }
     },
+    "fbjs": {
+      "version": "0.8.18",
+      "resolved": "https://registry.npmmirror.com/fbjs/-/fbjs-0.8.18.tgz",
+      "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
+      "requires": {
+        "core-js": "^1.0.0",
+        "isomorphic-fetch": "^2.1.1",
+        "loose-envify": "^1.0.0",
+        "object-assign": "^4.1.0",
+        "promise": "^7.1.1",
+        "setimmediate": "^1.0.5",
+        "ua-parser-js": "^0.7.30"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "1.2.7",
+          "resolved": "https://registry.npmmirror.com/core-js/-/core-js-1.2.7.tgz",
+          "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="
+        },
+        "promise": {
+          "version": "7.3.1",
+          "resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz",
+          "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+          "requires": {
+            "asap": "~2.0.3"
+          }
+        }
+      }
+    },
     "file-entry-cache": {
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -23845,9 +24173,9 @@
       "integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
     },
     "immutable": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz",
-      "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
+      "version": "3.7.6",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-3.7.6.tgz",
+      "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw=="
     },
     "import-fresh": {
       "version": "3.3.0",
@@ -23918,6 +24246,14 @@
       "resolved": "https://registry.npmmirror.com/intersection-observer/-/intersection-observer-0.12.2.tgz",
       "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="
     },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "ipaddr.js": {
       "version": "2.0.1",
       "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@@ -24169,6 +24505,15 @@
       "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
     },
+    "isomorphic-fetch": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+      "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+      "requires": {
+        "node-fetch": "^1.0.1",
+        "whatwg-fetch": ">=0.10.0"
+      }
+    },
     "istanbul-lib-coverage": {
       "version": "3.2.0",
       "resolved": "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@@ -26155,6 +26500,22 @@
         "tslib": "^2.0.3"
       }
     },
+    "node-fetch": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-1.7.3.tgz",
+      "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+      "requires": {
+        "encoding": "^0.1.11",
+        "is-stream": "^1.0.1"
+      },
+      "dependencies": {
+        "is-stream": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz",
+          "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="
+        }
+      }
+    },
     "node-forge": {
       "version": "1.3.1",
       "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -28501,6 +28862,13 @@
         "chokidar": ">=3.0.0 <4.0.0",
         "immutable": "^4.0.0",
         "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "dependencies": {
+        "immutable": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.0.tgz",
+          "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
+        }
       }
     },
     "sass-loader": {
@@ -28698,6 +29066,11 @@
         "send": "0.18.0"
       }
     },
+    "setimmediate": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
+      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+    },
     "setprototypeof": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -29426,6 +29799,11 @@
       "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.8.4.tgz",
       "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ=="
     },
+    "ua-parser-js": {
+      "version": "0.7.35",
+      "resolved": "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz",
+      "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g=="
+    },
     "unbox-primitive": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",

+ 2 - 0
后台/package.json

@@ -14,6 +14,8 @@
     "antd": "^5.0.4",
     "antd-mobile": "^5.30.0",
     "axios": "^1.1.3",
+    "braft-editor": "^2.3.9",
+    "braft-utils": "^3.0.12",
     "dayjs": "^1.11.7",
     "js-base64": "^3.7.3",
     "react": "^18.2.0",

+ 50 - 0
后台/src/components/Z_RicjText/index.module.scss

@@ -0,0 +1,50 @@
+.RichText {
+  :global {
+    .txtBox {
+      width: 1000px;
+      border: 1px solid #ccc;
+
+      // 隐藏媒体功能
+      .control-item.media {
+        display: none;
+      }
+
+      .bf-controlbar {
+        position: relative;
+
+        .upImgBox {
+          position: absolute;
+          bottom: 13px;
+          right: 15px;
+          cursor: pointer;
+          color: var(--themeColor);
+        }
+        .upImgBoxNo{
+          display: none;
+        }
+
+      }
+    }
+
+    .noUpThumb {
+      position: relative;
+      overflow: hidden;
+      opacity: 0;
+      transition: top .2s;
+      color: #ff4d4f;
+      top: -10px;
+    }
+
+    .noUpThumbAc {
+      top: 0;
+      opacity: 1;
+    }
+
+    .bf-media {
+      display: block;
+      margin: 10px auto;
+      max-width: 300px;
+      max-height: 300px;
+    }
+  }
+}

+ 177 - 0
后台/src/components/Z_RicjText/index.tsx

@@ -0,0 +1,177 @@
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import styles from "./index.module.scss";
+
+// 引入编辑器组件
+
+// 安装---npm install braft-editor --save --force
+// npm install braft-utils --save --force
+import { ContentUtils } from "braft-utils";
+import BraftEditor from "braft-editor";
+// 引入编辑器样式
+import "braft-editor/dist/index.css";
+
+import classNames from "classnames";
+import { MessageFu } from "@/utils/message";
+import { B2_APIupFile } from "@/store/action/B2Goods";
+import { fileDomInitialFu } from "@/utils/domShow";
+import { baseURL } from "@/utils/http";
+
+type Props = {
+  check: boolean;
+  dirCode: string;
+  richTxt: string;
+  setRichTxt: (val: string) => void;
+  isLook: boolean;
+};
+
+function RichText({ check, dirCode, richTxt, setRichTxt, isLook }: Props) {
+  // 添加 上传 图片的dom
+  useEffect(() => {
+    setTimeout(() => {
+      const dom = document.querySelector(".bf-controlbar")!;
+      const div = document.createElement("div");
+      div.className = isLook ? "upImgBoxNo" : "upImgBox";
+      div.title = "上传图片";
+      div.innerHTML = "上传图片";
+      div.onclick = async () => {
+        myInput.current?.click();
+      };
+      dom.appendChild(div);
+    }, 200);
+  }, [isLook]);
+
+  // 编辑器文本
+  const [editorValue, setEditorValue] = useState(
+    // 初始内容
+    BraftEditor.createEditorState(richTxt)
+  );
+
+  // 判断 富文本是否为空
+  const isTxtFlag = useMemo(() => {
+    const txt: string = editorValue.toHTML();
+    if (
+      txt.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll(" ", "") ===
+      ""
+    ) {
+      return true;
+    } else return false;
+  }, [editorValue]);
+
+  // 回显数据
+  const timeRef = useRef(false);
+
+  useEffect(() => {
+    if (timeRef.current) return;
+    if (richTxt) {
+      setEditorValue(BraftEditor.createEditorState(richTxt));
+      timeRef.current = true;
+    }
+  }, [richTxt]);
+
+  // 富文本信息改变的回调
+  const handleChange = useCallback(
+    (e: any) => {
+      setEditorValue(e);
+      setRichTxt(editorValue.toHTML());
+    },
+    [editorValue, setRichTxt]
+  );
+
+  const myInput = useRef<HTMLInputElement>(null);
+
+  // 上传图片
+  const handeUpPhoto = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0];
+        // 校验格式
+        const type = ["image/jpeg", "image/png"];
+        if (!type.includes(filesInfo.type)) {
+          e.target.value = "";
+          return MessageFu.warning("只支持png、jpg和jpeg格式!");
+        }
+        // 校验大小
+        if (filesInfo.size > 5 * 1024 * 1024) {
+          e.target.value = "";
+          return MessageFu.warning("最大支持5M!");
+        }
+        // 创建FormData对象
+        const fd = new FormData();
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        fd.append("type", "thumb");
+        fd.append("dirCode", dirCode);
+        fd.append("file", filesInfo);
+
+        e.target.value = "";
+
+        try {
+          const res = await B2_APIupFile(fd);
+          if (res.code === 0) {
+            MessageFu.success("上传成功!");
+            // 在光标位置插入图片
+            const newTxt = ContentUtils.insertMedias(editorValue, [
+              {
+                type: "IMAGE",
+                url: baseURL + res.data.filePath,
+              },
+            ]);
+
+            setEditorValue(newTxt);
+          }
+          fileDomInitialFu();
+        } catch (error) {
+          fileDomInitialFu();
+        }
+      }
+    },
+    [dirCode, editorValue]
+  );
+
+  return (
+    <div className={styles.RichText}>
+      <input
+        id="upInput"
+        type="file"
+        accept=".png,.jpg,.jpeg"
+        ref={myInput}
+        onChange={(e) => handeUpPhoto(e)}
+      />
+
+      <div className="txtBox">
+        <BraftEditor
+          readOnly={isLook}
+          placeholder="请输入内容"
+          value={editorValue}
+          onChange={(e) => handleChange(e)}
+        />
+      </div>
+      <div
+        className={classNames(
+          "noUpThumb",
+          check && isTxtFlag ? "noUpThumbAc" : ""
+        )}
+      >
+        请输入正文!
+      </div>
+
+      {/* 编辑器内容 */}
+      {/* <br />
+      <button onClick={btnOk}>点击确定获取文本</button>
+      <br /> */}
+      {/* 插入图片 */}
+      {/* <br />
+      <button onClick={insertTextFu}>在光标位置插入内容</button> */}
+    </div>
+  );
+}
+
+const MemoRichText = React.memo(RichText);
+
+export default MemoRichText;

+ 47 - 29
后台/src/pages/B2Goods/B2Edit/index.tsx

@@ -1,13 +1,19 @@
-import React, { useCallback, useEffect, useRef, useState } from "react";
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
 import styles from "./index.module.scss";
 import classNames from "classnames";
 import { Button, Form, FormInstance, Input, Popconfirm, Select } from "antd";
 import { useSelector } from "react-redux";
 import { RootState } from "@/store";
-import TextArea from "antd/es/input/TextArea";
 import UpFileOne from "@/components/Z_upFileOne";
 import { B2_APIgetInfo, B2_APIsave } from "@/store/action/B2Goods";
 import { MessageFu } from "@/utils/message";
+import RichText from "@/components/Z_RicjText";
 
 type Props = {
   editId: number;
@@ -24,6 +30,8 @@ function B2Edit({ editId, isLook, closeFu, editFu, addFu, myType }: Props) {
     if (res.code === 0) {
       FormBoxRef.current?.setFieldsValue(res.data);
       setCover(res.data.thumb);
+
+      setRichTxt(res.data.content);
     }
   }, []);
 
@@ -48,20 +56,42 @@ function B2Edit({ editId, isLook, closeFu, editFu, addFu, myType }: Props) {
   // 图片
   const [cover, setCover] = useState("");
 
+  // 富文本的值
+  const [richTxt, setRichTxt] = useState("");
+
   // 没有通过校验
   const onFinishFailed = useCallback(() => {
     setCheck(true);
   }, []);
 
+  // 判断 富文本是否为空
+  const isTxtFlag = useMemo(() => {
+    if (
+      richTxt
+        .replaceAll("<p>", "")
+        .replaceAll("</p>", "")
+        .replaceAll(" ", "") === ""
+    ) {
+      return true;
+    } else return false;
+  }, [richTxt]);
+
   // 通过校验点击确定
   const onFinish = useCallback(
     async (value: any) => {
       setCheck(true);
+
+      // 图片没传
       if (!cover) return;
+
+      // 富文本 为空
+      if (isTxtFlag) return;
+
       const obj = {
         ...value,
         id: editId > 0 ? editId : null,
         thumb: cover,
+        content: richTxt,
       };
       const res = await B2_APIsave(obj);
       if (res.code === 0) {
@@ -72,7 +102,7 @@ function B2Edit({ editId, isLook, closeFu, editFu, addFu, myType }: Props) {
       }
       // console.log("通过校验,点击确定", res);
     },
-    [addFu, closeFu, cover, editFu, editId]
+    [addFu, closeFu, cover, editFu, editId, isTxtFlag, richTxt]
   );
 
   return (
@@ -116,32 +146,20 @@ function B2Edit({ editId, isLook, closeFu, editFu, addFu, myType }: Props) {
               />
             </Form.Item>
 
-            <Form.Item
-              label="正文"
-              name="content"
-              rules={[
-                { required: true, message: "请输入正文!" },
-                {
-                  validator: (rule, value) => {
-                    if (value) {
-                      const txt = value
-                        .replaceAll(" ", "")
-                        .replaceAll("\n", "");
-                      return txt === ""
-                        ? Promise.reject("请输入有效字符!")
-                        : Promise.resolve();
-                    } else return Promise.resolve();
-                  },
-                },
-              ]}
-            >
-              <TextArea
-                autoSize
-                placeholder="请输入内容"
-                showCount
-                maxLength={500}
-              />
-            </Form.Item>
+            <div className="e_row">
+              <div className="e_rowL">
+                <span>* </span>正文:
+              </div>
+              <div className="e_rowR">
+                <RichText
+                  check={check}
+                  dirCode="myGoods"
+                  richTxt={richTxt}
+                  setRichTxt={(val) => setRichTxt(val)}
+                  isLook={isLook}
+                />
+              </div>
+            </div>
 
             <div className="e_row">
               <div className="e_rowL">

+ 0 - 11
后台/src/pages/B2Goods/index.tsx

@@ -124,17 +124,6 @@ function B2Goods() {
         ),
       },
       {
-        title: "正文",
-        render: (item: B2TableType) =>
-          item.content.length >= 50 ? (
-            <span style={{ cursor: "pointer" }} title={item.content}>
-              {item.content.substring(0, 50) + "..."}
-            </span>
-          ) : (
-            item.content
-          ),
-      },
-      {
         title: "操作",
         render: (item: B2TableType) => (
           <>

+ 27 - 1
后台/src/store/action/B2Goods.ts

@@ -1,5 +1,7 @@
 import http from "@/utils/http";
-import { AppDispatch } from "..";
+import store, { AppDispatch } from "..";
+import axios from "axios";
+import { domShowFu, progressDomFu } from "@/utils/domShow";
 
 /**
  * 获取赏析-版块列表
@@ -44,3 +46,27 @@ export const B2_APIgetInfo = (id: number) => {
 export const B2_APIsave = (data: any) => {
   return http.post("cms/goods/save", data);
 };
+
+const CancelToken = axios.CancelToken;
+/**
+ * 上传封面图和附件
+ */
+export const B2_APIupFile = (data: any) => {
+  domShowFu("#UpAsyncLoding", true);
+
+  return http.post("cms/config/upload", data, {
+    timeout: 0,
+    // 显示进度条
+    onUploadProgress: (e: any) => {
+      const complete = (e.loaded / e.total) * 100 || 0;
+      progressDomFu(complete + "%");
+    },
+    // 取消上传
+    cancelToken: new CancelToken(function executor(c) {
+      store.dispatch({
+        type: "layout/closeUpFile",
+        payload: { fu: c, state: true },
+      });
+    }),
+  });
+};

+ 1 - 0
后台/src/types/declaration.d.ts

@@ -4,3 +4,4 @@ declare module "*.png";
 declare module "*.jpg";
 declare module "*.gif";
 declare module "js-export-excel";
+declare module 'braft-utils';