소스 검색

Merge branch 'cheney' into dev

WanGxC 6 달 전
부모
커밋
b4bb7ebd05

+ 201 - 216
package-lock.json

@@ -74,7 +74,7 @@
 				"typescript": "^5.6.2",
 				"unplugin-auto-import": "^0.18.3",
 				"unplugin-vue-components": "^0.27.4",
-				"vite": "^4.5.3",
+				"vite": "^5.4.11",
 				"vite-plugin-lazy-import": "^1.0.7",
 				"vite-plugin-vue-setup-extend": "^0.4.0",
 				"vue-eslint-parser": "^9.1.0"
@@ -1533,10 +1533,26 @@
 				"vue": "^3.2.0"
 			}
 		},
+		"node_modules/@esbuild/aix-ppc64": {
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+			"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+			"cpu": [
+				"ppc64"
+			],
+			"license": "MIT",
+			"optional": true,
+			"os": [
+				"aix"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
 		"node_modules/@esbuild/android-arm": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
-			"integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+			"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
 			"cpu": [
 				"arm"
 			],
@@ -1550,9 +1566,9 @@
 			}
 		},
 		"node_modules/@esbuild/android-arm64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
-			"integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+			"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
 			"cpu": [
 				"arm64"
 			],
@@ -1566,9 +1582,9 @@
 			}
 		},
 		"node_modules/@esbuild/android-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
-			"integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+			"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
 			"cpu": [
 				"x64"
 			],
@@ -1582,9 +1598,9 @@
 			}
 		},
 		"node_modules/@esbuild/darwin-arm64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
-			"integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+			"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
 			"cpu": [
 				"arm64"
 			],
@@ -1598,9 +1614,9 @@
 			}
 		},
 		"node_modules/@esbuild/darwin-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
-			"integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+			"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
 			"cpu": [
 				"x64"
 			],
@@ -1614,9 +1630,9 @@
 			}
 		},
 		"node_modules/@esbuild/freebsd-arm64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
-			"integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+			"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
 			"cpu": [
 				"arm64"
 			],
@@ -1630,9 +1646,9 @@
 			}
 		},
 		"node_modules/@esbuild/freebsd-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
-			"integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+			"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
 			"cpu": [
 				"x64"
 			],
@@ -1646,9 +1662,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-arm": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
-			"integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+			"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
 			"cpu": [
 				"arm"
 			],
@@ -1662,9 +1678,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-arm64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
-			"integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+			"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
 			"cpu": [
 				"arm64"
 			],
@@ -1678,9 +1694,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-ia32": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
-			"integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+			"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
 			"cpu": [
 				"ia32"
 			],
@@ -1694,9 +1710,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-loong64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
-			"integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+			"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
 			"cpu": [
 				"loong64"
 			],
@@ -1710,9 +1726,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-mips64el": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
-			"integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+			"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
 			"cpu": [
 				"mips64el"
 			],
@@ -1726,9 +1742,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-ppc64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
-			"integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+			"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
 			"cpu": [
 				"ppc64"
 			],
@@ -1742,9 +1758,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-riscv64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
-			"integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+			"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
 			"cpu": [
 				"riscv64"
 			],
@@ -1758,9 +1774,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-s390x": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
-			"integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+			"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
 			"cpu": [
 				"s390x"
 			],
@@ -1774,9 +1790,9 @@
 			}
 		},
 		"node_modules/@esbuild/linux-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
-			"integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+			"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
 			"cpu": [
 				"x64"
 			],
@@ -1790,9 +1806,9 @@
 			}
 		},
 		"node_modules/@esbuild/netbsd-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
-			"integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+			"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
 			"cpu": [
 				"x64"
 			],
@@ -1806,9 +1822,9 @@
 			}
 		},
 		"node_modules/@esbuild/openbsd-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
-			"integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+			"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
 			"cpu": [
 				"x64"
 			],
@@ -1822,9 +1838,9 @@
 			}
 		},
 		"node_modules/@esbuild/sunos-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
-			"integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+			"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
 			"cpu": [
 				"x64"
 			],
@@ -1838,9 +1854,9 @@
 			}
 		},
 		"node_modules/@esbuild/win32-arm64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
-			"integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+			"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
 			"cpu": [
 				"arm64"
 			],
@@ -1854,9 +1870,9 @@
 			}
 		},
 		"node_modules/@esbuild/win32-ia32": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
-			"integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+			"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
 			"cpu": [
 				"ia32"
 			],
@@ -1870,9 +1886,9 @@
 			}
 		},
 		"node_modules/@esbuild/win32-x64": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
-			"integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+			"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
 			"cpu": [
 				"x64"
 			],
@@ -2526,13 +2542,12 @@
 			}
 		},
 		"node_modules/@rollup/rollup-android-arm-eabi": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz",
-			"integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.26.0.tgz",
+			"integrity": "sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==",
 			"cpu": [
 				"arm"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2540,13 +2555,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-android-arm64": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz",
-			"integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.26.0.tgz",
+			"integrity": "sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2554,13 +2568,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-darwin-arm64": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz",
-			"integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz",
+			"integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2568,13 +2581,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-darwin-x64": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz",
-			"integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.26.0.tgz",
+			"integrity": "sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==",
 			"cpu": [
 				"x64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2582,13 +2594,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-freebsd-arm64": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz",
-			"integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.26.0.tgz",
+			"integrity": "sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2596,13 +2607,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-freebsd-x64": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz",
-			"integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.26.0.tgz",
+			"integrity": "sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==",
 			"cpu": [
 				"x64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2610,13 +2620,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz",
-			"integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.26.0.tgz",
+			"integrity": "sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==",
 			"cpu": [
 				"arm"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2624,13 +2633,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-arm-musleabihf": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz",
-			"integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.26.0.tgz",
+			"integrity": "sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==",
 			"cpu": [
 				"arm"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2638,13 +2646,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-arm64-gnu": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz",
-			"integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.26.0.tgz",
+			"integrity": "sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2652,13 +2659,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-arm64-musl": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz",
-			"integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.26.0.tgz",
+			"integrity": "sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2666,13 +2672,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz",
-			"integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.26.0.tgz",
+			"integrity": "sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==",
 			"cpu": [
 				"ppc64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2680,13 +2685,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-riscv64-gnu": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz",
-			"integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.26.0.tgz",
+			"integrity": "sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==",
 			"cpu": [
 				"riscv64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2694,13 +2698,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-s390x-gnu": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz",
-			"integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.26.0.tgz",
+			"integrity": "sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==",
 			"cpu": [
 				"s390x"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2708,13 +2711,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-x64-gnu": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz",
-			"integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.26.0.tgz",
+			"integrity": "sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==",
 			"cpu": [
 				"x64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2722,13 +2724,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-linux-x64-musl": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz",
-			"integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.26.0.tgz",
+			"integrity": "sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==",
 			"cpu": [
 				"x64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2736,13 +2737,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-win32-arm64-msvc": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz",
-			"integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.26.0.tgz",
+			"integrity": "sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==",
 			"cpu": [
 				"arm64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2750,13 +2750,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-win32-ia32-msvc": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz",
-			"integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.26.0.tgz",
+			"integrity": "sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==",
 			"cpu": [
 				"ia32"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -2764,13 +2763,12 @@
 			]
 		},
 		"node_modules/@rollup/rollup-win32-x64-msvc": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz",
-			"integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.26.0.tgz",
+			"integrity": "sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==",
 			"cpu": [
 				"x64"
 			],
-			"dev": true,
 			"license": "MIT",
 			"optional": true,
 			"os": [
@@ -3505,7 +3503,6 @@
 			"version": "1.0.6",
 			"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
 			"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
-			"dev": true,
 			"license": "MIT"
 		},
 		"node_modules/@types/event-emitter": {
@@ -5557,9 +5554,9 @@
 			}
 		},
 		"node_modules/esbuild": {
-			"version": "0.18.20",
-			"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz",
-			"integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+			"version": "0.21.5",
+			"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
+			"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
 			"hasInstallScript": true,
 			"license": "MIT",
 			"bin": {
@@ -5569,28 +5566,29 @@
 				"node": ">=12"
 			},
 			"optionalDependencies": {
-				"@esbuild/android-arm": "0.18.20",
-				"@esbuild/android-arm64": "0.18.20",
-				"@esbuild/android-x64": "0.18.20",
-				"@esbuild/darwin-arm64": "0.18.20",
-				"@esbuild/darwin-x64": "0.18.20",
-				"@esbuild/freebsd-arm64": "0.18.20",
-				"@esbuild/freebsd-x64": "0.18.20",
-				"@esbuild/linux-arm": "0.18.20",
-				"@esbuild/linux-arm64": "0.18.20",
-				"@esbuild/linux-ia32": "0.18.20",
-				"@esbuild/linux-loong64": "0.18.20",
-				"@esbuild/linux-mips64el": "0.18.20",
-				"@esbuild/linux-ppc64": "0.18.20",
-				"@esbuild/linux-riscv64": "0.18.20",
-				"@esbuild/linux-s390x": "0.18.20",
-				"@esbuild/linux-x64": "0.18.20",
-				"@esbuild/netbsd-x64": "0.18.20",
-				"@esbuild/openbsd-x64": "0.18.20",
-				"@esbuild/sunos-x64": "0.18.20",
-				"@esbuild/win32-arm64": "0.18.20",
-				"@esbuild/win32-ia32": "0.18.20",
-				"@esbuild/win32-x64": "0.18.20"
+				"@esbuild/aix-ppc64": "0.21.5",
+				"@esbuild/android-arm": "0.21.5",
+				"@esbuild/android-arm64": "0.21.5",
+				"@esbuild/android-x64": "0.21.5",
+				"@esbuild/darwin-arm64": "0.21.5",
+				"@esbuild/darwin-x64": "0.21.5",
+				"@esbuild/freebsd-arm64": "0.21.5",
+				"@esbuild/freebsd-x64": "0.21.5",
+				"@esbuild/linux-arm": "0.21.5",
+				"@esbuild/linux-arm64": "0.21.5",
+				"@esbuild/linux-ia32": "0.21.5",
+				"@esbuild/linux-loong64": "0.21.5",
+				"@esbuild/linux-mips64el": "0.21.5",
+				"@esbuild/linux-ppc64": "0.21.5",
+				"@esbuild/linux-riscv64": "0.21.5",
+				"@esbuild/linux-s390x": "0.21.5",
+				"@esbuild/linux-x64": "0.21.5",
+				"@esbuild/netbsd-x64": "0.21.5",
+				"@esbuild/openbsd-x64": "0.21.5",
+				"@esbuild/sunos-x64": "0.21.5",
+				"@esbuild/win32-arm64": "0.21.5",
+				"@esbuild/win32-ia32": "0.21.5",
+				"@esbuild/win32-x64": "0.21.5"
 			}
 		},
 		"node_modules/escalade": {
@@ -8435,18 +8433,39 @@
 			}
 		},
 		"node_modules/rollup": {
-			"version": "3.29.5",
-			"resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.29.5.tgz",
-			"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
+			"version": "4.26.0",
+			"resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.26.0.tgz",
+			"integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==",
 			"license": "MIT",
+			"dependencies": {
+				"@types/estree": "1.0.6"
+			},
 			"bin": {
 				"rollup": "dist/bin/rollup"
 			},
 			"engines": {
-				"node": ">=14.18.0",
+				"node": ">=18.0.0",
 				"npm": ">=8.0.0"
 			},
 			"optionalDependencies": {
+				"@rollup/rollup-android-arm-eabi": "4.26.0",
+				"@rollup/rollup-android-arm64": "4.26.0",
+				"@rollup/rollup-darwin-arm64": "4.26.0",
+				"@rollup/rollup-darwin-x64": "4.26.0",
+				"@rollup/rollup-freebsd-arm64": "4.26.0",
+				"@rollup/rollup-freebsd-x64": "4.26.0",
+				"@rollup/rollup-linux-arm-gnueabihf": "4.26.0",
+				"@rollup/rollup-linux-arm-musleabihf": "4.26.0",
+				"@rollup/rollup-linux-arm64-gnu": "4.26.0",
+				"@rollup/rollup-linux-arm64-musl": "4.26.0",
+				"@rollup/rollup-linux-powerpc64le-gnu": "4.26.0",
+				"@rollup/rollup-linux-riscv64-gnu": "4.26.0",
+				"@rollup/rollup-linux-s390x-gnu": "4.26.0",
+				"@rollup/rollup-linux-x64-gnu": "4.26.0",
+				"@rollup/rollup-linux-x64-musl": "4.26.0",
+				"@rollup/rollup-win32-arm64-msvc": "4.26.0",
+				"@rollup/rollup-win32-ia32-msvc": "4.26.0",
+				"@rollup/rollup-win32-x64-msvc": "4.26.0",
 				"fsevents": "~2.3.2"
 			}
 		},
@@ -9575,32 +9594,33 @@
 			}
 		},
 		"node_modules/vite": {
-			"version": "4.5.5",
-			"resolved": "https://registry.npmmirror.com/vite/-/vite-4.5.5.tgz",
-			"integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==",
+			"version": "5.4.11",
+			"resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.11.tgz",
+			"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
 			"license": "MIT",
 			"dependencies": {
-				"esbuild": "^0.18.10",
-				"postcss": "^8.4.27",
-				"rollup": "^3.27.1"
+				"esbuild": "^0.21.3",
+				"postcss": "^8.4.43",
+				"rollup": "^4.20.0"
 			},
 			"bin": {
 				"vite": "bin/vite.js"
 			},
 			"engines": {
-				"node": "^14.18.0 || >=16.0.0"
+				"node": "^18.0.0 || >=20.0.0"
 			},
 			"funding": {
 				"url": "https://github.com/vitejs/vite?sponsor=1"
 			},
 			"optionalDependencies": {
-				"fsevents": "~2.3.2"
+				"fsevents": "~2.3.3"
 			},
 			"peerDependencies": {
-				"@types/node": ">= 14",
+				"@types/node": "^18.0.0 || >=20.0.0",
 				"less": "*",
 				"lightningcss": "^1.21.0",
 				"sass": "*",
+				"sass-embedded": "*",
 				"stylus": "*",
 				"sugarss": "*",
 				"terser": "^5.4.0"
@@ -9618,6 +9638,9 @@
 				"sass": {
 					"optional": true
 				},
+				"sass-embedded": {
+					"optional": true
+				},
 				"stylus": {
 					"optional": true
 				},
@@ -9656,44 +9679,6 @@
 				"xe-utils": "^3.5.26"
 			}
 		},
-		"node_modules/vite-plugin-lazy-import/node_modules/rollup": {
-			"version": "4.24.3",
-			"resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.24.3.tgz",
-			"integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@types/estree": "1.0.6"
-			},
-			"bin": {
-				"rollup": "dist/bin/rollup"
-			},
-			"engines": {
-				"node": ">=18.0.0",
-				"npm": ">=8.0.0"
-			},
-			"optionalDependencies": {
-				"@rollup/rollup-android-arm-eabi": "4.24.3",
-				"@rollup/rollup-android-arm64": "4.24.3",
-				"@rollup/rollup-darwin-arm64": "4.24.3",
-				"@rollup/rollup-darwin-x64": "4.24.3",
-				"@rollup/rollup-freebsd-arm64": "4.24.3",
-				"@rollup/rollup-freebsd-x64": "4.24.3",
-				"@rollup/rollup-linux-arm-gnueabihf": "4.24.3",
-				"@rollup/rollup-linux-arm-musleabihf": "4.24.3",
-				"@rollup/rollup-linux-arm64-gnu": "4.24.3",
-				"@rollup/rollup-linux-arm64-musl": "4.24.3",
-				"@rollup/rollup-linux-powerpc64le-gnu": "4.24.3",
-				"@rollup/rollup-linux-riscv64-gnu": "4.24.3",
-				"@rollup/rollup-linux-s390x-gnu": "4.24.3",
-				"@rollup/rollup-linux-x64-gnu": "4.24.3",
-				"@rollup/rollup-linux-x64-musl": "4.24.3",
-				"@rollup/rollup-win32-arm64-msvc": "4.24.3",
-				"@rollup/rollup-win32-ia32-msvc": "4.24.3",
-				"@rollup/rollup-win32-x64-msvc": "4.24.3",
-				"fsevents": "~2.3.2"
-			}
-		},
 		"node_modules/vite-plugin-vue-setup-extend": {
 			"version": "0.4.0",
 			"resolved": "https://registry.npmmirror.com/vite-plugin-vue-setup-extend/-/vite-plugin-vue-setup-extend-0.4.0.tgz",

+ 1 - 1
package.json

@@ -75,7 +75,7 @@
 		"typescript": "^5.6.2",
 		"unplugin-auto-import": "^0.18.3",
 		"unplugin-vue-components": "^0.27.4",
-		"vite": "^4.5.3",
+		"vite": "^5.4.11",
 		"vite-plugin-lazy-import": "^1.0.7",
 		"vite-plugin-vue-setup-extend": "^0.4.0",
 		"vue-eslint-parser": "^9.1.0"

+ 110 - 94
src/layout/navBars/breadcrumb/breadcrumb.vue

@@ -1,29 +1,40 @@
 <template>
-	<div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb">
-		<SvgIcon
-			class="layout-navbars-breadcrumb-icon"
-			:name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
-			:size="16"
-			@click="onThemeConfigChange"
-		/>
-		<el-breadcrumb class="layout-navbars-breadcrumb-hide">
-			<transition-group name="breadcrumb">
-				<el-breadcrumb-item v-for="(v, k) in state.breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
+  <div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb">
+    <SvgIcon
+        :name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'"
+        :size="16"
+        class="layout-navbars-breadcrumb-icon"
+        @click="onThemeConfigChange"
+    />
+    <el-breadcrumb class="layout-navbars-breadcrumb-hide">
+      <transition-group name="breadcrumb">
+        <el-breadcrumb-item class="flex items-center " style="font-size: 14px" v-for="(v, k) in state.breadcrumbList"
+                            :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName">
 					<span v-if="k === state.breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
-						<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />
-						<div v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div>
-						<div v-else>{{ v.meta.tagsViewName }}</div>
+						<SvgIcon v-if="themeConfig.isBreadcrumbIcon" :name="v.meta.icon"
+                     class="layout-navbars-breadcrumb-iconfont"/>
+						<div style="margin-bottom: 2px;" v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div>
+						<div style="margin-bottom: 2px;" v-else>{{ v.meta.tagsViewName }}</div>
 					</span>
-					<a v-else @click.prevent="onBreadcrumbClick(v)">
-						<SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />{{ $t(v.meta.title) }}
-					</a>
-				</el-breadcrumb-item>
-			</transition-group>
-		</el-breadcrumb>
-	</div>
+          <a v-else @click.prevent="onBreadcrumbClick(v)">
+            <SvgIcon v-if="themeConfig.isBreadcrumbIcon" :name="v.meta.icon"
+                     :style="[
+                        v.meta.icon.startsWith('el') ? {
+                          'vertical-align': 'middle',
+                          'margin': '0 5px 1px 5px',
+                          'text-align': 'center',
+                        } : {}
+                      ]"
+                     class="layout-navbars-breadcrumb-iconfont"/>
+            {{ $t(v.meta.title) }}
+          </a>
+        </el-breadcrumb-item>
+      </transition-group>
+    </el-breadcrumb>
+  </div>
 </template>
 
-<script setup lang="ts" name="layoutBreadcrumb">
+<script lang="ts" name="layoutBreadcrumb" setup>
 import { reactive, computed, onMounted } from 'vue';
 import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
 import { Local } from '/@/utils/storage';
@@ -40,107 +51,112 @@ const { routesList } = storeToRefs(stores);
 const route = useRoute();
 const router = useRouter();
 const state = reactive<BreadcrumbState>({
-	breadcrumbList: [],
-	routeSplit: [],
-	routeSplitFirst: '',
-	routeSplitIndex: 1,
+  breadcrumbList: [],
+  routeSplit: [],
+  routeSplitFirst: '',
+  routeSplitIndex: 1
 });
 
 // 动态设置经典、横向布局不显示
 const isShowBreadcrumb = computed(() => {
-	initRouteSplit(route.path);
-	const { layout, isBreadcrumb } = themeConfig.value;
-	if (layout === 'classic' || layout === 'transverse') return false;
-	else return isBreadcrumb ? true : false;
+  initRouteSplit(route.path);
+  const { layout, isBreadcrumb } = themeConfig.value;
+  if (layout === 'classic' || layout === 'transverse') return false;
+  else return isBreadcrumb ? true : false;
 });
 // 面包屑点击时
 const onBreadcrumbClick = (v: RouteItem) => {
-	const { redirect, path } = v;
-	if (redirect) router.push(redirect);
-	else router.push(path);
+  const { redirect, path } = v;
+  if (redirect) router.push(redirect);
+  else router.push(path);
 };
 // 展开/收起左侧菜单点击
 const onThemeConfigChange = () => {
-	themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
-	setLocalThemeConfig();
+  themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
+  setLocalThemeConfig();
 };
 // 存储布局配置
 const setLocalThemeConfig = () => {
-	Local.remove('themeConfig');
-	Local.set('themeConfig', themeConfig.value);
+  Local.remove('themeConfig');
+  Local.set('themeConfig', themeConfig.value);
 };
 // 处理面包屑数据
 const getBreadcrumbList = (arr: RouteItems) => {
-	arr.forEach((item: RouteItem) => {
-		state.routeSplit.forEach((v: string, k: number, arrs: string[]) => {
-			if (state.routeSplitFirst === item.path) {
-				state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`;
-				state.breadcrumbList.push(item);
-				state.routeSplitIndex++;
-				if (item.children) getBreadcrumbList(item.children);
-			}
-		});
-	});
+  arr.forEach((item: RouteItem) => {
+    state.routeSplit.forEach((v: string, k: number, arrs: string[]) => {
+      if (state.routeSplitFirst === item.path) {
+        state.routeSplitFirst += `/${ arrs[state.routeSplitIndex] }`;
+        state.breadcrumbList.push(item);
+        state.routeSplitIndex++;
+        if (item.children) getBreadcrumbList(item.children);
+      }
+    });
+  });
 };
 // 当前路由字符串切割成数组,并删除第一项空内容
 const initRouteSplit = (path: string) => {
-	if (!themeConfig.value.isBreadcrumb) return false;
-	state.breadcrumbList = [routesList.value[0]];
-	state.routeSplit = path.split('/');
-	state.routeSplit.shift();
-	state.routeSplitFirst = `/${state.routeSplit[0]}`;
-	state.routeSplitIndex = 1;
-	getBreadcrumbList(routesList.value);
-	if (route.name === 'home' || (route.name === 'notFound' && state.breadcrumbList.length > 1)) state.breadcrumbList.shift();
-	if (state.breadcrumbList.length > 0)
-		state.breadcrumbList[state.breadcrumbList.length - 1].meta.tagsViewName = other.setTagsViewNameI18n(<RouteToFrom>route);
+  if (!themeConfig.value.isBreadcrumb) return false;
+  state.breadcrumbList = [ routesList.value[0] ];
+  state.routeSplit = path.split('/');
+  state.routeSplit.shift();
+  state.routeSplitFirst = `/${ state.routeSplit[0] }`;
+  state.routeSplitIndex = 1;
+  getBreadcrumbList(routesList.value);
+  if (route.name === 'home' || (route.name === 'notFound' && state.breadcrumbList.length > 1)) state.breadcrumbList.shift();
+  if (state.breadcrumbList.length > 0)
+    state.breadcrumbList[state.breadcrumbList.length - 1].meta.tagsViewName = other.setTagsViewNameI18n(<RouteToFrom>route);
 };
 // 页面加载时
 onMounted(() => {
-	initRouteSplit(route.path);
+  initRouteSplit(route.path);
 });
 // 路由更新时
 onBeforeRouteUpdate((to) => {
-	initRouteSplit(to.path);
+  initRouteSplit(to.path);
 });
 </script>
 
-<style scoped lang="scss">
+<style lang="scss" scoped>
 .layout-navbars-breadcrumb {
-	flex: 1;
-	height: inherit;
-	display: flex;
-	align-items: center;
-	.layout-navbars-breadcrumb-icon {
-		cursor: pointer;
-		font-size: 18px;
-		color: var(--next-bg-topBarColor);
-		height: 100%;
-		width: 40px;
-		opacity: 0.8;
-		&:hover {
-			opacity: 1;
-		}
-	}
-	.layout-navbars-breadcrumb-span {
-		display: flex;
-		opacity: 0.7;
-		color: var(--next-bg-topBarColor);
-	}
-	.layout-navbars-breadcrumb-iconfont {
-		font-size: 14px;
-		margin-right: 5px;
-	}
-	:deep(.el-breadcrumb__separator) {
-		opacity: 0.7;
-		color: var(--next-bg-topBarColor);
-	}
-	:deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
-		font-weight: unset !important;
-		color: var(--next-bg-topBarColor);
-		&:hover {
-			color: var(--el-color-primary) !important;
-		}
-	}
+  display: flex;
+  align-items: center;
+  
+  .layout-navbars-breadcrumb-icon {
+    cursor: pointer;
+    font-size: 18px;
+    color: var(--next-bg-topBarColor);
+    height: 100%;
+    width: 40px;
+    opacity: 0.8;
+
+    &:hover {
+      opacity: 1;
+    }
+  }
+
+  .layout-navbars-breadcrumb-span {
+    display: flex;
+    opacity: 0.7;
+    color: var(--next-bg-topBarColor);
+  }
+
+  .layout-navbars-breadcrumb-iconfont {
+    font-size: 14px;
+    margin-right: 5px;
+  }
+
+  :deep(.el-breadcrumb__separator) {
+    opacity: 0.7;
+    color: var(--next-bg-topBarColor);
+  }
+
+  :deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
+    font-weight: unset !important;
+    color: var(--next-bg-topBarColor);
+
+    &:hover {
+      color: var(--el-color-primary) !important;
+    }
+  }
 }
 </style>

+ 1 - 1
src/layout/navBars/tagsView/tagsView.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="layout-navbars-tagsview" :class="{ 'layout-navbars-tagsview-shadow': getThemeConfig.layout === 'classic' }">
 		<el-scrollbar ref="scrollbarRef" @wheel.prevent="onHandleScroll">
-			<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef">
+			<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef" style="background-color:#fff !important;">
 				<li
 					v-for="(v, k) in state.tagsViewList"
 					:key="k"

+ 1 - 1
src/stores/themeConfig.ts

@@ -68,7 +68,7 @@ export const useThemeConfig = defineStore('themeConfig', {
 			// 是否开启菜单水平折叠效果
 			isCollapse: false,
 			// 是否开启菜单手风琴效果
-			isUniqueOpened: true,
+			isUniqueOpened: false,
 			// 是否开启固定 Header
 			isFixedHeader: true,
 			// 初始化变量,用于更新菜单 el-scrollbar 的高度,请勿删除

+ 23 - 0
src/utils/useCopyText.ts

@@ -0,0 +1,23 @@
+export function handleCopy(copyText: string) {
+  const textarea = document.createElement("textarea");
+  textarea.value = copyText; // 要复制的内容
+  textarea.style.position = "fixed"; // 避免页面滚动
+  textarea.style.opacity = "0";     // 隐藏元素
+  document.body.appendChild(textarea);
+
+  textarea.select(); // 选中内容
+
+  try {
+    const successful = document.execCommand("copy"); // 执行复制命令
+    if (successful) {
+      ElMessage.success({ message: "复制成功!", plain: true });
+    } else {
+      ElMessage.error({ message: "复制失败,请手动复制!", plain: true });
+    }
+  } catch (error) {
+    ElMessage.error({ message: "复制失败,请重试!", plain: true });
+    console.error("复制失败:", error);
+  }
+
+  document.body.removeChild(textarea); // 清理临时元素
+}

+ 38 - 0
src/utils/useCustomHeight.ts

@@ -0,0 +1,38 @@
+export function useTableHeight(heightObj: Record<string, number | Ref<HTMLElement | null>>) {
+  const tableHeight = ref<number>(0);
+
+  const calculateHeight = () => {
+    let totalHeight = 0;
+    const entries = Object.entries(heightObj);
+
+    entries.forEach(([key, height], index) => {
+      // console.log(`Processing ${key} at index ${index}:`);
+
+      // 判断 height 是否为 ref,如果是则解引用,否则直接使用数值
+      const resolvedHeight = isRef(height) ? unref(height) : height;
+
+      let currentHeight = 0;
+      if (typeof resolvedHeight === 'number') {
+        currentHeight = resolvedHeight;
+      } else if (resolvedHeight instanceof HTMLElement) {
+        currentHeight = resolvedHeight.offsetHeight;
+      }
+
+      totalHeight += currentHeight;
+      // console.log(`Key: ${key}, Current height: ${currentHeight}, Total so far: ${totalHeight}`);
+    });
+
+    tableHeight.value = window.innerHeight - totalHeight;
+  };
+
+  onMounted(() => {
+    calculateHeight();
+    window.addEventListener('resize', calculateHeight);
+  });
+
+  onBeforeUnmount(() => {
+    window.removeEventListener('resize', calculateHeight);
+  });
+
+  return { tableHeight };
+}

+ 3 - 1
src/utils/useTableHeight.ts

@@ -11,6 +11,7 @@ export function useTableHeight(titleRef: Ref<HTMLElement | null>, queryRef: Ref<
     dividerHeight: 32,
     toolbarHeight: 51,
     padding: 40,
+    tagView: 34
   });
 
   const totalOtherHeight = ref(0);
@@ -29,7 +30,8 @@ export function useTableHeight(titleRef: Ref<HTMLElement | null>, queryRef: Ref<
         computeTableHeight.value.headerHeight +
         computeTableHeight.value.dividerHeight +
         computeTableHeight.value.toolbarHeight +
-        computeTableHeight.value.padding;
+        computeTableHeight.value.padding
+        // computeTableHeight.value.tagView;
 
     tableHeight.value = window.innerHeight - totalOtherHeight.value;
   };

+ 10 - 0
src/views/product-manage/comment-detail/api.ts

@@ -0,0 +1,10 @@
+import { request } from '/@/utils/service';
+
+
+export function getChartData(query: any) {
+  return request({
+    url: '/api/choice/reviews/stat_avg_score/',
+    method: 'GET',
+    params: query
+  });
+}

+ 159 - 0
src/views/product-manage/comment-detail/component/AverageMonthly.vue

@@ -0,0 +1,159 @@
+<script lang="ts" setup>
+/**
+ * @Name: AverageMonthly.vue
+ * @Description: 月平均分图表
+ * @Author: Cheney
+ */
+
+import * as echarts from 'echarts';
+import * as api from '../api';
+import { useResponse } from '/@/utils/useResponse';
+
+
+const props = defineProps({
+  asin: String
+});
+const { asin } = props;
+
+let chartRef: any = useTemplateRef('chartRef');
+let chart: echarts.ECharts | null = null;
+let resizeObserver: ResizeObserver | null = null;
+let chartData: any = [];
+
+onBeforeMount(() => {
+  fetchChartData();
+});
+
+onMounted(() => {
+  initChart();
+});
+
+onUnmounted(() => {
+  resizeObserver?.disconnect();
+  chart?.dispose();
+});
+
+function updateChart() {
+  if (!chart || chartData.length === 0) return;
+
+  const chartOptions = {
+    title: {
+      text: '每月平均评分'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: [ '总量', '平均分' ]
+    },
+    grid: {
+      top: '20%',
+      left: '10%',
+      right: '10%',
+      bottom: '10%'
+    },
+    dataset: {
+      dimensions: [ 'month', 'total', 'avg_score' ],
+      source: chartData
+    },
+    xAxis: {
+      type: 'category'
+    },
+    yAxis: [
+      {
+        id: 0,
+        type: 'value',
+        name: '总量',
+        nameTextStyle: {
+          fontWeight: 'bold',
+          fontSize: 14,
+          color: '#333'
+        },
+        splitLine: {
+          show: true
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: '#333',
+            width: 1
+          }
+        }
+      },
+      {
+        id: 1,
+        type: 'value',
+        name: '平均分',
+        nameTextStyle: {
+          fontWeight: 'bold',
+          fontSize: 14,
+          color: '#333'
+        },
+        splitLine: {
+          show: false
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: '#333',
+            width: 1
+          }
+        }
+      }
+    ],
+    series: [
+      {
+        yAxisIndex: 0,
+        name: '总量',
+        type: 'bar',
+        barWidth: '18px',
+        itemStyle: {
+          borderRadius: [ 4, 4, 4, 4 ]
+        }
+      },
+      {
+        yAxisIndex: 1,
+        name: '平均分',
+        type: 'line'
+      }
+    ]
+  };
+
+  chart.setOption(chartOptions);
+}
+
+function initChart() {
+  if (!chartRef.value) return;
+
+  chart = echarts.init(chartRef.value);
+  updateChart();
+
+  resizeObserver = new ResizeObserver(() => {
+    chart?.resize();
+  });
+  if (chartRef.value) {
+    resizeObserver.observe(chartRef.value);
+  }
+}
+
+async function fetchChartData() {
+  const res = await useResponse(api.getChartData, { asin });
+  if (res.code === 2000 && res.data) {
+    chartData = res.data;
+    updateChart();
+  }
+}
+</script>
+
+<template>
+  <el-card class="border-none" shadow="hover">
+    <div ref="chartRef" class="chart"></div>
+  </el-card>
+</template>
+
+<style scoped>
+.chart {
+  width: 100%;
+  height: 400px;
+}
+</style>

+ 18 - 0
src/views/product-manage/comment-detail/component/NegativeClassification.vue

@@ -0,0 +1,18 @@
+<script lang="ts" setup>
+/**
+ * @Name: NegativeClassification.vue
+ * @Description: 负面标签分类
+ * @Author: Cheney
+ */
+
+</script>
+
+<template>
+  <el-card shadow="hover" class="border-none">
+    负面标签分类
+  </el-card>
+</template>
+
+<style scoped>
+
+</style>

+ 18 - 0
src/views/product-manage/comment-detail/component/NegativeLabel.vue

@@ -0,0 +1,18 @@
+<script lang="ts" setup>
+/**
+ * @Name: NegativeLabel.vue
+ * @Description: 负面标签
+ * @Author: Cheney
+ */
+
+</script>
+
+<template>
+  <el-card shadow="hover" class="border-none">
+    负面标签
+  </el-card>
+</template>
+
+<style scoped>
+
+</style>

+ 101 - 0
src/views/product-manage/comment-detail/index.vue

@@ -0,0 +1,101 @@
+<script lang="ts" setup>
+/**
+ * @Name: index.vue
+ * @Description: 评论详情
+ * @Author: Cheney
+ */
+
+import { DocumentCopy, Picture as IconPicture } from '@element-plus/icons-vue';
+import NegativeLabel from '/@/views/product-manage/comment-detail/component/NegativeLabel.vue';
+import NegativeClassification from '/@/views/product-manage/comment-detail/component/NegativeClassification.vue';
+import AverageMonthly from '/@/views/product-manage/comment-detail/component/AverageMonthly.vue';
+import VerticalDivider from '/@/components/VerticalDivider/index.vue';
+import { handleCopy } from '/@/utils/useCopyText';
+
+
+const isShowComment = defineModel({ default: false });
+
+const props = defineProps({
+  rowData: <any>Object,
+  title: String
+});
+const { rowData } = props;
+
+
+</script>
+
+<template>
+  <div class="drawer-container">
+    <el-drawer
+        ref="editDrawer"
+        v-model="isShowComment"
+        :show-close="false"
+        :title="`${title} - 评论详情`"
+        direction="btt"
+        size="85%"
+        style="background-color:#F3F4FB;">
+      <div class="sticky top-0" style="background-color:#F3F4FB; min-height: 20px; z-index: 2"></div>
+      <div class="px-5">
+        <!-- Title Card -->
+        <el-card body-class="flex justify-between items-center gap-5" class="border-none sticky top-5 z-10">
+          <div class="flex">
+            <el-image :src="`https://d1ge0kk1l5kms0.cloudfront.net/images/I/${rowData.img}.jpg`" class="mr-3"
+                      fit="fill"
+                      lazy style="min-width: 78px; height: 78px;">
+              <template #error>
+                <div class="flex justify-center items-center h-full w-full text-2xl"
+                     style="background:var(--el-fill-color-light)">
+                  <el-icon>
+                    <icon-picture />
+                  </el-icon>
+                </div>
+              </template>
+            </el-image>
+            <div>
+              <el-link :href="rowData.url"
+                       :underline="false"
+                       style="font-size: 18px;"
+                       type="primary">
+                <span class="line-clamp-2 text-ellipsis whitespace-normal">{{ rowData.title || '--' }}</span>
+              </el-link>
+              <div class="flex items-center">
+                <div class="font-semibold italic">{{ rowData.asin }}</div>
+                <VerticalDivider />
+                <el-icon class="ml-2 cursor-pointer" @click="handleCopy(rowData.asin)">
+                  <DocumentCopy />
+                </el-icon>
+              </div>
+            </div>
+          </div>
+          <!--<el-button :icon="Back" plain round type="info" @click="handleBack">返 回</el-button>-->
+        </el-card>
+        <!-- Chart -->
+        <!--<el-row :gutter="20" class="mt-5" style="z-index: 1">-->
+        <!--  <el-col :span="12">-->
+        <!--    <NegativeLabel />-->
+        <!--  </el-col>-->
+        <!--  <el-col :span="12">-->
+        <!--    <NegativeClassification />-->
+        <!--  </el-col>-->
+        <!--</el-row>-->
+        <!-- Chart -->
+        <div class="mt-5">
+          <AverageMonthly :asin="rowData.asin" />
+        </div>
+      </div>
+    </el-drawer>
+
+  </div>
+
+</template>
+
+<style scoped>
+.drawer-container :deep(.el-drawer__header) {
+  border-bottom: none;
+  font-weight: 500;
+}
+
+.drawer-container :deep(.el-drawer__title) {
+  font-size: 18px;
+}
+</style>

+ 88 - 80
src/views/product-manage/competitor-monitor/component/DataTable.vue

@@ -19,6 +19,8 @@ import EditDrawer from './EditDrawer.vue';
 import CreateDialog from '/src/views/product-manage/competitor-monitor/component/CreateDialog.vue';
 import * as api from '../api';
 import { downloadFile } from '/@/utils/service';
+import CommentDetail from '/@/views/product-manage/comment-detail/index.vue';
+import HistoricalDetail from '/@/views/product-manage/historical-detail/index.vue';
 
 
 interface Parameter {
@@ -50,7 +52,7 @@ const gridOptions: any = reactive({
   currentRowHighLight: true,
   height: '100%',
   customConfig: {
-    storage: true,
+    storage: true
   },
   toolbarConfig: {
     size: 'large',
@@ -84,12 +86,13 @@ const checkedList = ref<Set<number>>(new Set());
 
 const editOpen = ref(false);
 const createOpen = ref(false);
-const rowData = ref({});
-
-const dialogVisible = ref(false);
+const rowData = ref<any>({});
 
 const templateType = ref('monitor');
 
+const isShowComment = ref(false);
+const isShowHistory = ref(false);
+
 onMounted(() => {
   fetchList();
 });
@@ -124,35 +127,35 @@ function handleRefresh() {
 }
 
 async function handleDownload() {
-    gridOptions.loading = true;
-    try {
-      const query = {
-				country_code: queryParameter?.country,
-				goods__brand: queryParameter?.brand,
-				goods__tag: queryParameter?.group,
-				status: queryParameter?.status,
-				shop_id: queryParameter?.shop,
-				asin: queryParameter?.asin,
-				goods__sku: queryParameter?.sku,
-				platform_number: queryParameter?.platformId,
-				goods__all_ratings: queryParameter?.scoreNumber,
-				goods__all_reviews: queryParameter?.commentNumber,
-				goods__all_score: queryParameter?.displayScore
-      };
-      const response = await api.exportData(query);
-      const url = window.URL.createObjectURL(new Blob([ response.data ]));
-      const link = document.createElement('a');
-      link.href = url;
-      link.setAttribute('download', '竞品监控数据.xlsx');
-      document.body.appendChild(link);
-      link.click();
-      ElMessage.success('数据导出成功!');
-    } catch (error) {
-      ElMessage.error('数据导出失败,请重试!');
-      console.error(error);
-    } finally {
-      gridOptions.loading = false; // 结束加载状态
-    }
+  gridOptions.loading = true;
+  try {
+    const query = {
+      country_code: queryParameter?.country,
+      goods__brand: queryParameter?.brand,
+      goods__tag: queryParameter?.group,
+      status: queryParameter?.status,
+      shop_id: queryParameter?.shop,
+      asin: queryParameter?.asin,
+      goods__sku: queryParameter?.sku,
+      platform_number: queryParameter?.platformId,
+      goods__all_ratings: queryParameter?.scoreNumber,
+      goods__all_reviews: queryParameter?.commentNumber,
+      goods__all_score: queryParameter?.displayScore
+    };
+    const response = await api.exportData(query);
+    const url = window.URL.createObjectURL(new Blob([ response.data ]));
+    const link = document.createElement('a');
+    link.href = url;
+    link.setAttribute('download', '竞品监控数据.xlsx');
+    document.body.appendChild(link);
+    link.click();
+    ElMessage.success('数据导出成功!');
+  } catch (error) {
+    ElMessage.error('数据导出失败,请重试!');
+    console.error(error);
+  } finally {
+    gridOptions.loading = false; // 结束加载状态
+  }
 }
 
 async function batchDelete() {
@@ -204,28 +207,39 @@ function handleCreate() {
   createOpen.value = true;
 }
 
+function showComment(row: any) 
+{
+  isShowComment.value = true;
+  rowData.value = row;
+}
+
+function showHistory(row: any) {
+  isShowHistory.value = true;
+  rowData.value = row;
+}
+
 function downloadTemplate() {
-	const url = '/api/choice/competitor_monitor/import_data/';
-	const fileName = '竞品监控模板.xlsx';
-
-	if (url) {
-		downloadFile({
-			url,
-			method: 'GET',
-			filename: fileName,
-		});
-	} else {
-		console.error('未知的模板类型:', templateType.value);
-	}
+  const url = '/api/choice/competitor_monitor/import_data/';
+  const fileName = '竞品监控模板.xlsx';
+
+  if (url) {
+    downloadFile({
+      url,
+      method: 'GET',
+      filename: fileName
+    });
+  } else {
+    console.error('未知的模板类型:', templateType.value);
+  }
 }
 
 const gridEvents = {
-  custom ({ type }: any) {
+  custom({ type }: any) {
     if (type == 'confirm') {
       fetchList();
     }
   }
-}
+};
 
 defineExpose({ fetchList });
 
@@ -251,11 +265,7 @@ defineExpose({ fetchList });
           </template>
           <template #actions="{ confirm, cancel }">
             <el-button size="small" @click="cancel">No!</el-button>
-            <el-button
-                size="small"
-                type="danger"
-                @click="confirm"
-            >
+            <el-button size="small" type="danger" @click="confirm">
               Yes?
             </el-button>
           </template>
@@ -267,8 +277,7 @@ defineExpose({ fetchList });
           <el-select v-model="templateType" placeholder="Select" style="width: 190px">
             <template #prefix>
               <div class="flex items-center">
-                <el-button size="small" text type="success"
-                           style="margin-left: -7px; font-size: 14px; border-radius: 29px;"
+                <el-button size="small" style="margin-left: -7px; font-size: 14px; border-radius: 29px;" text type="success"
                            @click.stop="downloadTemplate">下载
                 </el-button>
                 <VerticalDivider style="margin-left: 7px" />
@@ -287,31 +296,27 @@ defineExpose({ fetchList });
           <Refresh />
         </el-icon>
       </el-button>
-			<el-popconfirm
-				width="220"
-				:icon="InfoFilled"
-				icon-color="#626AEF"
-				title="是否确认导出当前时间内所有数据项?"
-				@confirm="handleDownload"
-			>
-				<template #reference>
-					<el-button circle class="mr-3 toolbar-btn">
-						<el-icon>
-							<Download />
-						</el-icon>
-					</el-button>
-				</template>
-				<template #actions="{ confirm, cancel }">
-					<el-button size="small" @click="cancel">No!</el-button>
-					<el-button
-						type="danger"
-						size="small"
-						@click="confirm"
-					>
-						Yes?
-					</el-button>
-				</template>
-			</el-popconfirm>
+      <el-popconfirm
+          :icon="InfoFilled"
+          icon-color="#626AEF"
+          title="是否确认导出当前时间内所有数据项?"
+          width="220"
+          @confirm="handleDownload"
+      >
+        <template #reference>
+          <el-button circle class="mr-3 toolbar-btn">
+            <el-icon>
+              <Download />
+            </el-icon>
+          </el-button>
+        </template>
+        <template #actions="{ confirm, cancel }">
+          <el-button size="small" @click="cancel">No!</el-button>
+          <el-button size="small" type="danger" @click="confirm">
+            Yes?
+          </el-button>
+        </template>
+      </el-popconfirm>
     </template>
     <template #top>
       <div class="mb-2"></div>
@@ -327,11 +332,14 @@ defineExpose({ fetchList });
     </template>
     <!-- 自定义列插槽 -->
     <template v-for="col in CompetitorMonitorColumns" #[`${col.field}`]="{ row }">
-      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete" />
+      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete"
+                     @show-comment="showComment" @show-history="showHistory" />
     </template>
   </vxe-grid>
   <EditDrawer v-if="editOpen" v-model="editOpen" :row-data="rowData" @refresh="handleRefresh" />
   <CreateDialog v-if="createOpen" v-model="createOpen" @refresh="fetchList" />
+  <CommentDetail v-if="isShowComment" v-model="isShowComment" :row-data="rowData.goods" title="竞品监控" />
+  <HistoricalDetail v-if="isShowHistory" v-model="isShowHistory" :row-data="rowData.goods" title="竞品监控" />
 </template>
 
 <style scoped>

+ 12 - 8
src/views/product-manage/competitor-monitor/component/DataTableSlot.vue

@@ -9,7 +9,7 @@ import { useCountryInfoStore } from '/@/stores/countryInfo';
 import { Delete, InfoFilled, Operation, Tickets, Timer } from '@element-plus/icons-vue';
 import { getTagType } from '/@/utils/useTagColor';
 import PermissionButton from '/@/components/PermissionButton/index.vue';
-import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import ProductInfo from '/@/views/product-manage/component/ProductInfo.vue';
 import ProgressBar from '/@/views/product-manage/product-monitor/component/ProgressBar.vue';
 
 
@@ -19,7 +19,7 @@ const props = defineProps<{
 }>();
 const { row, field } = props;
 
-const emit = defineEmits([ 'edit-row', 'handle-delete' ]);
+const emit: any = defineEmits([ 'edit-row', 'handle-delete', 'show-comment', 'show-history' ]);
 
 const countryInfoStore = useCountryInfoStore();
 const country = countryInfoStore.Countries.find(c => c.code == row.country_code);
@@ -55,6 +55,10 @@ function starsPercent(goods: any) {
   }
   return ret;
 }
+
+function showDetail(detail: any) {
+  emit(`${detail}`, row);
+}
 </script>
 
 <template>
@@ -167,17 +171,17 @@ function starsPercent(goods: any) {
       <div class="flex justify-center gap-2 mb-2">
         <el-tooltip :enterable="false" :show-arrow="false" content="评论详情" hide-after="0"
                     placement="top" popper-class="custom-btn-tooltip">
-          <PermissionButton circle plain type="success">
+          <PermissionButton circle plain type="success" @click="showDetail('show-comment')">
             <el-icon>
-              <Tickets/>
+              <Tickets />
             </el-icon>
           </PermissionButton>
         </el-tooltip>
         <el-tooltip :enterable="false" :show-arrow="false" content="历史详情" hide-after="0"
                     placement="top" popper-class="custom-btn-tooltip">
-          <PermissionButton circle plain type="success">
+          <PermissionButton :color="'#6466F1'" circle plain type="success" @click="showDetail('show-history')">
             <el-icon>
-              <Timer/>
+              <Timer />
             </el-icon>
           </PermissionButton>
         </el-tooltip>
@@ -185,7 +189,7 @@ function starsPercent(goods: any) {
       <div class="flex justify-center gap-2">
         <PermissionButton circle plain type="warning" @click="handleEdit">
           <el-icon>
-            <Operation/>
+            <Operation />
           </el-icon>
         </PermissionButton>
         <el-popconfirm
@@ -198,7 +202,7 @@ function starsPercent(goods: any) {
           <template #reference>
             <PermissionButton circle plain type="danger">
               <el-icon>
-                <Delete/>
+                <Delete />
               </el-icon>
             </PermissionButton>
           </template>

+ 2 - 1
src/views/product-manage/product-list/component/ProductInfo.vue → src/views/product-manage/component/ProductInfo.vue

@@ -33,6 +33,7 @@ const props = defineProps({
             :src="`https://d1ge0kk1l5kms0.cloudfront.net/images/I/${item.img}.jpg`"
             :style="`width: ${imgWidth}px; margin-right: 5px;`"
             fit="fill"
+            lazy
         />
         <template #content>
           <el-image
@@ -42,7 +43,7 @@ const props = defineProps({
         </template>
       </el-tooltip>
     </div>
-    <el-image v-else :style="`width: ${imgWidth}px; margin-right: 5px;`">
+    <el-image v-else :style="`width: ${imgWidth}px; margin-right: 5px;`" lazy>
       <div slot="error" class="image-slot">
         <i class="el-icon-picture-outline"></i>
       </div>

+ 68 - 0
src/views/product-manage/historical-detail/index.vue

@@ -0,0 +1,68 @@
+<script lang="ts" setup>
+/**
+ * @Name: index.vue
+ * @Description: 历史详情
+ * @Author: Cheney
+ */
+
+import { useTableHeight } from '/@/utils/useCustomHeight';
+
+
+const isShowHistory = defineModel({ default: false });
+
+const props = defineProps({
+  rowData: <any>Object,
+  title: String
+});
+const { rowData, title } = props;
+console.log("(index.vue: 15)=> rowData", rowData);
+
+
+const heightObj = { topBar: 50, cardMargin: 8, cardPadding: 20 };
+const { tableHeight } = useTableHeight(heightObj);
+
+
+</script>
+
+<template>
+  <div class="drawer-container">
+    <el-drawer
+        ref="editDrawer"
+        v-model="isShowHistory"
+        :show-close="false"
+        direction="btt"
+        size="85%"
+        style="background-color:#F3F4FB;"
+        :title="`${title} - 历史详情`">
+      <div class="sticky top-0" style="background-color:#F3F4FB; min-height: 20px; z-index: 2"></div>
+      <div class="px-5">
+        <el-card>12341</el-card>
+        <el-card :body-style="{ height: tableHeight + 'px' }">
+          <div class="h-full overflow-hidden">
+            <vxe-table height="100%">
+              <vxe-column type="seq"></vxe-column>
+              <vxe-column type="seq"></vxe-column>
+              <vxe-column type="seq"></vxe-column>
+              <vxe-column type="seq"></vxe-column>
+              <vxe-column type="seq"></vxe-column>
+            </vxe-table>
+          </div>
+        </el-card>
+      </div>
+      
+    </el-drawer>
+
+  </div>
+
+</template>
+
+<style scoped>
+.drawer-container :deep(.el-drawer__header) {
+  border-bottom: none;
+  font-weight: 500;
+}
+
+.drawer-container :deep(.el-drawer__title) {
+  font-size: 18px;
+}
+</style>

+ 1 - 1
src/views/product-manage/product-list/component/DataTableSlot.vue

@@ -9,7 +9,7 @@ import { useCountryInfoStore } from '/@/stores/countryInfo';
 import { Message, Operation } from '@element-plus/icons-vue';
 import { getTagType } from '/@/utils/useTagColor';
 import PermissionButton from '/@/components/PermissionButton/index.vue';
-import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import ProductInfo from '/@/views/product-manage/component/ProductInfo.vue';
 
 
 const props = defineProps<{

+ 1 - 1
src/views/product-manage/product-list/component/EditDrawer.vue

@@ -27,7 +27,7 @@ const { rowData } = props;
 const emit = defineEmits([ 'refresh' ]);
 
 onBeforeMount(() => {
-  console.log('rowData=> ', rowData);
+  // console.log('rowData=> ', rowData);
 });
 
 interface RuleForm {

+ 3 - 3
src/views/product-manage/product-list/component/NoticeDialog.vue

@@ -105,7 +105,7 @@ function cancelDialog() {
     >
       <el-row class="mb-2">
         <el-col>
-          <span class="mr-2">人员选择</span>
+          <span class="mr-2 font-medium">人员选择</span>
           <el-select v-model="staffSelect" filterable placeholder="输入搜索" style="width: 200px;"
                      @change="addStaffChange">
             <el-option
@@ -121,9 +121,9 @@ function cancelDialog() {
       <el-row :gutter="20" class="mb-4">
         <el-col :span="2">
         </el-col>
-        <el-col :span="20" class="ml-2.5">
+        <el-col :span="20" class="ml-4" style="color: #909399">
           <i class="bi bi-info-circle"></i>
-          <span class="ml-1" style="color: #909399">仅可添加已绑定邮箱的用户</span>
+          <span class="ml-1">仅可添加已绑定邮箱的用户</span>
         </el-col>
       </el-row>
       <div class="flex flex-wrap gap-1.5 min-h-6">

+ 1 - 1
src/views/product-manage/product-list/index.vue

@@ -11,8 +11,8 @@ import { useTableHeight } from '/@/utils/useTableHeight';
 import DataTable from './component/DataTable.vue';
 import { DictionaryStore } from '/@/stores/dictionary';
 import { useResponse } from '/@/utils/useResponse';
-import * as api from './api';
 import { useTemplateRef } from 'vue';
+import * as api from './api';
 
 
 const { data: staticData } = DictionaryStore();

+ 91 - 73
src/views/product-manage/product-monitor/component/DataTable.vue

@@ -11,14 +11,16 @@ import { usePagination } from '/@/utils/usePagination';
 import { useTableData } from '/@/utils/useTableData';
 import { useResponse } from '/@/utils/useResponse';
 import { ProductMonitorColumns } from '/@/views/product-manage/Columns';
+import { downloadFile } from '/@/utils/service';
 import DataTableSlot from '/@/views/product-manage/product-monitor/component/DataTableSlot.vue';
 import PermissionButton from '/src/components/PermissionButton/index.vue';
 import VerticalDivider from '/src/components/VerticalDivider/index.vue';
 import ImportButton from '/src/components/ImportButton/index.vue';
 import EditDrawer from './EditDrawer.vue';
 import CreateDialog from '/src/views/product-manage/product-monitor/component/CreateDialog.vue';
+import CommentDetail from '/src/views/product-manage/comment-detail/index.vue';
 import * as api from '../api';
-import { downloadFile } from '/@/utils/service';
+import HistoricalDetail from '/@/views/product-manage/historical-detail/index.vue';
 
 
 interface Parameter {
@@ -50,7 +52,7 @@ const gridOptions: any = reactive({
   currentRowHighLight: true,
   height: '100%',
   customConfig: {
-    storage: true,
+    storage: true
   },
   toolbarConfig: {
     size: 'large',
@@ -84,10 +86,13 @@ const checkedList = ref<Set<number>>(new Set());
 
 const editOpen = ref(false);
 const createOpen = ref(false);
-const rowData = ref({});
+const rowData = ref<any>({});
 
 const templateType = ref('monitor');
 
+const isShowComment = ref(false);
+const isShowHistory = ref(false);
+
 onMounted(() => {
   fetchList();
 });
@@ -120,35 +125,35 @@ function handleRefresh() {
 }
 
 async function handleDownload() {
-		gridOptions.loading = true;
-		try {
-			const query = {
-				country_code: queryParameter?.country,
-				goods__brand: queryParameter?.brand,
-				goods__tag: queryParameter?.group,
-				status: queryParameter?.status,
-				shop_id: queryParameter?.shop,
-				asin: queryParameter?.asin,
-				goods__sku: queryParameter?.sku,
-				platform_number: queryParameter?.platformId,
-				goods__all_ratings: queryParameter?.scoreNumber,
-				goods__all_reviews: queryParameter?.commentNumber,
-				goods__all_score: queryParameter?.displayScore
-			};
-			const response = await api.exportData(query);
-			const url = window.URL.createObjectURL(new Blob([response.data]));
-			const link = document.createElement('a');
-			link.href = url;
-			link.setAttribute('download', '商品监控数据.xlsx');
-			document.body.appendChild(link);
-			link.click();
-			ElMessage.success('数据导出成功!');
-		} catch (error) {
-			ElMessage.error('数据导出失败,请重试!');
-			console.error(error);
-		} finally {
-			gridOptions.loading = false; // 结束加载状态
-		}
+  gridOptions.loading = true;
+  try {
+    const query = {
+      country_code: queryParameter?.country,
+      goods__brand: queryParameter?.brand,
+      goods__tag: queryParameter?.group,
+      status: queryParameter?.status,
+      shop_id: queryParameter?.shop,
+      asin: queryParameter?.asin,
+      goods__sku: queryParameter?.sku,
+      platform_number: queryParameter?.platformId,
+      goods__all_ratings: queryParameter?.scoreNumber,
+      goods__all_reviews: queryParameter?.commentNumber,
+      goods__all_score: queryParameter?.displayScore
+    };
+    const response = await api.exportData(query);
+    const url = window.URL.createObjectURL(new Blob([ response.data ]));
+    const link = document.createElement('a');
+    link.href = url;
+    link.setAttribute('download', '商品监控数据.xlsx');
+    document.body.appendChild(link);
+    link.click();
+    ElMessage.success('数据导出成功!');
+  } catch (error) {
+    ElMessage.error('数据导出失败,请重试!');
+    console.error(error);
+  } finally {
+    gridOptions.loading = false; // 结束加载状态
+  }
 }
 
 async function batchDelete() {
@@ -200,28 +205,38 @@ function handleCreate() {
   createOpen.value = true;
 }
 
+function showComment(row: any) {
+  isShowComment.value = true;
+  rowData.value = row;
+}
+
+function showHistory(row: any) {
+  isShowHistory.value = true;
+  rowData.value = row;
+}
+
 function downloadTemplate() {
-	const url = '/api/choice/reviews_monitor/import_data/';
-	const fileName = '商品监控模板.xlsx';
+  const url = '/api/choice/reviews_monitor/import_data/';
+  const fileName = '商品监控模板.xlsx';
 
-	if (url) {
-		downloadFile({
-			url,
-			method: 'GET',
-			filename: fileName,
-		});
-	} else {
-		console.error('未知的模板类型:', templateType.value);
-	}
+  if (url) {
+    downloadFile({
+      url,
+      method: 'GET',
+      filename: fileName
+    });
+  } else {
+    console.error('未知的模板类型:', templateType.value);
+  }
 }
 
 const gridEvents = {
-  custom ({ type }: any) {
+  custom({ type }: any) {
     if (type == 'confirm') {
       fetchList();
     }
   }
-}
+};
 
 defineExpose({ fetchList });
 
@@ -257,8 +272,8 @@ defineExpose({ fetchList });
           <el-select v-model="templateType" style="width: 190px">
             <template #prefix>
               <div class="flex items-center">
-                <el-button size="small" type="success" text
-                           style="margin-left: -7px; font-size: 14px; border-radius: 29px;"
+                <el-button size="small" style="margin-left: -7px; font-size: 14px; border-radius: 29px;" text
+                           type="success"
                            @click.stop="downloadTemplate">
                   下载
                 </el-button>
@@ -278,31 +293,31 @@ defineExpose({ fetchList });
           <Refresh />
         </el-icon>
       </el-button>
-			<el-popconfirm
-				width="220"
-				:icon="InfoFilled"
-				icon-color="#626AEF"
-				title="是否确认导出当前时间内所有数据项?"
-				@confirm="handleDownload"
-			>
-				<template #reference>
-					<el-button circle class="mr-3 toolbar-btn">
-						<el-icon>
-							<Download />
-						</el-icon>
-					</el-button>
-				</template>
-				<template #actions="{ confirm, cancel }">
-					<el-button size="small" @click="cancel">No!</el-button>
-					<el-button
-						type="danger"
-						size="small"
-						@click="confirm"
-					>
-						Yes?
-					</el-button>
-				</template>
-			</el-popconfirm>
+      <el-popconfirm
+          :icon="InfoFilled"
+          icon-color="#626AEF"
+          title="是否确认导出当前时间内所有数据项?"
+          width="220"
+          @confirm="handleDownload"
+      >
+        <template #reference>
+          <el-button circle class="mr-3 toolbar-btn">
+            <el-icon>
+              <Download />
+            </el-icon>
+          </el-button>
+        </template>
+        <template #actions="{ confirm, cancel }">
+          <el-button size="small" @click="cancel">No!</el-button>
+          <el-button
+              size="small"
+              type="danger"
+              @click="confirm"
+          >
+            Yes?
+          </el-button>
+        </template>
+      </el-popconfirm>
     </template>
     <template #top>
       <div class="mb-2"></div>
@@ -318,11 +333,14 @@ defineExpose({ fetchList });
     </template>
     <!-- 自定义列插槽 -->
     <template v-for="col in ProductMonitorColumns" #[`${col.field}`]="{ row }">
-      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete" />
+      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete"
+                     @show-comment="showComment" @show-history="showHistory" />
     </template>
   </vxe-grid>
   <EditDrawer v-if="editOpen" v-model="editOpen" :row-data="rowData" @refresh="handleRefresh" />
   <CreateDialog v-if="createOpen" v-model="createOpen" @refresh="fetchList" />
+  <CommentDetail v-if="isShowComment" v-model="isShowComment" :row-data="rowData.goods" title="商品监控" />
+  <HistoricalDetail v-if="isShowHistory" v-model="isShowHistory" :row-data="rowData.goods" title="商品监控"  />
 </template>
 
 <style scoped>

+ 16 - 5
src/views/product-manage/product-monitor/component/DataTableSlot.vue

@@ -9,7 +9,7 @@ import { useCountryInfoStore } from '/@/stores/countryInfo';
 import { Delete, InfoFilled, Operation, Tickets, Timer } from '@element-plus/icons-vue';
 import { getTagType } from '/@/utils/useTagColor';
 import PermissionButton from '/@/components/PermissionButton/index.vue';
-import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import ProductInfo from '/@/views/product-manage/component/ProductInfo.vue';
 import ProgressBar from '/@/views/product-manage/product-monitor/component/ProgressBar.vue';
 
 
@@ -19,7 +19,7 @@ const props = defineProps<{
 }>();
 const { row, field } = props;
 
-const emit = defineEmits([ 'edit-row', 'handle-delete' ]);
+const emit: any = defineEmits([ 'edit-row', 'handle-delete', 'show-comment', 'show-history' ]);
 
 const countryInfoStore = useCountryInfoStore();
 const country = countryInfoStore.Countries.find(c => c.code == row.country_code);
@@ -35,6 +35,11 @@ function handleEdit() {
 function onConfirm() {
   emit('handle-delete', row);
 }
+
+function showDetail(detail: any) {
+  emit(`${detail}`, row);
+}
+
 </script>
 
 <template>
@@ -134,15 +139,15 @@ function onConfirm() {
       <div class="flex justify-center gap-2 mb-2">
         <el-tooltip :enterable="false" :show-arrow="false" content="评论详情" hide-after="0"
                     placement="top" popper-class="custom-btn-tooltip">
-          <PermissionButton circle plain type="success">
+          <PermissionButton circle plain type="success" @click="showDetail('show-comment')">
             <el-icon>
               <Tickets/>
             </el-icon>
           </PermissionButton>
         </el-tooltip>
         <el-tooltip :enterable="false" :show-arrow="false" content="历史详情" hide-after="0"
-                    placement="top" popper-class="custom-btn-tooltip">
-          <PermissionButton circle plain type="success">
+                    placement="top" popper-class="custom-btn-tooltip-2">
+          <PermissionButton :color="'#6466F1'" circle plain type="success" @click="showDetail('show-history')">
             <el-icon>
               <Timer/>
             </el-icon>
@@ -202,4 +207,10 @@ function onConfirm() {
   border: 1px solid #67C23A !important;
   font-size: 14px;
 }
+.custom-btn-tooltip-2 {
+  background-color: #F0F0FE !important;
+  color: #606266 !important;
+  border: 1px solid #6466F1 !important;
+  font-size: 14px;
+}
 </style>

+ 3 - 0
vite.config.ts

@@ -79,6 +79,9 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
           'element-plus/es/locale/lang/zh-cn', 
           'element-plus/es/locale/lang/en', 
           'element-plus/es/locale/lang/zh-tw', 
+          'element-plus/es',
+          'element-plus/es/components/base/style/css',
+          'element-plus/es/components/message/style/css',
           '@fast-crud/fast-crud'
       ]
     },