优化界面 #7

Merged
SheYuWu03 merged 1 commits from liqiushi_branch into master 2024-07-09 01:24:46 +08:00
16 changed files with 1189 additions and 2015 deletions

468
package-lock.json generated
View File

@ -9,8 +9,6 @@
"version": "0.1.0",
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@headlessui/vue": "^1.7.22",
"@heroicons/vue": "^2.1.4",
"@vuepic/vue-datepicker": "^8.8.0",
"axios": "^1.7.2",
"core-js": "^3.8.3",
@ -38,14 +36,10 @@
"@vue/eslint-config-typescript": "^9.1.0",
"@vue/test-utils": "^2.0.0-0",
"@vue/vue3-jest": "^27.0.0-alpha.1",
"autoprefixer": "^10.4.19",
"babel-jest": "^27.0.6",
"daisyui": "^4.12.10",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"jest": "^27.0.5",
"postcss": "^8.4.39",
"tailwindcss": "^3.4.4",
"ts-jest": "^27.0.4",
"typescript": "~4.5.5"
}
@ -64,19 +58,6 @@
"node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21"
}
},
"node_modules/@alloc/quick-lru": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
@ -1895,8 +1876,9 @@
},
"node_modules/@element-plus/icons-vue": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"license": "MIT",
"peerDependencies": {
"vue": "^3.2.0"
}
@ -2018,30 +2000,6 @@
"@hapi/hoek": "^9.0.0"
}
},
"node_modules/@headlessui/vue": {
"version": "1.7.22",
"resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.22.tgz",
"integrity": "sha512-Hoffjoolq1rY+LOfJ+B/OvkhuBXXBFgd8oBlN+l1TApma2dB0En0ucFZrwQtb33SmcCqd32EQd0y07oziXWNYg==",
"license": "MIT",
"dependencies": {
"@tanstack/vue-virtual": "^3.0.0-beta.60"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/@heroicons/vue": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@heroicons/vue/-/vue-2.1.4.tgz",
"integrity": "sha512-wykVSZ/fqEG49lIeHgFGT9TCvBw9THuRTtA/sPp7FVk3iBob/HcmitMcLDwtXOW82TXb38HeLRl1/pcElPeSdg==",
"license": "MIT",
"peerDependencies": {
"vue": ">= 3"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
@ -3078,32 +3036,6 @@
"integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
"dev": true
},
"node_modules/@tanstack/virtual-core": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.8.1.tgz",
"integrity": "sha512-uNtAwenT276M9QYCjTBoHZ8X3MUeCRoGK59zPi92hMIxdfS9AyHjkDWJ94WroDxnv48UE+hIeo21BU84jKc8aQ==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/vue-virtual": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.8.1.tgz",
"integrity": "sha512-uhty1LzUbbcVc5zdMMSUjUt/ECTlMCtK49Ww7dH2m4lNNLGYwkj5SbfrAD8uCZxV1VeV7DRMXqhwUTELyR5rrA==",
"license": "MIT",
"dependencies": {
"@tanstack/virtual-core": "3.8.1"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"vue": "^2.7.0 || ^3.0.0"
}
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-1.1.2.tgz",
@ -5192,13 +5124,6 @@
}
]
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"dev": true,
"license": "MIT"
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz",
@ -5257,7 +5182,7 @@
},
"node_modules/autoprefixer": {
"version": "10.4.19",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
"resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.19.tgz",
"integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==",
"dev": true,
"funding": [
@ -5274,7 +5199,6 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.23.0",
"caniuse-lite": "^1.0.30001599",
@ -5863,16 +5787,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/caniuse-api/-/caniuse-api-3.0.0.tgz",
@ -6679,17 +6593,6 @@
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/css-tree": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz",
@ -6844,36 +6747,6 @@
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/culori": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
"integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/daisyui": {
"version": "4.12.10",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.10.tgz",
"integrity": "sha512-jp1RAuzbHhGdXmn957Z2XsTZStXGHzFfF0FgIOZj3Wv9sH7OZgLfXTRZNfKVYxltGUOBsG1kbWAdF5SrqjebvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"css-selector-tokenizer": "^0.8",
"culori": "^3",
"picocolors": "^1",
"postcss-js": "^4"
},
"engines": {
"node": ">=16.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/daisyui"
}
},
"node_modules/data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-2.0.0.tgz",
@ -7179,13 +7052,6 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true
},
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/diff-sequences": {
"version": "27.5.1",
"resolved": "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-27.5.1.tgz",
@ -7207,13 +7073,6 @@
"node": ">=8"
}
},
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true,
"license": "MIT"
},
"node_modules/dns-packet": {
"version": "5.6.1",
"resolved": "https://registry.npmmirror.com/dns-packet/-/dns-packet-5.6.1.tgz",
@ -8471,13 +8330,6 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true,
"license": "MIT"
},
"node_modules/fastq": {
"version": "1.17.1",
"resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.17.1.tgz",
@ -12328,16 +12180,6 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/jiti": {
"version": "1.21.6",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
}
},
"node_modules/joi": {
"version": "17.13.1",
"resolved": "https://registry.npmmirror.com/joi/-/joi-17.13.1.tgz",
@ -13600,16 +13442,6 @@
"node": ">=0.10.0"
}
},
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz",
@ -13891,13 +13723,6 @@
"node": ">=6"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz",
@ -14077,16 +13902,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.6.tgz",
@ -14132,9 +13947,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.39",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
"integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
"version": "8.4.38",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"funding": [
{
"type": "opencollective",
@ -14149,10 +13964,9 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
@ -14254,106 +14068,6 @@
"postcss": "^8.2.15"
}
},
"node_modules/postcss-import": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
"resolve": "^1.1.7"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"postcss": "^8.0.0"
}
},
"node_modules/postcss-js": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"camelcase-css": "^2.0.1"
},
"engines": {
"node": "^12 || ^14 || >= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.4.21"
}
},
"node_modules/postcss-load-config": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"lilconfig": "^3.0.0",
"yaml": "^2.3.4"
},
"engines": {
"node": ">= 14"
},
"peerDependencies": {
"postcss": ">=8.0.9",
"ts-node": ">=9.0.0"
},
"peerDependenciesMeta": {
"postcss": {
"optional": true
},
"ts-node": {
"optional": true
}
}
},
"node_modules/postcss-load-config/node_modules/lilconfig": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/postcss-load-config/node_modules/yaml": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
"integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
"dev": true,
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/postcss-loader": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/postcss-loader/-/postcss-loader-6.2.1.tgz",
@ -14561,26 +14275,6 @@
"postcss": "^8.1.0"
}
},
"node_modules/postcss-nested": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
"integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.0.11"
},
"engines": {
"node": ">=12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/postcss-normalize-charset": {
"version": "5.1.0",
"resolved": "https://registry.npmmirror.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
@ -15085,16 +14779,6 @@
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"pify": "^2.3.0"
}
},
"node_modules/read-pkg": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz",
@ -16127,99 +15811,6 @@
"postcss": "^8.2.15"
}
},
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
"glob": "^10.3.10",
"lines-and-columns": "^1.1.6",
"mz": "^2.7.0",
"pirates": "^4.0.1",
"ts-interface-checker": "^0.1.9"
},
"bin": {
"sucrase": "bin/sucrase",
"sucrase-node": "bin/sucrase-node"
},
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/sucrase/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/sucrase/node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/sucrase/node_modules/glob": {
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz",
"integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==",
"dev": true,
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/sucrase/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/sucrase/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
@ -16358,44 +15949,6 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/tailwindcss": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz",
"integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
"chokidar": "^3.5.3",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.3.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.21.0",
"lilconfig": "^2.1.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
"picocolors": "^1.0.0",
"postcss": "^8.4.23",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
"postcss-load-config": "^4.0.1",
"postcss-nested": "^6.0.1",
"postcss-selector-parser": "^6.0.11",
"resolve": "^1.22.2",
"sucrase": "^3.32.0"
},
"bin": {
"tailwind": "lib/cli.js",
"tailwindcss": "lib/cli.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tapable": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/tapable/-/tapable-1.1.3.tgz",
@ -16686,13 +16239,6 @@
"node": ">=8"
}
},
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/ts-jest": {
"version": "27.1.5",
"resolved": "https://registry.npmmirror.com/ts-jest/-/ts-jest-27.1.5.tgz",

View File

@ -6,13 +6,10 @@
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint",
"build:css": "npx tailwindcss -i ./src/assets/css/input.css -o ./src/assets/css/output.css --watch"
"lint": "vue-cli-service lint"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@headlessui/vue": "^1.7.22",
"@heroicons/vue": "^2.1.4",
"@vuepic/vue-datepicker": "^8.8.0",
"axios": "^1.7.2",
"core-js": "^3.8.3",
@ -40,14 +37,10 @@
"@vue/eslint-config-typescript": "^9.1.0",
"@vue/test-utils": "^2.0.0-0",
"@vue/vue3-jest": "^27.0.0-alpha.1",
"autoprefixer": "^10.4.19",
"babel-jest": "^27.0.6",
"daisyui": "^4.12.10",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"jest": "^27.0.5",
"postcss": "^8.4.39",
"tailwindcss": "^3.4.4",
"ts-jest": "^27.0.4",
"typescript": "~4.5.5"
},

View File

@ -12,25 +12,6 @@ export default {
IndexPage
}
}
const debounce = (fn, delay) => {
let timer
return (...args) => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...args)
}, delay)
}
}
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver{
constructor(callback) {
callback = debounce(callback, 200);
super(callback);
}
}
const siderBarWidth = ref("200px");
const toggleMenu = ()=>{
if(siderBarWidth.value == "200px")

View File

@ -3,7 +3,7 @@
padding: 0;
/* 设置所有对话框的header颜色固定 */
.el-dialog__header{
background-color: #158484;
background-color: #1890ff;
font-size: 28px;
display: flex;
justify-content: center;

View File

@ -1,27 +1,45 @@
<!-- /**用于显示sidebar的页面 */ -->
<template>
<!-- 这一层用来放边栏 -->
<el-container style="height: 100%; border: 0px; background-color: #f5f6fa; width:100%">
<el-header class = "containerSystemName">
<el-container
style="height: 100%; border: 0px; background-color: #f5f6fa; width: 100%"
>
<el-header class="containerSystemName">
<!-- 这里要放两个部件一个是系统名称一个是折叠按钮 -->
<!-- 这里主要调整el-container的布局模式就直接写在这里了 -->
<el-container style = 'padding: 0'>
<el-container class = 'text-systemName'>
<el-text v-show = '!isFold' style="color: white; font-size: 16px;">线索库系统</el-text>
<el-container style="padding: 0">
<el-container class="text-systemName">
<img
src="@/assets/logo.png"
alt=""
style="width: 40px; height: 40px"
/>
<el-text v-show="!isFold" style="color: white; font-size: 16px"
>线索库系统</el-text
>
</el-container>
<el-button class ='btnFold' @click = 'handleFold'><el-icon><Fold /></el-icon></el-button>
<el-button class="btnFold" @click="handleFold"
><el-icon><Fold /></el-icon
></el-button>
</el-container>
</el-header>
<el-menu class = 'containerSelections'
<el-menu
style="border: none; height: 100vh"
text-color="rgba(255,255,255,0.65)"
active-text-color="#ffd04b"
default-active="/Home"
:collapse="isCollapse"
:collapse-transition="false"
class="containerSelections"
router
>
<el-menu-item index="/Home">
<el-icon><HomeFilled /></el-icon>
<span v-show = '!isFold'>首页</span>
<span v-show="!isFold">系统首页</span>
</el-menu-item>
<el-menu-item index="/Delete">
<el-icon><DeleteFilled /></el-icon>
<span v-show = '!isFold'>回收站</span>
<span v-show="!isFold">回收站</span>
</el-menu-item>
<!--
@brief: 用于调试我设计的各种界面相当于一个画板
@ -30,105 +48,112 @@
-->
<el-menu-item index="/test">
<el-icon><View /></el-icon>
<span v-show = '!isFold'>测试专用</span>
<span v-show="!isFold">测试专用</span>
</el-menu-item>
</el-menu>
</el-container>
</template>
<script>
export default{
name:'AsideMenu',
export default {
name: "AsideMenu",
props: {
isCollapse: Boolean
isCollapse: Boolean,
},
data(){
data() {
// :
return {
isFold:false,
}
isFold: false,
};
},
methods:{
methods: {
//
handleFold(){
handleFold() {
this.isFold = !this.isFold;
// indexPage
if(this.isFold)
this.$emit('update:isCollapse',true);
else
this.$emit('update:isCollapse',false);
}
if (this.isFold) this.$emit("update:isCollapse", true);
else this.$emit("update:isCollapse", false);
},
}
},
};
</script>
/**
@brief: CSS设计
@date: 2024年6月20日
@author: myz
*/
/** @brief: CSS设计 @date: 2024年6月20日 @author: myz */
<style scoped>
.containerSystemName{
color:white; /**字体颜色为白色 */
background-color: #158484; /* 容器背景颜色 */
.containerSystemName {
color: white; /**字体颜色为白色 */
background-color: #090470; /* 容器背景颜色 */
display: flex;
justify-content: center; /**水平居中 */
align-items: center; /**竖直居中 */
font-weight: bolder; /** 字体加粗 */
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /*设置字体*/
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; /*设置字体*/
font-size: 14px; /**字体大小 */
height:6%;
height: 8%;
width: 100%;
padding-left:0;
padding-right:3px;
padding-left: 0;
padding-right: 3px;
}
.el-text{
color:white
}
.text-systemName{
background-color: #158484; /* 容器背景颜色 */
.text-systemName {
background-color: #090470; /* 容器背景颜色 */
display: flex;
/**竖直居中 */
align-items: center;
/**水平居中 */
justify-content: center;
height:100%;
padding:0;
height: 100%;
padding: 0;
}
.containerSelections{
color: white;
background-color: #1DAFAF;
height: 94%;
width:100%;
border:0px;
}
.el-menu-item{
color:white;
font-weight: bold;
.containerSelections {
background-color: #000c17;
height: 92%;
width: 100%;
}
/**覆写悬浮,选中等样式 */
:deep .el-menu-item:hover{
background-color: #1ad4c4d4;
color: antiquewhite;
}
:deep .el-menu-item.is-active{
color: #158484;
border: 0px;
}
.btnFold{
/**覆写悬浮,选中等样式 */
.btnFold {
display: flex;
align-items: center;
color: #0E5858;
color: #8f9191;
font-size: 28px;
background-color: transparent;
border: 0;
}
.btnFold:hover{
.btnFold:hover {
background-color: transparent;
color:#1ad4c4d4;
color: #1ad4c4d4;
}
.el-menu--line {
background-color: #000c17 !important;
}
.el-menu--line.el-menu-item {
background-color: #000c17 !important;
padding-left: 49px !important;
}
.el-menu-item:hover {
color: #ffd04b !important;
}
.el-menu-item:hover i {
color: #ffd04b;
}
.el-menu-item.is-active {
background-color: #1890ff !important;
border-radius: 5px;
margin-right: 1px;
margin-left: 1px;
}
.el-menu-item {
font-size: 17px !important;
height: 48px;
line-height: 47px;
margin-right: 1px;
margin-left: 1px;
}
.el-menu-item i {
font-size: 20px !important;
}
</style>

View File

@ -1,42 +1,41 @@
<!-- /***用于显示边栏的页面 */ -->
<template>
<el-container class = 'toolbar' >
<el-text class = "pageName">{{ pageTitle }}</el-text>
<el-container class="toolbar">
<el-text class="pageName">{{ pageTitle }}</el-text>
</el-container>
</template>
<script>
export default {
name: 'HeaderPage',
props:{
name: "HeaderPage",
props: {
pageTitle: String,
icon:String
icon: String,
},
methods:{
toUser(){
console.log('toUser')
methods: {
toUser() {
console.log("toUser");
},
logout(){
console.log('logout')
logout() {
console.log("logout");
},
}
}
},
};
</script>
<style scoped>
.toolbar{
.toolbar {
background-color: white;
color: #6B6363;
color: #6b6363;
display: flex;
height:100%;
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
}
.pageName{
.pageName {
font-size: 24px;
font-weight: bold;
}
</style>

View File

@ -1,15 +1,22 @@
<template>
<el-dialog
title="添加线索"
v-model='dialogVisible'
v-model="dialogVisible"
draggable
align-center=true
align-center="true"
@close="onClose"
>
<el-container>
<el-form label-width="100px">
<el-form-item v-for="(col, index) in addClueCols" :key="index" :label="col.col_name">
<el-input v-model="formData['col_'+col.col_id]" :placeholder="'输入' + col.col_name"></el-input>
<el-form-item
v-for="(col, index) in addClueCols"
:key="index"
:label="col.col_name"
>
<el-input
v-model="formData['col_' + col.col_id]"
:placeholder="'输入' + col.col_name"
></el-input>
</el-form-item>
</el-form>
<el-footer class="dialog-footer">
@ -18,67 +25,65 @@
</el-footer>
</el-container>
</el-dialog>
</template>
<script>
export default {
name:'AddDialog',
name: "AddDialog",
props: {
visible:Boolean,
addClueCols:Array,
id:Number,
tableId:String,
visible: Boolean,
addClueCols: Array,
id: Number,
tableId: String,
},
data() {
return{
formData:{},
dialogVisible:false,
}
return {
formData: {},
dialogVisible: false,
};
},
watch: {
visible(value){
visible(value) {
this.dialogVisible = value;
},
},
methods: {
clickToCloseDialog(){
clickToCloseDialog() {
this.dialogVisible = false;
},
onClose(){
onClose() {
this.formData = {};
this.dialogVisible = false;
},
onSave(){
onSave() {
this.formData.clue_id = this.id;
this.formData.delete_flag = 0;
console.log('修改后: ',this.formData);
this.$axios.post('http://localhost:8000/addOneClue/',
{table_id:this.tableId,record:this.formData})
.then(response=>{
if(response.data.message == '插入成功'){
console.log("修改后: ", this.formData);
this.$axios
.post("http://localhost:8000/addOneClue/", {
table_id: this.tableId,
record: this.formData,
})
.then((response) => {
if (response.data.message == "插入成功") {
this.$message({
type:'success',
message:'插入成功'
type: "success",
message: "插入成功",
});
location.reload();
}else if(response.data.message == '插入失败'){
} else if (response.data.message == "插入失败") {
this.$message({
typeof:'error',
message:'插入失败,请对应数据格式,请重试!'
})
typeof: "error",
message: "插入失败,请对应数据格式,请重试!",
});
}
})
.catch(error=>{
.catch((error) => {
this.$handleNetError(error);
})
}
});
},
}
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@ -3,14 +3,22 @@
<el-dialog
title="编辑线索记录"
v-model="dialogVisible"
align-center="true"
draggable
@opened="onOpen"
@close="onClose"
>
<el-container>
<el-form label-width="100px">
<el-form-item v-for="(col, index) in formFields" :key="index" :label="col.label">
<el-input v-model="formData['col_'+col.prop]" :placeholder="computedPlaceholders[col.prop]"></el-input>
<el-form-item
v-for="(col, index) in formFields"
:key="index"
:label="col.label"
>
<el-input
v-model="formData['col_' + col.prop]"
:placeholder="computedPlaceholders[col.prop]"
></el-input>
</el-form-item>
</el-form>
<el-footer class="dialog-footer">
@ -22,7 +30,7 @@
</template>
<script>
export default {
export default {
props: {
columns: Array, //
visible: Boolean,
@ -35,7 +43,7 @@
computedPlaceholders() {
const placeholders = {};
// formFieldsprop
this.formFields.forEach(field => {
this.formFields.forEach((field) => {
// prop'col_'
const formDataKey = `col_${field.prop}`;
// formData
@ -46,29 +54,33 @@
return placeholders;
},
},
emits: ['update:visible'],
emits: ["update:visible"],
data() {
return {
formData: {},
formFields: [],
dialogVisible:false,
dialogVisible: false,
placeholders: {}, //
};
},
watch: {
columns(newColumns) {
this.formFields = newColumns.filter(col => col.prop !== 'id').map(col => ({ ...col, prop: col.prop.replace('col_', '') }));
this.formFields = newColumns
.filter((col) => col.prop !== "id")
.map((col) => ({ ...col, prop: col.prop.replace("col_", "") }));
},
visible(value) {
this.dialogVisible = value;
},
},
created() {
this.formFields = this.columns.filter(col => col.prop !== 'id').map(col => ({ ...col, prop: col.prop.replace('col_', '') }));
this.formFields = this.columns
.filter((col) => col.prop !== "id")
.map((col) => ({ ...col, prop: col.prop.replace("col_", "") }));
},
methods: {
onClose() {
this.$emit('update:visible', false);
this.$emit("update:visible", false);
this.dialogVisible = false;
this.formData = {};
},
@ -76,30 +88,32 @@
this.formData.clue_id = this.editDataID.clue_id;
this.formData.delete_flag = 0;
console.log('修改后的数据:',this.formData);
console.log("修改后的数据:", this.formData);
//
this.$axios.post('http://localhost:8000/updateOneClue/',
{table_id:this.editDataID.table_id,record:this.formData})
this.$axios
.post("http://localhost:8000/updateOneClue/", {
table_id: this.editDataID.table_id,
record: this.formData,
})
.then(() => {
this.onClose();
this.$message.success('保存成功');
}).catch(error => {
this.$message.success("保存成功");
})
.catch((error) => {
this.$handleNetError(error);
});
location.reload();
},
onOpen(){
console.log('修改前的数据:',this.formData);
onOpen() {
console.log("修改前的数据:", this.formData);
},
clickToCloseDialog(){
clickToCloseDialog() {
this.dialogVisible = false;
this.formData = {};
}
},
};
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@ -16,7 +16,7 @@
<div class="demo-select">
<div class="block">
<span class="demonstration">选择统计指标</span>
<el-select v-model="selectedrow2" multiple placeholder="统计指标">
<el-select v-model="selectedrow2" placeholder="统计指标">
<el-option
v-for="row in rowOptions2"
:key="row.value"

View File

@ -2,8 +2,8 @@
<div>
<div class="demo-select">
<div class="block">
<span class="demonstration">选择实体列</span>
<el-select v-model="selectedrow" placeholder="请选择实体列">
<span class="demonstration">选择横轴</span>
<el-select v-model="selectedrow" placeholder="请选择横轴">
<el-option
v-for="row in rowOptions"
:key="row.value"
@ -15,8 +15,8 @@
</div>
<div class="demo-select">
<div class="block">
<span class="demonstration">选择统计指标</span>
<el-select v-model="selectedrow2" placeholder="统计指标">
<span class="demonstration">选择竖轴</span>
<el-select v-model="selectedrow2" placeholder="请选择数轴">
<el-option
v-for="row in rowOptions2"
:key="row.value"
@ -26,19 +26,6 @@
</el-select>
</div>
</div>
<div class="demo-select">
<div class="block">
<span class="demonstration">请选择起始日期列</span>
<el-select v-model="selectedrow3" placeholder="日期列">
<el-option
v-for="row in rowOptions3"
:key="row.value"
:label="row.label"
:value="row.value"
></el-option>
</el-select>
</div>
</div>
<div class="demo-select">
<div class="block">
<span class="demonstration">图形样式</span>
@ -53,29 +40,22 @@
</div>
</div>
</div>
</template>
<script setup>
import { ref, defineExpose, defineProps, defineEmits,watch } from 'vue';
</template>
const selectedEntity = ref(null);
const selectedChartType = ref(''); //
const selectedrow = ref(null);
const selectedrow2 = ref(null);
const rowOptions2=ref('')
<script setup>
import { ref, defineExpose, defineProps, defineEmits,watch } from 'vue';
const selectedEntity = ref(null);
const selectedChartType = ref(''); //
const selectedrow = ref(null);
const selectedrow2 = ref(null);
const selectedrow3= ref(null);
const rowOptions2=ref(null);
const rowOptions3=ref(null);
const chartTypes = [
const chartTypes = [
{ value: 'line', label: '折线图' },
{ value: 'bar', label: '柱状图' },
{ value: 'pie', label: '饼图' }
];
//
const emits = defineEmits(['update:selectedEntity', 'update:selectedrow', 'update:selectedrow2','update:selectedrow3','update:selectedChartType']);
const props= defineProps({
{ value: 'scatter', label: '散点图' },
];
const props= defineProps({
rowOptions: Array,
})
@ -86,45 +66,59 @@ watch(() => props.rowOptions, (newVal) => {
{ value: 'entity', label: '线索数' }, //
...newVal //
];
rowOptions3.value = [
{ value: 'entity', label: '线索数' }, //
...newVal //
];
}, { immediate: true });
//
defineExpose({
//
const emits = defineEmits(['update:selectedEntity', 'update:selectedrow', 'update:selectedrow2','update:selectedChartType']);
// onMounted(async () => {
// try {
// //
// const response = await fetch('http://localhost:3000/data');
// if (!response.ok) {
// throw new Error('Failed to fetch data');
// }
// const data = await response.json();
// rowOptions.value = data;
// rowOptions2.value = [
// { value: 'entity', label: '线' }, //
// ...data //
// ];
// console.log(rowOptions.value)
// } catch (error) {
// console.error('Error fetching data:', error);
// }
// });
//
defineExpose({
selectedEntity,
selectedrow,
selectedrow2,
selectedrow3,
selectedChartType
});
});
//
watch(selectedEntity, () => {
//
watch(selectedEntity, () => {
emits('update:selectedEntity', selectedEntity.value);
});
});
watch(selectedrow, () => {
watch(selectedrow, () => {
emits('update:selectedrow', selectedrow.value);
});
watch(selectedrow2, () => {
});
watch(selectedrow2, () => {
emits('update:selectedrow2', selectedrow2.value);
});
watch(selectedrow3, () => {
emits('update:selectedrow3', selectedrow3.value);
});
watch(selectedChartType, () => {
});
watch(selectedChartType, () => {
emits('update:selectedChartType', selectedChartType.value);
});
});
</script>
</script>
<style>
<style>
.el-row {
.el-row {
margin-top: 5px;
margin-bottom: 10px;
}

View File

@ -5,7 +5,6 @@ import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './assets/css/global.css'
import './assets/css/tailwind.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import axios from 'axios'
import NetErrorHandler from '@/api/netErrorHandler';

View File

@ -1,24 +1,46 @@
<template>
<el-container style="height:100%">
<el-header class = 'containerHead'>
<HeaderPage :pageTitle = 'pageTitle'></HeaderPage>
<el-button class = 'btnReturnHomePage' @click="returnHome">
<el-tooltip content = '返回首页'>
<el-icon><Back /></el-icon>
<el-container style="height: 100%">
<el-header class="containerHead">
<HeaderPage :pageTitle="pageTitle"></HeaderPage>
<el-button class="btnReturnHomePage" @click="returnHome">
<el-tooltip content="返回首页">
<el-icon><ArrowLeft /></el-icon>
</el-tooltip>
</el-button>
</el-header>
<el-main class ='container_Tools_Main'>
<el-header class ='containerTools'>
<!-- 模式切换按钮 -->
<el-button class = 'btnDelete'>
<el-tooltip content = '批量删除'>
<el-main class="container_Tools_Main">
<!-- 折叠版存放约束条件显示 -->
<!-- <el-container class="containerConstraints">
<el-collapse v-model="activeNames">
<el-collapse-item name="1">
<div
class="divConstraintView"
v-for="(i, index) in Constraints"
:key="index"
>
{{
"逻辑关系:" +
i.merge +
" 约束列:" +
search_clu_name(i.col_id) +
" " +
Condition_to_string(i)
}}
<button @click="constraint_delete(index)">删除</button>
</div>
</el-collapse-item>
</el-collapse>
</el-container> -->
<!-- 工具栏 -->
<el-header class="containerTools">
<el-button class="btnDelete">
<el-tooltip content="删除所有">
<el-icon><Delete /></el-icon>
</el-tooltip>
</el-button>
<el-button class = 'btnSearch' @click = 'searchDialogVisible = true'>
<el-tooltip content = '条件查找'>
<el-icon><Search /></el-icon>
<el-button class="btnSearch" @click="searchDialogVisible = true">
<el-tooltip content="条件查找">
<el-icon style="margin-right: -15px"><Search /></el-icon>
</el-tooltip>
<!-- 条件查找对应的对话框 -->
<!-- @author myz
@ -27,68 +49,16 @@
@v-model:isVisible 控制对话框可见的v-model
@confirm: @confirm 处理子部件的confirm事件 -->
<ConstraintSearchDialog
:colData = 'clueCols'
v-model:isVisible = 'searchDialogVisible'
@confirm = 'handleSearchDialogConfirm'
:colData="clueCols"
v-model:isVisible="searchDialogVisible"
@confirm="handleSearchDialogConfirm"
/>
</el-button>
<el-button class = 'btnMore' @click="dochart">
<el-tooltip content = '更多'>
<el-icon><More /></el-icon>
</el-tooltip>
</el-button>
</el-header>
<!-- 编辑线索的对话框 -->
<EditDialog
:columns="cols"
ref="editDialog"
:editDataID="currentEditDataID"
/>
<el-main class = 'containerMain'>
<!-- 展示约束条件 -->
<details class="shadow-md collapse collapse-arrow bg-white mb-1 opacity-90 text-gray-900 text-xl">
<summary class="collapse-title font-bold">已添加的约束条件</summary>
<div class="collapse-content flex flex-col bg-white bg-opacity-30 list-decimal">
<li class = ' text-sm italic tracking-wide flex justify-between' v-for="(i,index) in Constraints" :key="index" >
<el-text>{{"逻辑关系:" + i.merge + " 约束列:" + search_clu_name(i.col_id) + " " +Condition_to_string(i)}}</el-text>
<el-button class = 'btnItemDelete' @click="constraint_delete(index)">删除</el-button>
</li>
</div>
</details>
<el-table
class = 'containerTable'
:data="formattedTableData"
height="100%"
style="width: 100%; margin-bottom: 0.5%; height:95%"
@selection-change="handleSelectionChange"
:selectable="selectionItem_visible"
>
<el-table-column type = 'selection' width="30"/>
<el-table-column class = 'containerTabHead'
v-for="(column, index) in cols"
:key="index"
:prop="column.prop"
:label="column.label"
show-overflow-tooltip
width = "150"
/>
<el-table-column fixed="right" width = 150px label="操作">
<template #header>
<div style="display: flex; justify-self: flex-end; padding-left: 38px;">操作</div>
</template>
<template #default="scope">
<!-- 使用插槽将数据传入到方法watchClue中 -->
<el-button class = 'btnItemEdit' size="small" @click="editClue(scope.row)">编辑</el-button>
<el-button class = 'btnItemDelete' size="small" @click="deleteClue(scope.row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<el-button class = 'btnPlus' @click="addOneClue">
<el-tooltip content = '添加一条线索'>
<el-button class="btnPlus" @click="addOneClue">
<el-tooltip content="添加">
<el-icon><Plus /></el-icon>
</el-tooltip>
</el-button>
<!-- 添加线索的对话框 -->
<AddDialog
ref="addDialog"
:addClueCols="clueCols"
@ -96,7 +66,87 @@
:tableId="clueId"
>
</AddDialog>
<el-button class="btnMore" @click="dochart">
<el-tooltip content="更多">
<el-icon><More /></el-icon>
</el-tooltip>
</el-button>
</el-header>
<EditDialog
:columns="cols"
ref="editDialog"
:editDataID="currentEditDataID"
></EditDialog>
<el-main class="containerMain">
<el-table
class="containerTable"
:data="formattedTableData"
border
:header-cell-style="{
background: '#f2f5fc',
}"
height="100%"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
style="background-color: black"
/>
<el-table-column
class="containerTabHead"
v-for="(column, index) in cols"
:key="index"
:prop="column.prop"
:label="column.label"
/>
<el-table-column
fixed="right"
width="200px"
label="操作"
class="custom-operation-column"
>
<template #default="scope">
<div class="mb-4">
<!-- 使用插槽将数据传入到方法watchClue中 -->
<el-button
:icon="Delete"
class="btnItemEdit"
@click="editClue(scope.row)"
>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 5px">编辑</span>
</el-button>
<el-button class="btnItemDelete" @click="deleteClue(scope.row)">
<el-icon>
<Delete />
</el-icon>
<span style="margin-left: 5px">删除</span>
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</el-main>
<!-- </el-main> -->
<el-footer>
<el-button class="btnPlus" @click="addOneClue">
<el-tooltip content="添加">
<el-icon><Plus /></el-icon>
</el-tooltip>
</el-button>
<AddDialog
ref="addDialog"
:addClueCols="clueCols"
:id="MaxId"
:tableId="clueId"
>
</AddDialog>
</el-footer>
</el-main>
</el-container>
</template>
@ -107,39 +157,40 @@ const debounce = (fn, delay) => {
let timer;
return (...args) => {
if (timer) {
clearTimeout(timer)
clearTimeout(timer);
}
timer = setTimeout(() => {
fn(...args)
}, delay)
}
fn(...args);
}, delay);
};
};
//
const _ResizeObserver = window.ResizeObserver;
window.ResizeObserver = class ResizeObserver extends _ResizeObserver{
window.ResizeObserver = class ResizeObserver extends _ResizeObserver {
constructor(callback) {
callback = debounce(callback, 200);
super(callback);
}
};
import ConstraintSearchDialog from "@/components/components_cluespage/ConstraintSearchDialog.vue"
import EditDialog from "@/components/components_cluespage/EditDialog.vue"
import HeaderPage from "@/components/HeaderPage.vue"
import AddDialog from "@/components/components_cluespage/AddDialog.vue"
import ConstraintSearchDialog from "@/components/components_cluespage/ConstraintSearchDialog.vue";
import EditDialog from "@/components/components_cluespage/EditDialog.vue";
import HeaderPage from "@/components/HeaderPage.vue";
import AddDialog from "@/components/components_cluespage/AddDialog.vue";
export default{
components:{
export default {
components: {
ConstraintSearchDialog,
HeaderPage,
EditDialog,
AddDialog,
},
name:'CluesPage',
data(){
name: "CluesPage",
data() {
// id
const clueId = this.$route.params.id;
const pageTitle = this.$route.params.pageTitle;
// console.log("线ID", clueId)
const generateMockData = (cols, numRows = 20) => {
const data = [];
for (let i = 0; i < numRows; i++) {
@ -163,134 +214,120 @@ export default{
return columns;
}
return {
//
searchDialogVisible : false,
searchDialogVisible: false,
//
"Constraints":[
{"merge":"AND","col_id":"3","type":"double","down":"0","up":"INF","inside":"","date":""}, // 1_30
{"merge":"AND","col_id":"2","type":"date","down":"","up":"","inside":"","date":"03.06.2024,30.06.2024"}, // !_22024/1/1
{"merge":"OR","col_id":"4","type":"string","down":"","up":"","inside":"AAA","date":""} // 1_4(),AAA
Constraints: [
//
// {"merge":"AND","col_id":"3","type":"double","down":"0","up":"INF","inside":"","date":""}, // 1_30
// {"merge":"AND","col_id":"2","type":"date","down":"","up":"","inside":"","date":"03.06.2024,30.06.2024"}, // !_22024/1/1
// {"merge":"OR","col_id":"4","type":"string","down":"","up":"","inside":"AAA","date":""} // 1_4(),AAA
],
pageTitle, // /线
//
pageTitle, //
clueId, // 线ID
MaxId:Number ,// 线Id
MaxId: Number, // 线Id
addDialogVisible: false, // 线
chart: false,
currentEditDataID: {},
selectedColumnData :{},
selectedColumnData: {},
clueCols, // clueCols[]
clueData: generateMockData(clueCols, 20), // 20 , clueData:[]
batchRemoveBtn_disabled: true, //
editBtn_disabled: true, //
selectionItem_visible: false, //
/* 变量用于控制样式 */
mulmodeStyle: '',
normalmodeStyle: '',
modeSelectedStyle:{
"color": "white",
"font-size": "14px",
"font-weight": "bold",
"background-color": "#1ad4c4d4",
};
},
modeUnselectedStyle:{
"color": "white",
"font-size": "14px",
"font-weight": "bold",
"background-color": "#1DAFAF",
},
batchDeleteBtn_style: '',
editBtn_style: '',
editBtn_disabled_style:{
"background-color": "gray",
"color": "white",
"border-radius": "14px",
"font-size": "12px",
"font-weight": "bold"
},
editBtn_enabled_style:{
"background-color": "1DAFAF",
"color": "white",
"border-radius": "14px",
"font-size": "12px",
"font-weight": "bold"
}
}
},
methods:{
methods: {
// confirm
handleSearchDialogConfirm(form){
handleSearchDialogConfirm(form) {
console.log("提交约束条件", form);
const newConstraint = {
"merge": form.logic,
"col_id": form.col_id,
"type": form.type,
"inside": form.search_string,
"up": form.max_limit,
"down": form.min_limit,
"date": form.continuous_time[0] + ',' + form.continuous_time[1],
}
merge: form.logic,
col_id: form.col_id,
type: form.type,
inside: form.search_string,
up: form.max_limit,
down: form.min_limit,
date: form.continuous_time[0] + "," + form.continuous_time[1],
};
this.Constraints.push(newConstraint);
this.getClueCols();
this.getClueData();
},
// id
search_clu_name(aa){
search_clu_name(aa) {
for (let col of this.clueCols) {
if(aa == col.col_id)
return col.col_name;
if (aa == col.col_id) return col.col_name;
}
},
Condition_to_string(Constraint){
if(Constraint.type == "string"){
Condition_to_string(Constraint) {
if (Constraint.type == "string") {
return " 包含 " + Constraint.inside;
}
if(Constraint.up == "INF" && Constraint.down == "INF"){
if (Constraint.up == "INF" && Constraint.down == "INF") {
return " 类型为 " + Constraint.type;
}
if(Constraint.up == "INF" && Constraint.type == "double"){
if (Constraint.up == "INF" && Constraint.type == "double") {
return " 大于等于 " + Constraint.down;
}
if(Constraint.down == "INF" && Constraint.type == "double"){
if (Constraint.down == "INF" && Constraint.type == "double") {
return " 小于等于 " + Constraint.up;
}
if(Constraint.type == "double")return " 在 " + Constraint.down + " 和 " + Constraint.up + "之间";
if(Constraint.type == "date")return "在 " + Constraint.date + "之间";
if (Constraint.type == "double")
return (
" 在 " + Constraint.down + " 和 " + Constraint.up + "之间"
);
if (Constraint.type == "date") return "在 " + Constraint.date + "之间";
},
constraint_delete(index){
constraint_delete(index) {
this.Constraints.splice(index, 1);
this.getClueCols();
this.getClueData();
},
dochart(){
const table=JSON.stringify(this.clueData);
const column=JSON.stringify(this.cols);
this.$router.push({name:'Graph',params:{columns:column,tabledata:table}})
dochart() {
const table = JSON.stringify(this.clueData);
const column = JSON.stringify(this.cols);
this.$router.push({
name: "Graph",
params: { columns: column, tabledata: table },
});
},
handleSelectionChange(selection) {
// selection
this.selectedColumnData = selection;
console.log( this.selectedColumnData);
console.log('选择的行数据:', selection);
console.log(this.selectedColumnData);
console.log("选择的行数据:", selection);
},
receiveSrow(value) {
//
this.srow = value;
console.log("djlasj", value);
},
//
returnHome(){
this.$router.push({name:'Table'})
returnHome() {
this.$router.push({ name: "Table" });
},
//
getClueCols(){
this.$axios.post('http://localhost:8000/showClueCol/', {table_id:this.clueId}).then(response=>{
getClueCols() {
this.$axios
.post("http://localhost:8000/showClueCol/", { table_id: this.clueId })
.then((response) => {
this.clueCols = response.data;
})
});
},
// 线
getClueData(){
this.$axios.post('http://localhost:8000/showClue/',{table_id:this.clueId,Constraints:this.Constraints}).then(response=>{
this.clueData = response.data;
getClueData() {
this.$axios
.post("http://localhost:8000/showClue/", {
table_id: this.clueId,
Constraints: this.Constraints,
})
.then((response) => {
this.clueData = response.data;
console.log(this.clueData);
});
},
mergeCols(){
mergeCols() {
// 便
const colMap = this.clueCols.reduce((acc, col) => {
acc[col.col_id] = col.col_name;
@ -299,64 +336,69 @@ export default{
// clueData
//
const mergedColumns = Object.keys(this.clueData[0]).map(key => {
if (key.startsWith('col_')) {
const colId = key.replace('col_', ''); //
if(colId != 'id'){//id
return { prop: key, label: colMap[colId] || '未知列名' };
const mergedColumns = Object.keys(this.clueData[0])
.map((key) => {
if (key.startsWith("col_")) {
const colId = key.replace("col_", ""); //
if (colId != "id") {
//id
return { prop: key, label: colMap[colId] || "未知列名" };
}
}
return null; // col_
}).filter(Boolean); // null
})
.filter(Boolean); // null
//
return mergedColumns;
},
deleteClue(row){
deleteClue(row) {
const postData = {
table_id:this.clueId,
clue_id:row.clue_id
table_id: this.clueId,
clue_id: row.clue_id,
};
//console.log(row)
this.$axios.post('http://localhost:8000/delClue/',postData).then(response=>{
this.$axios
.post("http://localhost:8000/delClue/", postData)
.then((response) => {
const message = response.data.message;
//
if(message == "删除成功"){
if (message == "删除成功") {
// this.$message
this.$message({
type:'success',
message:'删除成功!'
type: "success",
message: "删除成功!",
});
//
location.reload();
}else if(message == "删除失败"){
} else if (message == "删除失败") {
this.$message({
type:'error',
message:'删除失败,请重试!'
type: "error",
message: "删除失败,请重试!",
});
}
})
.catch(error=>{
.catch((error) => {
// 使
this.$handleNetError(error);
});
},
// 线
editClue(row){
editClue(row) {
let editDataID = {
table_id:this.clueId,
clue_id:row.clue_id // clue_id,
table_id: this.clueId,
clue_id: row.clue_id, // clue_id,
};
this.$refs.editDialog.dialogVisible = true; //
this.$refs.editDialog.formData = this.formatFormData(row); //
this.currentEditDataID = editDataID;
console.log('editDataID',editDataID);
console.log("editDataID", editDataID);
},
//
formatFormData(row) {
const formData = {};
this.cols.forEach(col => {
if (col.prop !== 'id') {
this.cols.forEach((col) => {
if (col.prop !== "id") {
formData[col.prop] = row[col.prop];
}
});
@ -364,13 +406,13 @@ export default{
return formData;
},
// 线
addOneClue(){
addOneClue() {
this.$refs.addDialog.dialogVisible = true; //
this.MaxId = this.clueData.length + 1;
},
},
computed: {
cols(){
cols() {
if (this.clueCols.length && this.clueData.length) {
return this.mergeCols();
}
@ -379,25 +421,25 @@ export default{
formattedTableData() {
// ID
const Data = this.clueData.map(row => {
const Data = this.clueData.map((row) => {
const newRow = { ...row }; // row
//
this.cols.forEach(col => {
if (col.label !== 'ID') {
this.cols.forEach((col) => {
if (col.label !== "ID") {
newRow[col.label] = newRow[col.prop];
}
});
return newRow;
});
return Data;
}
},
},
watch: {
//
searchDialogVisible(newValue){
searchDialogVisible(newValue) {
console.log(newValue);
},
Constraints(newv){
Constraints(newv) {
console.log(newv);
},
},
@ -405,117 +447,99 @@ export default{
</script>
<style scoped>
.el-container{
.el-container {
padding: 0;
}
.containerTools{
height:4%;
padding:0.7%;
display:flex;
.containerTools {
background: white;
height: 6%;
padding: 2%;
display: flex;
justify-content: flex-end;
align-items: center;
}
.containerHead{
padding:0;
height:6%;
padding :0;
.containerHead {
padding: 0;
height: 8%;
padding: 0;
width: 100%;
display:flex;
display: flex;
justify-content: space-between;
background-color: white;
background-color: #b3c0d1;
align-items: center;
}
.HeaderPage{
.el-container.toolbar {
background: #b3c0d1;
}
.HeaderPage {
width: 90%;
}
.btnReturnHomePage{
.btnReturnHomePage {
font-size: large;
width: 3%;
font-weight: 25px;
}
.container_Tools_Main{
padding:0;
.container_Tools_Main {
padding: 0;
background-color: #f5f6fa;
height: 94%;
height: 92%;
width: 100%;
display: flex;
justify-content: center;
flex-direction: column;
}
.el-button{
.el-button {
background-color: transparent;
margin:2;
padding:2;
margin: 2;
padding: 2;
border: 0;
color: #0e5858;
font-size: 24px;
}
.el-button:hover{
.el-button:hover {
background-color: rgba(255, 255, 255, 0.7);
}
/* 设置表格 */
.containerMain{
.containerMain {
background-color: #f5f6fa;
padding: 10px;
padding-top: 0;
height:96%;
height: 90%;
overflow: auto;
}
.btnItemDelete{
background-color: lightcoral;
.btnItemDelete {
background-color: rgb(223, 62, 62);
color: white;
border-radius: 14px;
font-size: 12px;
font-size: 14px;
font-weight: bold;
}
.btnItemDelete:hover{
.btnItemDelete:hover {
background: rgba(240, 128, 128, 0.647);
}
.btnItemEdit{
background-color: #1DAFAF;
.btnItemEdit {
background-color: #409eff;
color: white;
border-radius: 14px;
font-size: 12px;
font-size: 14px;
font-weight: bold;
}
.btnItemEdit:hover{
background: #1dafafd2;
.btnItemEdit:hover {
background: #90bdeb;
}
.btnDelete,.btnSearch,.btnMore{
.btnDelete,
.btnSearch,
.btnMore {
text-align: start;
padding: 0.6%;
margin: 0;
}
/* 控制多选模式和单选模式按钮的CSS */
#mul-mode{
background-color: #1DAFAF;
color: white;
font-size: 14px;
font-weight: bold;
.custom-operation-column .cell {
font-size: 16px; /* 修改操作字体大小 */
text-align: center; /* 调整标题文本居中对齐 */
/* 其他样式调整 */
}
#normal-mode{
color: white;
font-size: 14px;
font-weight: bold;
background-color: #1DAFAF;
}
#mul-mode:hover,#normal-mode:hover{
background-color: #1ad4c4d4;
color: white;
}
#containerConstraints{
background-color: #1DAFAF;
}
.btnPlus{
color:white;
font-size: 14px;
width: 1%;
background-color: #158484;
height: 1%;
}
.btnPlus:hover{
background-color: #1DAFAF
.custom-operation-header {
font-size: 16px; /* 修改标题字体大小 */
text-align: center; /* 调整标题文本居中对齐 */
/* 其他样式调整 */
}
</style>

View File

@ -1,19 +1,17 @@
<template>
<el-container class = "containerAll">
<el-container class="containerAll">
<!--这是头栏部件-->
<el-header class = 'containerHead'>
<HeaderPage :pageTitle = 'pageTitle'>
</HeaderPage>
<el-header class="containerHead">
<HeaderPage :pageTitle="pageTitle"> </HeaderPage>
</el-header>
<el-main style="padding:0; height:92%" >
<el-container class = "container_Tools_Main" >
<el-main style="padding: 0; height: 92%">
<el-container class="container_Tools_Main">
<!--这是主体的头栏用于防止工具等-->
<el-header class = 'containerTools'>
<el-header class="containerTools">
<!--这是上传文档按钮-->
<el-button class = 'uploadBtn' type = 'primary' @click='openDialog'>
<el-tooltip content = '上传文件'>
<el-icon><DocumentAdd/></el-icon>
<el-button class="uploadBtn" type="primary" @click="openDialog">
<el-tooltip content="上传文件">
<el-icon><DocumentAdd /></el-icon>
</el-tooltip>
</el-button>
<el-dialog
@ -30,16 +28,14 @@
:http-request="uploadFiles"
:on-exceed="handleExceed"
:limit="1"
accept='.csv'
accept=".csv"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
拖拽文件到这里或者 <em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">
上传csv文档
</div>
<div class="el-upload__tip">上传csv文档</div>
</template>
</el-upload>
</div>
@ -52,9 +48,8 @@
</div>
</template>
</el-dialog>
</el-header>
<el-main class = 'containerMain'>
<el-main class="containerMain">
<Clues_Database_Display />
</el-main>
</el-container>
@ -64,112 +59,118 @@
<script>
/** 引入所有线索库的展示部件 */
import Clues_Database_Display from '@/components/components_homepage/ShowCluesTable.vue'
import Clues_Database_Display from "@/components/components_homepage/ShowCluesTable.vue";
/** 映入头栏的展示部件 */
import HeaderPage from "@/components/HeaderPage.vue"
import { ElContainer } from 'element-plus'
import HeaderPage from "@/components/HeaderPage.vue";
import { ElContainer } from "element-plus";
export default{
components:{
export default {
components: {
HeaderPage,
Clues_Database_Display
Clues_Database_Display,
},
data(){
return{
pageTitle: '线索库总览',
dialogVisible:false,
fileList:[],
fileName:'',
isFileUploaded:false,
data() {
return {
pageTitle: "线索库总览",
dialogVisible: false,
fileList: [],
fileName: "",
isFileUploaded: false,
cardsPerRow: 3, // 3
}
};
},
methods:{
openDialog(){
methods: {
openDialog() {
this.dialogVisible = true;
},
handleUpload(){
handleUpload() {
this.dialogVisible = false;
},
uploadFiles(params){
uploadFiles(params) {
this.fileList.push(params.file);
console.log("获取到的文件:",params.file);
console.log("获取到的文件:", params.file);
},
//
handleExceed() {
this.$message({ type: 'error', message: '最多支持1个附件上传' })
this.$message({ type: "error", message: "最多支持1个附件上传" });
},
//
submitImportForm() {
// 使form
const params = new FormData()
const params = new FormData();
// paramsData
this.fileList.forEach((file) => {
params.append('file', file)
console.log("导入表单的文件:",file)
params.append("file", file);
console.log("导入表单的文件:", file);
});
// params
params.append('name', this.fileName)
params.append("name", this.fileName);
// console.log("",params.get('name'));
console.log("整个表单数据:",params)
console.log("整个表单数据:", params);
//axios
this.$axios.post('http://localhost:8000/CSVUploadView/',params).then(response => {
this.$axios
.post("http://localhost:8000/CSVUploadView/", params)
.then((response) => {
this.$message({
message: response.data.message,
type: "success"
})
location.reload()
type: "success",
});
location.reload();
// this.$refs.importFormRef.resetFields()//
// this.$refs.upload.clearFiles()//
this.fileList = []//
this.dialogVisible1 = false//
})
}
}
}
this.fileList = []; //
this.dialogVisible1 = false; //
});
},
},
};
</script>
<style scoped>
/** 工具栏的样式 */
.containerAll{
.containerAll {
/* 只有调整父部件的高度子部件的高度才能按照100%调控 */
height: 100%;
padding:0;
padding: 0;
width: 100%;
}
/* 头栏样式表 */
.containerHead{
.containerHead {
width: 100%;
padding: 0;
height: 6%;
height: 8%;
background-color: #b3c0d1;
}
.containerTools{
.toolbar {
background-color: #b3c0d1;
}
.containerTools {
padding-right: 2%; /**让按钮与卡片最左侧对齐 */
margin: 0;
height: 6%;
display: flex;
align-items: center;
justify-content: flex-end;
}
/* 工具栏和主体样式 */
.container_Tools_Main{
.container_Tools_Main {
width: 100%;
padding: 0;
margin: 0;
height:100%;
height: 100%;
background-color: #f5f6fa;
}
/* 上传按钮样式 */
.uploadBtn{
color: #0E5858;
.uploadBtn {
color: #0e5858;
background-color: transparent;
border: 0;
font-size:30px;
font-size: 30px;
}
.uploadBtn:hover{
.uploadBtn:hover {
background-color: rgba(255, 255, 255, 0.7);
}
</style>

View File

@ -35,31 +35,10 @@
@update:selectedrow="handleSelectedRow"
@update:selectedChartType="handleSelectedChartType"
@update:selectedrow2="handleSelectedRow2"
@update:selectedrow3="handleSelectedRow3"
:rowOptions="convertedColumns"
:rowOptions2="convertedColumns"
>
</component>
<el-card v-if="entity">
<el-row>
<el-table
:data="columnData"
:show-header="true"
:max-height="200"
@selection-change="handleSelectionChange"
stripe
>
<el-table-column type="selection" width="55" style="background-color: black;"/>
<el-table-column
prop="name"
label="对象"
header-style="background-color: black; color: white;"
style="text-align: center;">
</el-table-column>
</el-table>
</el-row>
</el-card>
<el-form-item>
<el-button type="primary" size="medium" @click="handleGenerateChart">
点击生成图表
@ -69,16 +48,16 @@
</el-row>
</el-card>
</div>
<div class="right-grid" v-if="hasUpperContent">
<div class="right-grid">
<div class="upper-right" v-if="hasUpperContent">
<el-button type="danger" @click="clearchart">取消</el-button>
<div ref="chartContainer" class="chart-container"></div>
</div>
<div class="lower-right">
</div>
<div class="right-grid" v-else> <div ref="chartContainer" class="chart-container"></div> </div>
</div>
</div>
</el-container>
</template>
@ -106,8 +85,6 @@ export default {
data() {
return {
ISmul4:false,
selectedColumnData:Array,
xz:[],
yz:[],
pageTitle:'图形可视化',
@ -121,7 +98,6 @@ export default {
stype:'',
srow:'',
srow2:'',
srow3:'',
gap:'',
monthKey:'',
chartType: 'bar',
@ -152,25 +128,6 @@ export default {
// }
// },
computed: {
entity()
{
if (this.selectedEntity=='entity5')
return 1;
else
return 0;
},
columnData() {
if (this.srow)
{
let name=this.srow
const uniqueSet = new Set(this.mytable.map(item => item[name]));
// Set
const uniqueArray = Array.from(uniqueSet).map(name => ({ name: name }));
return uniqueArray;
}
else
return '';
},
convertedColumns() {
return this.mycolumns.map(item => {
return { value: item.prop, label: item.label };
@ -202,77 +159,9 @@ export default {
console.log('Parsed columns:', this.mycolumns,this.table);
},
methods: {
handleSelectionChange(selection) {
// selection
let obj=selection.map(item=>item.name)
console.log(obj)
this.selectedColumnData =selection.map(item=>item.name)
console.log( this.selectedColumnData);
console.log('选择的行数据:', selection);
},
returnHome(){
window.history.back();
},
extractThreeColumns(tableData) {
let extractedData = tableData.map(row => ({
month: row[this.srow3],
product: row[this.srow],
amount: row[this.srow2]
}));
return extractedData;
},
count_sum_time()
{
this.hasUpperContent = true;
let counts = {};
let salesData=this.extractThreeColumns(this.mytable);
console.log(salesData)
// counts
salesData.forEach(record => {
let { month, product, amount } = record;
let currentMonth=new Date(month)
let monthKey1 = currentMonth.getFullYear() + '-' + (currentMonth.getMonth() + 1);
if (!counts[monthKey1]) {
counts[monthKey1] = {};
}
if ( !counts[monthKey1][product])
counts[monthKey1][product] = amount;
else
counts[monthKey1][product] += amount;
});
// counts
const products = this.selectedColumnData;
let years = Array.from(new Set(salesData.map(record => new Date(record.month).getFullYear()+ '-' + (new Date(record.month).getMonth() + 1)))).sort();
// Create the structure similar to 'source'
let result = [['product', ...years]];
products.forEach(product => {
let rowData = [product];
for (let i = 0; i < years.length; i++) {
rowData.push(0);
}
result.push(rowData);
});
products.forEach(product=>
{
years.forEach(year => {
if (counts[year][product])
result[products.indexOf(product)+1][years.indexOf(year)+1]+=counts[year][product];
else
result[products.indexOf(product)+1][years.indexOf(year)+1]+=0;
});
}
)
console.log(result)
return result;
},
countsumbystring() {
//
this.hasUpperContent = true;
@ -295,98 +184,6 @@ for (let i = 0; i < years.length; i++) {
//
return sumByName;
},
do_entity4()
{let counts=[];
for (let i=0;i<this.srow2.length;i++)
{
this.handletwodata(this.srow,this.srow2[i]);
if (this.srow2[i]=='entity')
{
counts[i]=this.countStrings();
}
else
counts[i]=this.countsumbystring();
}
return counts;
},
generateyAxis(counts)
{
let yAxis = [];
// Generate Evaporation and Precipitation yAxis
for (let i = 0; i < counts.length; i++) {
yAxis.push({
type: 'value',
name: this.srow2[i],
position: 'left',
offset:i*40,
alignTicks: true,
axisLine: {
show: true
}
});
}
return yAxis;
},
generateSeries2(counts)
{
let Series= [];
// Generate Evaporation and Precipitation yAxis
for (let i = 0; i < counts.length; i++) {
Series.push({
name: this.srow2[i],
type: this.stype,
data: Object.values(counts[i]),
});
} return Series;
},
generateOptions(counts)
{
let option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: {
right: '20%'
},
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
legend: {
data: Object.values(this.srow2)
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true
},
// prettier-ignore
data: Object.keys(counts[0]),
axisLabel:
{
frontSize:12,
interval:0,
rotate:30
}
}
],
yAxis: this.generateyAxis(counts),
series: this.generateSeries2(counts),
};return option;
},
handlerow()
{
this.srow='';
@ -531,14 +328,6 @@ currentDate.setDate(currentDate.getDate()+1);
handleSelectedRow2(value) {
console.log('Selected Row2:', value);
this.srow2=value
if (this.selectedEntity=='emtity4' &&this.srow2.length()>1)
{
this.ISmul4=true;
}
},
handleSelectedRow3(value) {
console.log('Selected Row3:', value);
this.srow3=value
},
handleSelectedChartType(value) {
@ -620,18 +409,7 @@ currentDate.setDate(currentDate.getDate()+1);
});
return counts;
},
generateSeries(source) {
// series
const series = [];
for (let i = 0; i < source.length - 1; i++) {
if (i < 3) {
series.push({ type: 'bar', seriesLayoutBy: 'row' }); // grid series
} else {
series.push({ type: 'bar', xAxisIndex: 1, yAxisIndex: 1 }); // grid series
}
}
return series;
},
drawChart(counts) {
try
{
@ -639,17 +417,8 @@ currentDate.setDate(currentDate.getDate()+1);
this.chartInstance = echarts.init(chartContainer);
let option;
if (!this.entity)
{
if (this.stype === 'bar' || this.stype == 'line') {
option = {
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
xAxis: {
type: 'category',
data: Object.keys(counts),
@ -672,15 +441,6 @@ currentDate.setDate(currentDate.getDate()+1);
} else if (this.stype === 'pie') {
const data = Object.entries(counts).map(([name, value]) => ({ value, name }));
option = {
toolbox: {
show: true,
feature: {
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
series: [{
type: 'pie',
radius: '60%',
@ -689,35 +449,7 @@ currentDate.setDate(currentDate.getDate()+1);
xAxis: { show: false }, //
};
}
}
else{
option = {
legend: {},
tooltip: {},
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
restore: { show: true },
saveAsImage: { show: true }
}
},
dataset: {
source: counts
},
xAxis: [
{ type: 'category', gridIndex: 0 },
{ type: 'category', gridIndex: 1 }
],
yAxis: [{ gridIndex: 0 }, { gridIndex: 1 }],
grid: [{ bottom: '55%' }, { top: '55%' }],
series: this.generateSeries(counts)
};
}
if (this.selectedEntity=='entity4')
{
option=this.generateOptions(counts);
console.log(option)
}
this.chartInstance.setOption(option);
}catch(error)
{
@ -781,16 +513,16 @@ currentDate.setDate(currentDate.getDate()+1);
}
},
handletwodata(srow,srow2) {
handletwodata() {
if (!this.mytable || this.mytable.length === 0) {
alert("没有数据");
} else {
if (!srow || !srow2) {
if (!this.srow || !this.srow2) {
return null;
} else {
const combinedData = this.mytable.map(row => {
if (row && row[srow] !== undefined) {
return [row[srow], row[srow2]];
if (row && row[this.srow] !== undefined) {
return [row[this.srow], row[this.srow2]];
} else {
return [null, null]; //
}
@ -807,7 +539,7 @@ currentDate.setDate(currentDate.getDate()+1);
console.log(this.columns)
try{
this.handledata();
this.handletwodata(this.srow,this.srow2[0]);
this.handletwodata();
} catch(error) {
alert("请选择数据")
}
@ -830,13 +562,20 @@ currentDate.setDate(currentDate.getDate()+1);
const counts=this.countDataByInterval();
setTimeout(()=>this.drawChart(counts),500);
}else if(this.selectedEntity=='entity4'){
let counts=this.do_entity4();
console.log(counts)
if (this.srow2!='entity'){
const counts=this.countsumbystring();
setTimeout(()=>this.drawChart(counts),500);
} else {
const counts=this.countStrings();
setTimeout(()=>this.drawChart(counts),500);
}
}
else if (this.selectedEntity=='entity5'){
const counts=this.count_sum_time();
console.log(counts)
this.hasUpperContent = true;
const counts={}
for (let i = 0; i < this.xz.length; i++) {
counts[this.xz[i]] = this.yz[i];
}
setTimeout(()=>this.drawChart(counts),500);}
else {
this.$message.warning('请选择实体');
@ -847,31 +586,44 @@ currentDate.setDate(currentDate.getDate()+1);
</script>
<style scoped>
.container {
display: grid;
grid-template-columns: 35% 65%;
width: 100%;
height: 80vh;
gap: 10px;
text-align: center
}
.left-grid {
.left-grid, .right-grid {
background-color: #f0f0f0;
border-radius: 2%;
padding: 20px;
height: 100%;
box-sizing: border-box;
}
.right-grid {
display: grid;
grid-template-rows: 600px auto; /* 上半部分固定为600px下半部分自动填充 */
background-color: #e9d7df;
border-radius: 2%;
padding: 20px;
height: 100%;
}
.upper-right {
/* 上半部分样式 */
display: flex;
justify-content: center;
align-items: center;
/* 如果内容溢出,隐藏溢出部分 */
}
.lower-right {
/* 下半部分样式 */
display: flex;
justify-content: center;
align-items: center;
overflow-y: auto; /* 如果内容过多,显示滚动条 */
}
.chart-container {
width: 90%;
height: 90%;
@ -879,8 +631,8 @@ currentDate.setDate(currentDate.getDate()+1);
}
.el-row {
margin-top: 0px;
margin-bottom: 5px;
margin-top: 5px;
margin-bottom: 10px;
}
.demo-select {

View File

@ -1,58 +1,20 @@
<template>
<div style="background-color: #fff; height: 100vh;">
<el-container style="height: 100%; display: flex; flex-direction: column;">
<el-header class="withrawHeader">
<h1 class="headerText">回收站</h1>
</el-header>
<el-main style="flex: 1; overflow: auto;">
<!-- 工具栏 -->
<el-header class="toolbar" style="padding: 10px;">
<el-tooltip class="withdrawToolTip" content="撤销对选中线索的删除">
<el-button class='btnWithdraw' @click="withdrawSelected">
<el-icon><Remove /></el-icon>
</el-button>
</el-tooltip>
<el-tooltip class="deleteToolTip" content="彻底删除选中线索">
<el-button class="btnDelete" @click="deleteSelected">
<el-icon><DeleteFilled /></el-icon>
</el-button>
</el-tooltip>
<!-- 刷新 -->
<el-tooltip class="withdrawToolTip" content="刷新">
<el-button class="btnDelete" @click="refreshData">
<el-icon><RefreshRight /></el-icon>
</el-button>
</el-tooltip>
</el-header>
<el-table
:data="tableData"
style="width: 100%;"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" class="withdrawSelectionCol"></el-table-column>
<el-table :data="tableData" style="width: 100%">
<!-- 动态生成表格列 -->
<el-table-column v-for="column in tableColumns" :key="column.prop" :prop="column.prop" :label="column.label">
<template v-slot="scope">
<span>{{ formatValue(scope.row, column.prop) }}</span>
<span>{{ formatValue(scope.row,column.prop) }}</span>
</template>
</el-table-column>
<!-- 添加删除按钮 -->
<el-table-column label="操作">
<template v-slot:default="scope">
<el-button type="text" @click="withdrawRow(scope.row)">撤销</el-button>
<el-button type="text" @click="deleteClue(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</div>
</template>
<script>
import axios from 'axios';
@ -68,11 +30,43 @@ export default {
{ prop: "table_id", label: "表ID" },
{ prop: "clue_id", label: "线索ID" },
{ prop: "del_time", label: "时间" }
], //
deleteClues:[], //
] //
};
},
methods: {
getDelete() {
//
axios.get('http://localhost:8000/showDelRecords/')
.then(res => {
console.log(res.data)
if(res.data.message=='没有删除记录')
{
return
}
this.tableData = res.data; //
})
.catch(error => {
console.error(error);
});
},
withdrawRow(row) {
const index = this.tableData.indexOf(row);
if (index !== -1) {
// ID
axios.post('http://localhost:8000/withDraw/', { id: row.id })
.then(response => {
console.log('撤销成功:', response.data);
//
this.tableData.splice(index, 1);
})
.catch(error => {
console.error('撤销失败:', error);
});
}
}
},
formatValue(row, prop) {
// type
if (prop === 'type' && row[prop] === '0') {
@ -85,166 +79,12 @@ export default {
return '线索'
return row[prop];
},
getDelete() {
//
axios.get('http://localhost:8000/showDelRecords/').then(res => {
if(res.data.message=='没有删除记录')
{
return
}
this.tableData = res.data.data; // data
})
.catch(error => {
this.$handleNetError(error); //
});
},
withdrawRow(row) {
const index = this.tableData.indexOf(row);
if (index !== -1) {
// ID
axios.post('http://localhost:8000/withDraw/', { id: row.id }).then(response => {
console.log('撤销成功:', response.data);
//
this.tableData.splice(index, 1);
})
.catch(error => {
this.$handleNetError(error);
});
}
},
handleSelectionChange(selection){
this.deleteClues = selection; //
},
//
withdrawSelected(){
//
if(this.deleteClues.length == 0){
this.$message({
type: 'warning',
message: '请选择要撤销的线索'
});
return;
}
for(let i = 0;i < this.deleteClues.length;i++){
this.$axios.post('http://localhost:8000/withDraw/',{ id:this.deleteClues[i].id })
.catch(error => {
this.$handleNetError(error);
return;
});
}
this.$message({
type: 'success',
message: '撤销成功,即将刷新界面'
});
//
location.reload();
},
// 线
deleteClue(row){
const deleteItem = {
table_id: row.table_id,
clue_id: row.clue_id
}
this.$axios.post('http:localhosat:8000/deleteSelected/',{deleteData:deleteItem}).then(response=>{
if(response.data.message == '删除成功'){
//
this.$message({
type: 'success',
message: '删除成功,即将刷新界面'
});
location.reload(); //
}else{
this.$message({
type: 'error',
message: '删除失败'
});
}
})
.catch(error=>{
this.$handleNetError(error); //
})
},
// 线
deleteSelected(){
//
if(this.deleteClues.length == 0){
this.$message({
type: 'warning',
message: '请选择要删除的线索'
});
return;
}
// deleteItems
const deleteItems = this.deleteClues.map(row => ({
table_id: row.table_id, //
clue_id: row.clue_id,
}));
//
for(let i = 0; i < deleteItems.length; i++){
this.$axios.post('http://localhost:8000/deleteSelected/',
{table_id:deleteItems[i].table_id, clue_id:deleteItems[i].clue_id}).then(response=>{
if(response.data.message == '删除成功'){
//
this.$message({
type: 'success',
message: '删除成功'
});
}else{
this.$message({
type: 'error',
message: '删除失败'
});
}
})
.catch(error=>{
this.$handleNetError(error); //
return;
})
}
this.$message({
type: 'success',
message: '删除成功,即将刷新界面'
});
//
location.reload();
},
refreshData(){
location.reload();
}
},
mounted() {
this.getDelete(); //
}
//
};
</script>
<style scoped>
.withdrawSelectionCol{
width: 50px;
}
.headerText{
font-size: 24px;
text-align: center;
}
.toolbar{
height:6%;
padding:2%;
display:flex;
justify-content: flex-end;
align-items: center;
}
.btnDelete, .btnWithdraw{
text-align: start;
padding: 0.6%;
margin: 0;
}
.deleteToolTip, .withdrawToolTip .el-tooltip__content{
color: red !important;
}
<style>
/* 可以添加一些自定义样式 */
</style>

View File

@ -1,4 +1,5 @@
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
transpileDependencies: true,
lintOnSave:false,
})