From 368ec992d89a8f28044209c5e55c179740e68a23 Mon Sep 17 00:00:00 2001 From: chenkainan Date: Tue, 5 Aug 2025 10:40:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 191 ++++++++++-- package.json | 7 +- src/App.vue | 99 +++++-- src/assets/css/common.css | 49 ++++ src/components/common/BackToTop.vue | 72 +++++ src/components/layout/Footer.vue | 149 ++++++++++ src/components/layout/HeaderNav.vue | 372 ++++++++++++++++++++++++ src/components/layout/HomeLayout.vue | 227 +++++++++++++++ src/components/product/ProductList.vue | 191 ++++++++++++ src/main.js | 58 +++- src/router/index.js | 168 +++++++++-- src/store/index.js | 191 +++++++++++- src/views/AboutView.vue | 5 - src/views/Home.vue | 384 +++++++++++++++++++++++++ src/views/HomeView.vue | 18 -- src/views/Index.vue | 88 ++++++ src/views/User/OrderList.vue | 0 src/views/User/UserCenter.vue | 0 vue.config.js | 3 +- 19 files changed, 2178 insertions(+), 94 deletions(-) create mode 100644 src/assets/css/common.css create mode 100644 src/components/common/BackToTop.vue create mode 100644 src/components/layout/Footer.vue create mode 100644 src/components/layout/HeaderNav.vue create mode 100644 src/components/layout/HomeLayout.vue create mode 100644 src/components/product/ProductList.vue delete mode 100644 src/views/AboutView.vue create mode 100644 src/views/Home.vue delete mode 100644 src/views/HomeView.vue create mode 100644 src/views/Index.vue create mode 100644 src/views/User/OrderList.vue create mode 100644 src/views/User/UserCenter.vue diff --git a/package-lock.json b/package-lock.json index 01b457b..82f3ba8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2346,6 +2346,19 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, + "async-validator": { + "version": "1.8.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz", + "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==", + "requires": { + "babel-runtime": "6.x" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", @@ -2366,6 +2379,21 @@ "postcss-value-parser": "^4.2.0" } }, + "axios": { + "version": "1.11.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "babel-helper-vue-jsx-merge-props": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", + "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==" + }, "babel-loader": { "version": "8.4.1", "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.4.1.tgz", @@ -2417,6 +2445,22 @@ "@babel/helper-define-polyfill-provider": "^0.6.5" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + } + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2586,7 +2630,6 @@ "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -2795,6 +2838,14 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", @@ -3195,8 +3246,7 @@ "deepmerge": { "version": "1.5.2", "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" }, "default-gateway": { "version": "6.0.3", @@ -3325,6 +3375,11 @@ "object-keys": "^1.1.1" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", @@ -3448,7 +3503,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "requires": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -3479,6 +3533,19 @@ "integrity": "sha512-SdnWJwSUot04UR51I2oPD8kuP2VI37/CADR1OHsFOUzZIvfWJBO6q11k5P/uKNyTT3cdOsnyjkrZ+DDShqYqJA==", "dev": true }, + "element-ui": { + "version": "2.15.14", + "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.14.tgz", + "integrity": "sha512-2v9fHL0ZGINotOlRIAJD5YuVB8V7WKxrE9Qy7dXhRipa035+kF7WuU/z+tEmLVPBcJ0zt8mOu1DKpWcVzBK8IA==", + "requires": { + "async-validator": "~1.8.1", + "babel-helper-vue-jsx-merge-props": "^2.0.0", + "deepmerge": "^1.2.0", + "normalize-wheel": "^1.0.1", + "resize-observer-polyfill": "^1.5.0", + "throttle-debounce": "^1.0.1" + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3543,14 +3610,12 @@ "es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" }, "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, "es-module-lexer": { "version": "1.7.0", @@ -3562,11 +3627,21 @@ "version": "1.1.1", "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "requires": { "es-errors": "^1.3.0" } }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "escalade": { "version": "3.2.0", "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", @@ -3865,8 +3940,19 @@ "follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==" + }, + "form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + } }, "forwarded": { "version": "0.2.0", @@ -3920,8 +4006,7 @@ "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "gensync": { "version": "1.0.0-beta.2", @@ -3939,7 +4024,6 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "requires": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -3957,7 +4041,6 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "requires": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -4018,8 +4101,7 @@ "gopd": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, "graceful-fs": { "version": "4.2.11", @@ -4060,8 +4142,15 @@ "has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } }, "hash-sum": { "version": "2.0.0", @@ -4073,7 +4162,6 @@ "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "requires": { "function-bind": "^1.1.2" } @@ -4501,6 +4589,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" + }, "js-message": { "version": "1.0.7", "resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz", @@ -4801,8 +4894,7 @@ "math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" }, "mdn-data": { "version": "2.0.14", @@ -4877,14 +4969,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -5122,6 +5212,11 @@ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true }, + "normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5874,6 +5969,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", @@ -6004,6 +6104,11 @@ "regenerate": "^1.4.2" } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, "regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -6078,6 +6183,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "resolve": { "version": "1.22.10", "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz", @@ -6404,6 +6514,11 @@ "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true }, + "shvl": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/shvl/-/shvl-2.0.3.tgz", + "integrity": "sha512-V7C6S9Hlol6SzOJPnQ7qzOVEWUQImt3BNmmzh40wObhla3XOYMe4gGiYzLrJd5TFa+cI2f9LKIRJTTKZSTbWgw==" + }, "side-channel": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", @@ -6803,6 +6918,11 @@ } } }, + "throttle-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz", + "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==" + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz", @@ -6991,6 +7111,11 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "vue-lazyload": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/vue-lazyload/-/vue-lazyload-1.3.3.tgz", + "integrity": "sha512-uHnq0FTEeNmqnbBC2aRKlmtd9LofMZ6Q3mWvgfLa+i9vhxU8fDK+nGs9c1iVT85axSua/AUnMttIq3xPaU9G3A==" + }, "vue-loader": { "version": "17.4.2", "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-17.4.2.tgz", @@ -7066,6 +7191,22 @@ "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz", "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==" }, + "vuex-persistedstate": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/vuex-persistedstate/-/vuex-persistedstate-4.1.0.tgz", + "integrity": "sha512-3SkEj4NqwM69ikJdFVw6gObeB0NHyspRYMYkR/EbhR0hbvAKyR5gksVhtAfY1UYuWUOCCA0QNGwv9pOwdj+XUQ==", + "requires": { + "deepmerge": "^4.2.2", + "shvl": "^2.0.3" + }, + "dependencies": { + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + } + } + }, "watchpack": { "version": "2.4.4", "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.4.tgz", diff --git a/package.json b/package.json index 332cd19..97b3147 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,15 @@ "build": "vue-cli-service build" }, "dependencies": { + "axios": "^1.11.0", "core-js": "^3.8.3", + "element-ui": "^2.15.14", + "js-cookie": "^3.0.5", "vue": "^2.6.14", + "vue-lazyload": "^1.3.3", "vue-router": "^3.5.1", - "vuex": "^3.6.2" + "vuex": "^3.6.2", + "vuex-persistedstate": "^4.1.0" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.0", diff --git a/src/App.vue b/src/App.vue index a97ef37..4a3637f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,32 +1,99 @@ + + diff --git a/src/assets/css/common.css b/src/assets/css/common.css new file mode 100644 index 0000000..85c5135 --- /dev/null +++ b/src/assets/css/common.css @@ -0,0 +1,49 @@ +body, html { + padding: 0; + margin: 0; +} + +div { + box-sizing: border-box; +} + +/*单行隐藏*/ +.text-overflow { + overflow-x: hidden; + overflow-y: inherit; + text-overflow: ellipsis; + white-space: nowrap; +} + +/*两行隐藏,其他行设置-webkit-line-clamp:n */ +.text-overflowRows { + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + word-break: break-all; + display: -webkit-box; + -webkit-box-orient: vertical; +} + +.flex-between { + display: flex; + justify-content: space-between; + align-items: center; +} + +.flex-center { + display: flex; + justify-content: center; + align-items: center; +} + +.flex-around { + display: flex; + justify-content: space-around; + align-items: center; +} + +.flex-column { + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/src/components/common/BackToTop.vue b/src/components/common/BackToTop.vue new file mode 100644 index 0000000..d432d52 --- /dev/null +++ b/src/components/common/BackToTop.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/components/layout/Footer.vue b/src/components/layout/Footer.vue new file mode 100644 index 0000000..a9be141 --- /dev/null +++ b/src/components/layout/Footer.vue @@ -0,0 +1,149 @@ + + + + + \ No newline at end of file diff --git a/src/components/layout/HeaderNav.vue b/src/components/layout/HeaderNav.vue new file mode 100644 index 0000000..cc7647f --- /dev/null +++ b/src/components/layout/HeaderNav.vue @@ -0,0 +1,372 @@ + + + + + diff --git a/src/components/layout/HomeLayout.vue b/src/components/layout/HomeLayout.vue new file mode 100644 index 0000000..c31d8d5 --- /dev/null +++ b/src/components/layout/HomeLayout.vue @@ -0,0 +1,227 @@ + + + + + + \ No newline at end of file diff --git a/src/components/product/ProductList.vue b/src/components/product/ProductList.vue new file mode 100644 index 0000000..4c859ff --- /dev/null +++ b/src/components/product/ProductList.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/main.js b/src/main.js index f253456..0f35aa7 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,64 @@ import Vue from 'vue' -import App from './App.vue' +import App from './App' import router from './router' import store from './store' +import ElementUI from 'element-ui' +import 'element-ui/lib/theme-chalk/index.css' +import axios from 'axios' +import VueLazyload from 'vue-lazyload' +import '@/assets/css/common.css' +// 全局配置 Vue.config.productionTip = false +Vue.use(ElementUI) +Vue.prototype.$http = axios +// 配置图片懒加载 +Vue.use(VueLazyload, { + preLoad: 1.3, // 预加载高度比例 + error: require('./assets/logo.png'), + loading: require('./assets/logo.png'), + attempt: 3, // 增加尝试次数 + listenEvents: ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove'], // 确保监听事件完整 + adapter: { + // 增加加载状态日志 + loaded({ bindType, el, naturalHeight, naturalWidth, $parent, src, loading, error, Init }) { + console.log('图片加载完成:', src) + }, + error({ bindType, el, error, $parent, src, loading }) { + console.log('图片加载失败:', src) + } + } +}) + +// 请求拦截器设置 +axios.interceptors.request.use( + config => { + // 可以在这里添加token等信息 + return config + }, + error => { + return Promise.reject(error) + } +) + +// 响应拦截器设置 +axios.interceptors.response.use( + response => { + return response.data + }, + error => { + // 统一错误处理 + ElementUI.Message.error('请求失败,请稍后重试') + return Promise.reject(error) + } +) + +/* eslint-disable no-new */ new Vue({ + el: '#app', router, store, - render: h => h(App) -}).$mount('#app') + components: { App }, + template: '' +}) diff --git a/src/router/index.js b/src/router/index.js index a395a1f..60d0b55 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,29 +1,153 @@ import Vue from 'vue' -import VueRouter from 'vue-router' -import HomeView from '../views/HomeView.vue' +import Router from 'vue-router' -Vue.use(VueRouter) +Vue.use(Router) -const routes = [ - { - path: '/', - name: 'home', - component: HomeView - }, - { - path: '/about', - name: 'about', - // route level code-splitting - // this generates a separate chunk (about.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue') - } -] - -const router = new VueRouter({ +const router = new Router({ mode: 'history', base: process.env.BASE_URL, - routes + routes: [ + { + path: '/', + name: 'Index', + meta: { + title: '首页 - 精品商城', + keepAlive: false + }, + component: () => import('@/views/Index.vue') + }, + { + path: '/Home', + name: 'Home', + meta: { + title: '首页 - 精品商城', + keepAlive: false + }, + component: () => import('@/views/Home.vue') + }, + // { + // path: '/category/:id?', + // name: 'Category', + // meta: { + // title: '商品分类 - 精品商城', + // keepAlive: false + // }, + // component: () => import('@/views/Category.vue') + // }, + // { + // path: '/product/:id', + // name: 'ProductDetail', + // meta: { + // title: '商品详情 - 精品商城', + // keepAlive: false + // }, + // component: () => import('@/views/ProductDetail.vue') + // }, + // { + // path: '/cart', + // name: 'Cart', + // meta: { + // title: '购物车 - 精品商城', + // requireAuth: true, + // keepAlive: false + // }, + // component: () => import('@/views/Cart.vue') + // }, + // { + // path: '/checkout', + // name: 'Checkout', + // meta: { + // title: '结算 - 精品商城', + // requireAuth: true, + // keepAlive: false + // }, + // component: () => import('@/views/Checkout.vue') + // }, + { + path: '/userCenter', + name: 'UserCenter', + meta: { + title: '个人中心 - 精品商城', + requireAuth: true, + keepAlive: false + }, + component: () => import('@/views/User/UserCenter.vue') + }, + { + path: 'orderList', + name: 'OrderList', + meta: { + title: '我的订单 - 精品商城', + requireAuth: true, + keepAlive: false + }, + component: () => import('@/views/User/OrderList.vue') + }, + // { + // path: '/user/orders/:id', + // name: 'OrderDetail', + // meta: { + // title: '订单详情 - 精品商城', + // requireAuth: true, + // keepAlive: false + // }, + // component: () => import('@/views/OrderDetail.vue') + // }, + // { + // path: '/login', + // name: 'Login', + // meta: { + // title: '登录 - 精品商城', + // keepAlive: false + // }, + // component: () => import('@/views/Login.vue') + // }, + // { + // path: '/register', + // name: 'Register', + // meta: { + // title: '注册 - 精品商城', + // keepAlive: false + // }, + // component: () => import('@/views/Register.vue') + // }, + // { + // path: '*', + // name: 'NotFound', + // meta: { + // title: '页面不存在 - 精品商城', + // keepAlive: false + // }, + // component: () => import('@/views/NotFound.vue') + // } + ], + scrollBehavior(to, from, savedPosition) { + // 页面滚动到顶部 + return { x: 0, y: 0 } + } +}) + +// 路由守卫 +router.beforeEach((to, from, next) => { + // 设置页面标题 + if (to.meta.title) { + document.title = to.meta.title + } + + // 验证登录状态 + if (to.meta.requireAuth) { + const token = localStorage.getItem('token') + if (token) { + next() + } else { + next({ + path: '/login', + query: { redirect: to.fullPath } + }) + } + } else { + next() + } }) -export default router +export default router \ No newline at end of file diff --git a/src/store/index.js b/src/store/index.js index ceffa8e..b8b4198 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,17 +1,202 @@ import Vue from 'vue' import Vuex from 'vuex' +import createPersistedState from 'vuex-persistedstate' Vue.use(Vuex) export default new Vuex.Store({ + plugins: [ + createPersistedState({ + storage: window.localStorage, + reducer(val) { + return { + // 只持久化需要的状态 + cart: val.cart, + user: val.user + } + } + }) + ], state: { - }, - getters: { + // 购物车状态 + cart: { + items: [], // 购物车商品列表 + totalCount: 0, // 商品总数 + totalPrice: 0 // 商品总价 + }, + // 用户状态 + user: { + isLogin: false, + info: null, + token: '' + }, + // 分类数据 + categories: [], + // 全局加载状态 + loading: false }, mutations: { + // 更新分类数据 + UPDATE_CATEGORIES(state, categories) { + state.categories = categories + }, + + // 更新加载状态 + UPDATE_LOADING(state, status) { + state.loading = status + }, + + // 用户登录 + USER_LOGIN(state, { userInfo, token }) { + state.user.isLogin = true + state.user.info = userInfo + state.user.token = token + localStorage.setItem('token', token) + }, + + // 用户登出 + USER_LOGOUT(state) { + state.user.isLogin = false + state.user.info = null + state.user.token = '' + localStorage.removeItem('token') + }, + + // 添加商品到购物车 + ADD_TO_CART(state, product) { + const existingItem = state.cart.items.find(item => item.id === product.id) + + if (existingItem) { + existingItem.quantity += product.quantity || 1 + } else { + state.cart.items.push({ + ...product, + quantity: product.quantity || 1 + }) + } + + this.commit('UPDATE_CART_TOTAL') + }, + + // 从购物车移除商品 + REMOVE_FROM_CART(state, productId) { + state.cart.items = state.cart.items.filter(item => item.id !== productId) + this.commit('UPDATE_CART_TOTAL') + }, + + // 更新购物车商品数量 + UPDATE_CART_ITEM_QUANTITY(state, { productId, quantity }) { + const item = state.cart.items.find(item => item.id === productId) + if (item) { + item.quantity = quantity + this.commit('UPDATE_CART_TOTAL') + } + }, + + // 清空购物车 + CLEAR_CART(state) { + state.cart.items = [] + this.commit('UPDATE_CART_TOTAL') + }, + + // 更新购物车总计 + UPDATE_CART_TOTAL(state) { + state.cart.totalCount = state.cart.items.reduce((total, item) => { + return total + item.quantity + }, 0) + + state.cart.totalPrice = state.cart.items.reduce((total, item) => { + return total + (item.price * item.quantity) + }, 0) + } }, actions: { + // 获取分类数据 + fetchCategories({ commit }) { + commit('UPDATE_LOADING', true) + // 模拟API请求 + return new Promise(resolve => { + setTimeout(() => { + const categories = [ + { id: 1, name: '电子产品', icon: 'el-icon-laptop' }, + { id: 2, name: '服装鞋帽', icon: 'el-icon-shopping-bag-1' }, + { id: 3, name: '家居用品', icon: 'el-icon-home' }, + { id: 4, name: '美妆个护', icon: 'el-icon-present' }, + { id: 5, name: '食品饮料', icon: 'el-icon-dish' }, + { id: 6, name: '图书音像', icon: 'el-icon-document' } + ] + commit('UPDATE_CATEGORIES', categories) + commit('UPDATE_LOADING', false) + resolve(categories) + }, 500) + }) + }, + + // 用户登录 + login({ commit }, { username, password }) { + commit('UPDATE_LOADING', true) + // 模拟登录API请求 + return new Promise((resolve, reject) => { + setTimeout(() => { + if (username === 'test' && password === '123456') { + const userInfo = { id: 1, username: 'test', avatar: 'https://picsum.photos/200' } + const token = 'fake-token-123456' + commit('USER_LOGIN', { userInfo, token }) + commit('UPDATE_LOADING', false) + resolve(userInfo) + } else { + commit('UPDATE_LOADING', false) + reject(new Error('用户名或密码错误')) + } + }, 1000) + }) + }, + + // 用户登出 + logout({ commit }) { + commit('USER_LOGOUT') + }, + + // 添加商品到购物车 + addToCart({ commit }, product) { + commit('ADD_TO_CART', product) + }, + + // 从购物车移除商品 + removeFromCart({ commit }, productId) { + commit('REMOVE_FROM_CART', productId) + }, + + // 更新购物车商品数量 + updateCartItemQuantity({ commit }, payload) { + commit('UPDATE_CART_ITEM_QUANTITY', payload) + }, + + // 清空购物车 + clearCart({ commit }) { + commit('CLEAR_CART') + } }, - modules: { + getters: { + // 获取分类列表 + getCategories: state => state.categories, + + // 获取购物车信息 + getCart: state => state.cart, + + // 获取购物车商品总数 + getCartTotalCount: state => state.cart.totalCount, + + // 获取购物车商品总价 + getCartTotalPrice: state => state.cart.totalPrice, + + // 获取用户登录状态 + isUserLogin: state => state.user.isLogin, + + // 获取用户信息 + getUserInfo: state => state.user.info, + + // 获取加载状态 + getLoadingStatus: state => state.loading } }) diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue deleted file mode 100644 index 3fa2807..0000000 --- a/src/views/AboutView.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 0000000..d0d2430 --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,384 @@ + + + + + + diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue deleted file mode 100644 index e8d96d7..0000000 --- a/src/views/HomeView.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/src/views/Index.vue b/src/views/Index.vue new file mode 100644 index 0000000..91a086d --- /dev/null +++ b/src/views/Index.vue @@ -0,0 +1,88 @@ + + + + + \ No newline at end of file diff --git a/src/views/User/OrderList.vue b/src/views/User/OrderList.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/views/User/UserCenter.vue b/src/views/User/UserCenter.vue new file mode 100644 index 0000000..e69de29 diff --git a/vue.config.js b/vue.config.js index 910e297..fe86d76 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,4 +1,5 @@ const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ - transpileDependencies: true + transpileDependencies: true, + runtimeCompiler: true })