diff --git a/package-lock.json b/package-lock.json index 88ef9f6..db77b94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,11 @@ "version": "0.0.0", "dependencies": { "@element-plus/icons-vue": "^2.3.2", + "axios": "^1.18.0", + "element-china-area-data": "^6.1.0", "element-plus": "^2.14.1", - "vue": "^3.5.34" + "vue": "^3.5.34", + "vue-router": "4" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.6", @@ -549,6 +552,12 @@ "@vue/shared": "3.5.35" } }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, "node_modules/@vue/reactivity": { "version": "3.5.35", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.35.tgz", @@ -637,12 +646,73 @@ "vue": "^3.5.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/china-division": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/china-division/-/china-division-2.7.0.tgz", + "integrity": "sha512-4uUPAT+1WfqDh5jytq7omdCmHNk3j+k76zEG/2IqaGcYB90c2SwcixttcypdsZ3T/9tN1TTpBDoeZn+Yw/qBEA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -655,6 +725,32 @@ "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", "license": "MIT" }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -665,6 +761,29 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/element-china-area-data": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/element-china-area-data/-/element-china-area-data-6.1.0.tgz", + "integrity": "sha512-IkpcjwQv2A/2AxFiSoaISZ+oMw1rZCPUSOg5sOCwT5jKc96TaawmKZeY81xfxXsO0QbKxU5LLc6AirhG52hUmg==", + "license": "MIT", + "dependencies": { + "china-division": "^2.7.0" + } + }, "node_modules/element-plus": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.14.1.tgz", @@ -703,6 +822,51 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -727,6 +891,42 @@ } } }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -742,6 +942,116 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -1035,12 +1345,48 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", "license": "MIT" }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -1112,6 +1458,15 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/rolldown": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", @@ -1284,6 +1639,21 @@ "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.3.tgz", "integrity": "sha512-x4nsFpy5Pe8fqPzp/5vkTPeTTDBpAx4WVtV47Ejt0+2FQrq4pRRsJs7JmYRqMFzTu/LW+pCWEjQ3YVCkPV7f9g==", "license": "MIT" + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } } } } diff --git a/package.json b/package.json index 299ca56..86ce356 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.3.2", + "axios": "^1.18.0", "element-china-area-data": "^6.1.0", "element-plus": "^2.14.1", "vue": "^3.5.34", diff --git a/src/api/afterSales.js b/src/api/afterSales.js new file mode 100644 index 0000000..b59c6b9 --- /dev/null +++ b/src/api/afterSales.js @@ -0,0 +1,22 @@ +// api/afterSales.js —— 售后管理接口 +import request from '../utils/request' + +export function getAfterSalesList(params) { + return request.get('/after-sales', {params}) +} + +export function getAfterSalesDetail(id) { + return request.get(`/after-sales/${id}`) +} + +export function createAfterSales(data) { + return request.post('/after-sales', data) +} + +export function updateAfterSales(id, data) { + return request.put(`/after-sales/${id}`, data) +} + +export function deleteAfterSales(id) { + return request.delete(`/after-sales/${id}`) +} diff --git a/src/api/contract.js b/src/api/contract.js new file mode 100644 index 0000000..f3c57e0 --- /dev/null +++ b/src/api/contract.js @@ -0,0 +1,22 @@ +// api/contract.js —— 合同管理接口 +import request from '../utils/request' + +export function getContractList(params) { + return request.get('/contracts', {params}) +} + +export function getContractDetail(id) { + return request.get(`/contracts/${id}`) +} + +export function createContract(data) { + return request.post('/contracts', data) +} + +export function updateContract(id, data) { + return request.put(`/contracts/${id}`, data) +} + +export function deleteContract(id) { + return request.delete(`/contracts/${id}`) +} diff --git a/src/api/customer.js b/src/api/customer.js new file mode 100644 index 0000000..ace2f5a --- /dev/null +++ b/src/api/customer.js @@ -0,0 +1,22 @@ +// api/customer.js —— 客户管理接口 +import request from '../utils/request' + +export function getCustomerList(params) { + return request.get('/customers', {params}) +} + +export function getCustomerDetail(id) { + return request.get(`/customers/${id}`) +} + +export function createCustomer(data) { + return request.post('/customers', data) +} + +export function updateCustomer(id, data) { + return request.put(`/customers/${id}`, data) +} + +export function deleteCustomer(id) { + return request.delete(`/customers/${id}`) +} diff --git a/src/api/employee.js b/src/api/employee.js new file mode 100644 index 0000000..5135776 --- /dev/null +++ b/src/api/employee.js @@ -0,0 +1,22 @@ +// api/employee.js —— 员工管理接口 +import request from '../utils/request' + +export function getEmployeeList(params) { + return request.get('/employees', {params}) +} + +export function getEmployeeDetail(id) { + return request.get(`/employees/${id}`) +} + +export function createEmployee(data) { + return request.post('/employees', data) +} + +export function updateEmployee(id, data) { + return request.put(`/employees/${id}`, data) +} + +export function deleteEmployee(id) { + return request.delete(`/employees/${id}`) +} diff --git a/src/api/product.js b/src/api/product.js new file mode 100644 index 0000000..73a332d --- /dev/null +++ b/src/api/product.js @@ -0,0 +1,22 @@ +// api/product.js —— 产品管理接口 +import request from '../utils/request' + +export function getProductList(params) { + return request.get('/products', {params}) +} + +export function getProductDetail(id) { + return request.get(`/products/${id}`) +} + +export function createProduct(data) { + return request.post('/products', data) +} + +export function updateProduct(id, data) { + return request.put(`/products/${id}`, data) +} + +export function deleteProduct(id) { + return request.delete(`/products/${id}`) +} diff --git a/src/api/user.js b/src/api/user.js new file mode 100644 index 0000000..9b02352 --- /dev/null +++ b/src/api/user.js @@ -0,0 +1,43 @@ +// api/user.js —— 用户相关接口 +import request from '../utils/request' + +// 登录 +export function login(data) { + return request.post('/user/login', data) +} + +// 获取当前用户信息 +export function getUserInfo() { + return request.get('/user/info') +} + +// 登出 +export function logout() { + return request.post('/user/logout') +} + +// 修改密码 +export function changePassword(data) { + return request.put('/user/password', data) +} + +// ========== 用户管理 CRUD(管理员) ========== +export function getUserList(params) { + return request.get('/users', {params}) +} + +export function getUserDetail(id) { + return request.get(`/users/${id}`) +} + +export function createUser(data) { + return request.post('/users', data) +} + +export function updateUser(id, data) { + return request.put(`/users/${id}`, data) +} + +export function deleteUser(id) { + return request.delete(`/users/${id}`) +} diff --git a/src/components/Login.vue b/src/components/Login.vue index 782cecb..e04e275 100644 --- a/src/components/Login.vue +++ b/src/components/Login.vue @@ -67,6 +67,7 @@ import {reactive, ref} from 'vue' import {ElMessage} from 'element-plus' import {Lock, User} from '@element-plus/icons-vue' import {useRouter} from 'vue-router' +import {login} from '../api/user' const router = useRouter() @@ -93,11 +94,22 @@ const handleLogin = async () => { try { await loginFormRef.value.validate() loading.value = true - await new Promise((r) => setTimeout(r, 800)) - ElMessage.success('登录成功(模拟)') + const res = await login({ + username: loginForm.username, + password: loginForm.password, + }) + // 保存 token 和用户信息 + localStorage.setItem('token', res.data.token) + localStorage.setItem('userInfo', JSON.stringify(res.data.userInfo)) + if (loginForm.remember) { + localStorage.setItem('rememberUser', loginForm.username) + } else { + localStorage.removeItem('rememberUser') + } + ElMessage.success('登录成功') router.push('/panel') } catch { - // 校验失败,element-plus 会自动显示红色提示 + // 校验失败或 API 错误,拦截器已弹提示 } finally { loading.value = false } diff --git a/src/components/contract.vue b/src/components/contract.vue index cc0df13..8f07d2f 100644 --- a/src/components/contract.vue +++ b/src/components/contract.vue @@ -1,196 +1,277 @@ + + - - \ No newline at end of file +.page-container { + background: #fff; + padding: 20px; + border-radius: 8px; +} +.search-bar { + display: flex; + gap: 10px; + margin-bottom: 16px; + flex-wrap: wrap; + align-items: center; +} +.pagination-bar { + margin-top: 16px; + display: flex; + justify-content: flex-end; +} + diff --git a/src/components/customer.vue b/src/components/customer.vue index 4c6a2ce..83fff09 100644 --- a/src/components/customer.vue +++ b/src/components/customer.vue @@ -1,149 +1,268 @@ - - - \ No newline at end of file +// 搜索 +const search = reactive({name: '', phone: '', customer_type: ''}) +const loading = ref(false) +const tableData = ref([]) +const pagination = reactive({page: 1, pageSize: 10, total: 0}) + +// 弹窗 +const dialogVisible = ref(false) +const isEdit = ref(false) +const editId = ref(null) +const submitLoading = ref(false) +const formRef = ref(null) + +const form = reactive({ + name: '', phone: '', region: [], address: '', email: '', customer_type: 'Normal', remark: '', +}) + +const rules = { + name: [{required: true, message: '请输入客户姓名', trigger: 'blur'}], +} + +// 获取列表 +const fetchList = async () => { + loading.value = true + try { + const params = { + page: pagination.page, + pageSize: pagination.pageSize, + ...search, + } + // 清空空值 + Object.keys(params).forEach(k => { if (!params[k]) delete params[k] }) + const res = await getCustomerList(params) + tableData.value = res.data.list + pagination.total = res.data.total + } catch {} finally { + loading.value = false + } +} + +const handleSearch = () => { + pagination.page = 1 + fetchList() +} + +const resetSearch = () => { + search.name = '' + search.phone = '' + search.customer_type = '' + handleSearch() +} + +// 打开新增 +const openAdd = () => { + isEdit.value = false + editId.value = null + Object.assign(form, {name: '', phone: '', region: [], address: '', email: '', customer_type: 'Normal', remark: ''}) + dialogVisible.value = true +} + +// 打开编辑 +const openEdit = (row) => { + isEdit.value = true + editId.value = row.id + Object.assign(form, { + name: row.name || '', + phone: row.phone || '', + region: [], + address: row.address || '', + email: row.email || '', + customer_type: row.customer_type || 'Normal', + remark: row.remark || '', + }) + dialogVisible.value = true +} + +// 提交 +const handleSubmit = async () => { + if (!formRef.value) return + await formRef.value.validate() + submitLoading.value = true + try { + // 从 region cascader 拆出省市区 + const [province, city, district] = form.region + const payload = { + name: form.name, + phone: form.phone || null, + province: province || null, + city: city || null, + district: district || null, + address: form.address || null, + email: form.email || null, + customer_type: form.customer_type, + remark: form.remark || null, + } + if (isEdit.value) { + await updateCustomer(editId.value, payload) + ElMessage.success('更新成功') + } else { + await createCustomer(payload) + ElMessage.success('新增成功') + } + dialogVisible.value = false + fetchList() + } catch {} finally { + submitLoading.value = false + } +} + +// 删除 +const handleDelete = async (id) => { + try { + await ElMessageBox.confirm('确定删除该客户?', '提示', {type: 'warning'}) + await deleteCustomer(id) + ElMessage.success('删除成功') + fetchList() + } catch {} +} + +onMounted(() => { + fetchList() +}) + + + diff --git a/src/components/employee.vue b/src/components/employee.vue new file mode 100644 index 0000000..a8a53a7 --- /dev/null +++ b/src/components/employee.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/src/components/panel.vue b/src/components/panel.vue index 689e792..8bdad2f 100644 --- a/src/components/panel.vue +++ b/src/components/panel.vue @@ -1,13 +1,42 @@