上传代码
24
CampusExpressDelivery/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
5
CampusExpressDelivery/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Vue 3 + TypeScript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
27
CampusExpressDelivery/SSL/xiaokuaisong.shop.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEA7gB1IUC1Utw3ghZ3Do2VJaBC+vAJUapVPCm4UuBZBvjziMnU
|
||||
feqhe1OPAkwUC1CDtuh5+xacknsheY6CrdfOV5qkMqCvg4opavcCWuj9d5wppO1U
|
||||
oBjsbYNUslYzwq2F3X0/N1sFUOQM56V69fIY+Kedos6FHsZD/ErX7yhDBY4H4Se2
|
||||
Q5NQjL12eWVys3Jn07ATTTAfVbsewJAxeMh58j51kVU0XhijemuibvtgiCSKMa4J
|
||||
TUM2+tldxC9Xfb4Et3xFTWdAJnp945oqWAzoDa9YszNGYJrs3TFJKsCxuXe8wBBT
|
||||
4iRLb+hcyVm8Wekax04HmJhl1NZhT+pg7mHnoQIDAQABAoIBAAQrkEHVdrvhgYw7
|
||||
KSnBTbPFoqjPkgU7HCBYTYtPtKWicO90lF9isCLHXngMhdUjK3Sl7wW5EiQfqdDt
|
||||
wCDMSUh4DGCZ98tQ7Vv7QSB/SLoq24CxGyCNQT7DvGUdzS1AAbqFWFlHpDCkN0zr
|
||||
hYuXyuvX8YNV1aep8wzhkZYmXSLErztMiFUvUYscIqQLkuVO8c0ydiA1ALPhvtB2
|
||||
Sv6PrEHeXMvi8ESTh/BMxrCHZZrDDodCMh0goY212UCAhBY/CG2z15s1GmgjdENt
|
||||
Fh88Ic5ZUTLq5BRM3tDRlErb/6/9lQLPxpfExPKC4eOyKHMpGvvPrzQUEWaUSlu2
|
||||
rzI6uQECgYEA/32Q7mYmvkIoAUmNPi7f8G65NKTVi6eUhkrbVKUksx78dqLg2Ay1
|
||||
156YJwA+VFdwnw3OkMlJYIhXXF7wQ6MvFB21wXkEkMQj/J/l3f/LoeVrR+Md2lyF
|
||||
M3P04zWkQoCRdTz9L3U08szlk7bj4RJxbLYxJ/0jJcO5H8afN1BkOSECgYEA7nn2
|
||||
h7jwvEZkTN1sAsYROQKssxBhZYQ4+M4wJ+QdGB4t6KNbO2PH+l1U8Mg2yFq++QRq
|
||||
uP9Q+qr89oTUYggmXzGseV5SeArMA5VN7py5Jg8L8eJGVEXALLXaC3ywTNY33A2C
|
||||
ff55HT7TRDoI638T4k7iYJ1VkfaDsexEgi8HXoECgYBK2H8fx98rt3e+wMxW3iaO
|
||||
afFpwawpaGNzX/SW/HYe30H4g0i5IigXTYenTUP1M1Rz0/iio8USOX7WOZ3LQr/k
|
||||
9bssPYaf3kXomPMfMPN3rxzZh2hUcuw2oY6pDSrcrItwO/iz8XMceff7aQWjBuMh
|
||||
hNIrs9WbF5Zg/6/e5Xcm4QKBgCAM9D05deFX9JMAD0wwIpBu85b9VJm4M4/85iv2
|
||||
VJKxO6pQiippNq9Ha+sQfYxf5drB5TYH2nJWGLlpEMI8JiwVGQEW1C6eBN1Wa6ru
|
||||
FVQwIYLYzmr1FObtaeixUWCCSe+hQTB9yvlLQEmjIx/DbIC16WbivmVnpDt9bZex
|
||||
imQBAoGARrA+XSwSytsdeM1JTIBwOhS8IprraxfVqhaqg7zneypy54Q3V9+inVeK
|
||||
rvVmEazUVtZsTg/J3uKxHv+LX+mFdwAV8lDElz/p1K1stMfsSUnNKLLDmRjrN586
|
||||
RBcp36sTnMVYikffNqxfowzymmvrJAKOny3sovZICzPkgzoPTm8=
|
||||
-----END RSA PRIVATE KEY-----
|
62
CampusExpressDelivery/SSL/xiaokuaisong.shop.pem
Normal file
@ -0,0 +1,62 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGEjCCBPqgAwIBAgIQBbg2EGUqRzMeBv4XlQPfPzANBgkqhkiG9w0BAQsFADBu
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
|
||||
RFYgVExTIENBIC0gRzIwHhcNMjUwMzEzMDAwMDAwWhcNMjUwNjEwMjM1OTU5WjAc
|
||||
MRowGAYDVQQDExF4aWFva3VhaXNvbmcuc2hvcDCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggEPADCCAQoCggEBAO4AdSFAtVLcN4IWdw6NlSWgQvrwCVGqVTwpuFLgWQb484jJ
|
||||
1H3qoXtTjwJMFAtQg7boefsWnJJ7IXmOgq3XzleapDKgr4OKKWr3Alro/XecKaTt
|
||||
VKAY7G2DVLJWM8Kthd19PzdbBVDkDOelevXyGPinnaLOhR7GQ/xK1+8oQwWOB+En
|
||||
tkOTUIy9dnllcrNyZ9OwE00wH1W7HsCQMXjIefI+dZFVNF4Yo3prom77YIgkijGu
|
||||
CU1DNvrZXcQvV32+BLd8RU1nQCZ6feOaKlgM6A2vWLMzRmCa7N0xSSrAsbl3vMAQ
|
||||
U+IkS2/oXMlZvFnpGsdOB5iYZdTWYU/qYO5h56ECAwEAAaOCAvwwggL4MB8GA1Ud
|
||||
IwQYMBaAFHjfkZBf7t6s9sV169VMVVPvJEq2MB0GA1UdDgQWBBQXPuvYOoWcOMyK
|
||||
b3LR/m5M+SEqOjAzBgNVHREELDAqghF4aWFva3VhaXNvbmcuc2hvcIIVd3d3Lnhp
|
||||
YW9rdWFpc29uZy5zaG9wMD4GA1UdIAQ3MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUH
|
||||
AgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAw
|
||||
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGABggrBgEFBQcBAQR0MHIw
|
||||
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBKBggrBgEFBQcw
|
||||
AoY+aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0VuY3J5cHRpb25FdmVyeXdo
|
||||
ZXJlRFZUTFNDQS1HMi5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIE
|
||||
ggFvBIIBawFpAHcATnWjJ1yaEMM4W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGV
|
||||
jmc97gAABAMASDBGAiEAoYWQ8iavGTLIH4jqUngz50C0ZjZAnlTxgg8/YwjsQUoC
|
||||
IQDgojkRl8fgVYI3jC0u/n8MNQEnoKTJI8Y9q3cAsm0+XgB3AHMgIg8IFor588Sm
|
||||
iwqyappKAO71d4WKCE0FANSlQkRZAAABlY5nPhAAAAQDAEgwRgIhAPR2D8STMyua
|
||||
aO386zeiuK50P3zUM7hXC6hkrRTq6HJaAiEAhNZWFG2XG93jldcd76I+o74Xl/3i
|
||||
OS+6IgavCD15cYQAdQDm0jFjQHeMwRBBBtdxuc7B0kD2loSG+7qHMh39HjeOUAAA
|
||||
AZWOZz4gAAAEAwBGMEQCIBDSrtuoMLTcOXWkLUd2wE1b/rOyJhrOpNzuyVSjiJl8
|
||||
AiA+lA9UqElkIXJ7dVbv6+9Y3OviuCpFlhcL0HChF+C0gzANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEA0CZyVm1PtZh5EZoMu0vheFjgEeefq2qvqU5b0/aQaCXnLnBu694tBlL2
|
||||
YZz+L0Q2wnzjBMczoJFBROEyauvHT4rtq/xkyUOtLl9XB4jD+H0pNWwJ1m69m9ED
|
||||
7Tqam3PKTc4k7ICLRZtLTHk/3hW0EuAYpf8Ncm2Bqr8RHGVkQ4+5TyVuK3TzDrtG
|
||||
ICX1+k8JQxupEWHzmZkcCf5qd1m+yv/qzkCQ2bqe48zFqMx+1Nw2mc82VBp+TXup
|
||||
Gk9rNNStjj7+pDYNGBQDR35WXKgy1Nq8npqMLCZcFHLMld9hCfoRkjoYiINbCqBM
|
||||
dpfu6Ss9Ap9isZv9IqW33n0WY/8HVw==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqjCCA5KgAwIBAgIQDeD/te5iy2EQn2CMnO1e0zANBgkqhkiG9w0BAQsFADBh
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
|
||||
MjAeFw0xNzExMjcxMjQ2NDBaFw0yNzExMjcxMjQ2NDBaMG4xCzAJBgNVBAYTAlVT
|
||||
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
|
||||
MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO8Uf46i/nr7pkgTDqnE
|
||||
eSIfCFqvPnUq3aF1tMJ5hh9MnO6Lmt5UdHfBGwC9Si+XjK12cjZgxObsL6Rg1njv
|
||||
NhAMJ4JunN0JGGRJGSevbJsA3sc68nbPQzuKp5Jc8vpryp2mts38pSCXorPR+sch
|
||||
QisKA7OSQ1MjcFN0d7tbrceWFNbzgL2csJVQeogOBGSe/KZEIZw6gXLKeFe7mupn
|
||||
NYJROi2iC11+HuF79iAttMc32Cv6UOxixY/3ZV+LzpLnklFq98XORgwkIJL1HuvP
|
||||
ha8yvb+W6JislZJL+HLFtidoxmI7Qm3ZyIV66W533DsGFimFJkz3y0GeHWuSVMbI
|
||||
lfsCAwEAAaOCAU8wggFLMB0GA1UdDgQWBBR435GQX+7erPbFdevVTFVT7yRKtjAf
|
||||
BgNVHSMEGDAWgBROIlQgGJXm427mD/r6uRLtBhePOTAOBgNVHQ8BAf8EBAMCAYYw
|
||||
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
|
||||
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
|
||||
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
|
||||
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
|
||||
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAoBs1eCLKakLtVRPFRjBIJ9LJ
|
||||
L0s8ZWum8U8/1TMVkQMBn+CPb5xnCD0GSA6L/V0ZFrMNqBirrr5B241OesECvxIi
|
||||
98bZ90h9+q/X5eMyOD35f8YTaEMpdnQCnawIwiHx06/0BfiTj+b/XQih+mqt3ZXe
|
||||
xNCJqKexdiB2IWGSKcgahPacWkk/BAQFisKIFYEqHzV974S3FAz/8LIfD58xnsEN
|
||||
GfzyIDkH3JrwYZ8caPTf6ZX9M1GrISN8HnWTtdNCH2xEajRa/h9ZBXjUyFKQrGk2
|
||||
n2hcLrfZSbynEC/pSw/ET7H5nWwckjmAJ1l9fcnbqkU/pf6uMQmnfl0JQjJNSg==
|
||||
-----END CERTIFICATE-----
|
10
CampusExpressDelivery/auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
51
CampusExpressDelivery/components.d.ts
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
||||
ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACard: typeof import('ant-design-vue/es')['Card']
|
||||
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
||||
ADescriptions: typeof import('ant-design-vue/es')['Descriptions']
|
||||
ADescriptionsItem: typeof import('ant-design-vue/es')['DescriptionsItem']
|
||||
ADivider: typeof import('ant-design-vue/es')['Divider']
|
||||
ADrawer: typeof import('ant-design-vue/es')['Drawer']
|
||||
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
||||
AEmpty: typeof import('ant-design-vue/es')['Empty']
|
||||
AForm: typeof import('ant-design-vue/es')['Form']
|
||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||
AImage: typeof import('ant-design-vue/es')['Image']
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
|
||||
ALayout: typeof import('ant-design-vue/es')['Layout']
|
||||
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
||||
ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
|
||||
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
|
||||
AList: typeof import('ant-design-vue/es')['List']
|
||||
AListItem: typeof import('ant-design-vue/es')['ListItem']
|
||||
AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta']
|
||||
AMenu: typeof import('ant-design-vue/es')['Menu']
|
||||
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
|
||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
|
||||
ATable: typeof import('ant-design-vue/es')['Table']
|
||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
}
|
BIN
CampusExpressDelivery/dist.zip
Normal file
13
CampusExpressDelivery/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>校快送</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
3952
CampusExpressDelivery/package-lock.json
generated
Normal file
30
CampusExpressDelivery/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "campusexpressdelivery",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.7.7",
|
||||
"echarts": "^5.6.0",
|
||||
"element-plus": "^2.8.8",
|
||||
"pinia": "^2.2.6",
|
||||
"pinia-plugin-persistedstate": "^4.1.3",
|
||||
"vue": "^3.5.12",
|
||||
"vue-router": "^4.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"sass-embedded": "^1.81.0",
|
||||
"typescript": "~5.6.2",
|
||||
"unplugin-auto-import": "^0.18.5",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite": "^5.4.10",
|
||||
"vue-tsc": "^2.1.8"
|
||||
}
|
||||
}
|
1
CampusExpressDelivery/public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
13
CampusExpressDelivery/src/App.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<a-config-provider :locale="zhCN">
|
||||
<router-view/>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import zhCN from "ant-design-vue/es/locale/zh_CN";
|
||||
import dayjs from 'dayjs';
|
||||
import 'dayjs/locale/zh-cn';
|
||||
|
||||
dayjs.locale('zh-cn');
|
||||
</script>
|
31
CampusExpressDelivery/src/api/myAxios.ts
Normal file
@ -0,0 +1,31 @@
|
||||
// 创建实例时配置默认值
|
||||
import axios from "axios";
|
||||
import router from "../router";
|
||||
|
||||
//const viteEnv = import.meta.env;
|
||||
|
||||
const myAxios = axios.create({
|
||||
withCredentials: true,
|
||||
//baseURL:'http://39.101.78.35:6271/api'
|
||||
// baseURL:'http://localhost:9999'
|
||||
// baseURL:'http://39.101.78.35:6445/api'
|
||||
// baseURL:'https://xiaokuaisong.shop:6448/api'
|
||||
baseURL:'https://xiaokuaisong.shop/api'
|
||||
});
|
||||
|
||||
myAxios.interceptors.request.use(function (config) {
|
||||
return config;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
myAxios.interceptors.response.use(function (response: any) {
|
||||
if (response.data.code === 40100) {
|
||||
router.replace('/')
|
||||
}
|
||||
return response.data;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default myAxios;
|
BIN
CampusExpressDelivery/src/assets/background.png
Normal file
After Width: | Height: | Size: 4.8 MiB |
BIN
CampusExpressDelivery/src/assets/login/bgi.jpg
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
CampusExpressDelivery/src/assets/login/hidePassword.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
CampusExpressDelivery/src/assets/login/image.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
CampusExpressDelivery/src/assets/login/showPassword.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
CampusExpressDelivery/src/assets/logo.png
Normal file
After Width: | Height: | Size: 20 KiB |
48
CampusExpressDelivery/src/layout/ManageLayout.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div id="manage">
|
||||
<a-layout has-sider>
|
||||
<a-layout-sider :style="{ width: '200px' }">
|
||||
<ManageSidebar/>
|
||||
</a-layout-sider>
|
||||
<a-layout>
|
||||
<a-layout-header :style="{ background: '#fff', padding: 0}">
|
||||
<ManageHeader/>
|
||||
</a-layout-header>
|
||||
<a-layout-content class="main">
|
||||
<router-view :key="key" class="main-card"/>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ManageHeader from "./manage/ManageHeader.vue";
|
||||
import ManageSidebar from "./manage/ManageSidebar.vue";
|
||||
import {useRoute} from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const key = () => {
|
||||
return route.path + Math.random();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
#manage {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
flex: 1;
|
||||
flex-basis: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
</style>
|
171
CampusExpressDelivery/src/layout/manage/ManageHeader.vue
Normal file
@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<div class="manage-header">
|
||||
<div class="header-left">
|
||||
<a-breadcrumb class="breadcrumb">
|
||||
<a-breadcrumb-item>校快送后台管理系统</a-breadcrumb-item>
|
||||
<a-breadcrumb-item class="routeName">{{ route.name }}</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<!-- <div class="bell">-->
|
||||
<!-- <BellTwoTone/>-->
|
||||
<!-- </div>-->
|
||||
<div class="name">
|
||||
{{ store.loginUser.userRole === "notLogin" ? '未登录' : store.loginUser.userRole }}
|
||||
</div>
|
||||
<div class="user">
|
||||
<a-dropdown>
|
||||
<a-avatar :size="40" class="user-avatar" :src="store.loginUser.avatarUrl"/>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item @click="logout">
|
||||
<LogoutOutlined />
|
||||
退出登录
|
||||
</a-menu-item>
|
||||
<a-menu-item @click="showDrawer">
|
||||
<UserOutlined />
|
||||
个人中心
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-drawer
|
||||
title="个人中心"
|
||||
:placement="placement"
|
||||
:closable="false"
|
||||
:open="open"
|
||||
@close="onClose"
|
||||
class="custom-class"
|
||||
>
|
||||
<a-avatar :size="64" :src="store.loginUser.avatarUrl"></a-avatar>
|
||||
|
||||
<div class="message">
|
||||
<p class="firstmessage">用户名:{{ store.loginUser.username }}</p>
|
||||
<p>账号ID:{{ store.loginUser.username }}</p>
|
||||
<p>注册时间:2024-06-20</p>
|
||||
<p>账号权限:{{store.loginUser.userRole}}</p>
|
||||
<p>联系方式:{{store.loginUser.phone}}</p>
|
||||
</div>
|
||||
|
||||
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {userStore} from "../../store/userStore.ts";
|
||||
import {UserOutlined,LogoutOutlined} from '@ant-design/icons-vue';
|
||||
import myAxios from "../../api/myAxios.ts";
|
||||
import {message} from "ant-design-vue";
|
||||
import { ref } from 'vue';
|
||||
import type { DrawerProps } from 'ant-design-vue';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const store = userStore()
|
||||
|
||||
|
||||
const placement = ref<DrawerProps['placement']>('right');
|
||||
const open = ref<boolean>(false);
|
||||
|
||||
const showDrawer = () => {
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 登出
|
||||
*/
|
||||
const logout = async () => {
|
||||
const res: any = await myAxios.post("/user/logout", {})
|
||||
if (res.code === 0 && res.data) {
|
||||
// 清除用户角色
|
||||
store.$reset()
|
||||
await router.replace('/')
|
||||
message.success('登出成功');
|
||||
} else {
|
||||
message.error(`登出失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.manage-header {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
background: #fff;
|
||||
border-bottom: 2px solid #ccced7;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.header-left .breadcrumb {
|
||||
color: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.routeName {
|
||||
font-size: 13px;
|
||||
padding-top: 10px;
|
||||
font-weight: 400;
|
||||
|
||||
}
|
||||
.header-right {
|
||||
display: flex;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.header-right .bell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.header-right .name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.header-right .user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
//transition: all 0.5s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.user-avatar:hover {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
|
||||
.custom-class img{
|
||||
float: left;
|
||||
}
|
||||
.message {
|
||||
float: right;
|
||||
margin-right: 100px;
|
||||
}
|
||||
.firstmessage {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
91
CampusExpressDelivery/src/layout/manage/ManageSidebar.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<a-menu
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
style="max-height: 200vh; min-height: 100vh"
|
||||
@click="handleClick"
|
||||
>
|
||||
<a-menu-item key="/index">
|
||||
<PieChartOutlined />
|
||||
<span>首页</span>
|
||||
</a-menu-item>
|
||||
<a-sub-menu>
|
||||
<template #title>
|
||||
<span>
|
||||
<UserOutlined />
|
||||
<span>用户管理</span>
|
||||
</span>
|
||||
</template>
|
||||
<a-menu-item key="/userList">用户列表</a-menu-item>
|
||||
</a-sub-menu>
|
||||
<a-sub-menu>
|
||||
<template #title>
|
||||
<span>
|
||||
<UserOutlined />
|
||||
<span>快送员管理</span>
|
||||
</span>
|
||||
</template>
|
||||
<a-menu-item key="/errandList">快送员列表</a-menu-item>
|
||||
<a-menu-item key="/runList">订单列表</a-menu-item>
|
||||
</a-sub-menu>
|
||||
<a-sub-menu>
|
||||
<template #title>
|
||||
<span>
|
||||
<ShopOutlined />
|
||||
<span>店铺管理</span>
|
||||
</span>
|
||||
</template>
|
||||
<a-menu-item key="/businessManage">门店管理</a-menu-item>
|
||||
<a-menu-item key="/storeList">订单列表</a-menu-item>
|
||||
<a-menu-item key="/log">店铺操作日志</a-menu-item>
|
||||
</a-sub-menu>
|
||||
<a-sub-menu>
|
||||
<template #title>
|
||||
<span>
|
||||
<SettingOutlined />
|
||||
<span>系统管理</span>
|
||||
</span>
|
||||
</template>
|
||||
<a-menu-item key="/info">管理员公告管理</a-menu-item>
|
||||
<!-- <a-menu-item key="/businessInfoManage">商家公告管理</a-menu-item>-->
|
||||
<a-menu-item key="/category">分类管理</a-menu-item>
|
||||
<a-menu-item key="/carousel">轮播图管理</a-menu-item>
|
||||
</a-sub-menu>
|
||||
<a-menu-item key="/CustomerService">
|
||||
<AlipayOutlined />
|
||||
<span>人工客服</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {UserOutlined, ShopOutlined, SettingOutlined,AlipayOutlined,PieChartOutlined} from '@ant-design/icons-vue';
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
// 选中侧边栏
|
||||
const selectedKeys = ref<string[]>(['/userList']);
|
||||
|
||||
onMounted(() => {
|
||||
setSelectedKey()
|
||||
})
|
||||
|
||||
// 根据路由设置当前选中侧边栏
|
||||
const setSelectedKey = () => {
|
||||
selectedKeys.value = [route.path];
|
||||
}
|
||||
|
||||
// 路由跳转
|
||||
const handleClick = (item: any) => {
|
||||
router.push(item.key)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
14
CampusExpressDelivery/src/main.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {createApp} from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import pinia from "./store";
|
||||
import router from "./router";
|
||||
|
||||
const app = createApp(App)
|
||||
// 配置路由
|
||||
app.use(router)
|
||||
// 配置pinia
|
||||
app.use(pinia)
|
||||
// 挂在实例
|
||||
app.mount('#app')
|
||||
|
11
CampusExpressDelivery/src/router/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {createRouter, createWebHashHistory} from "vue-router";
|
||||
import {routes} from "./routes";
|
||||
|
||||
// 创建路由实例并传递 `routes` 配置
|
||||
const router = createRouter({
|
||||
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
|
||||
history: createWebHashHistory(),
|
||||
routes, // `routes: routes` 的缩写
|
||||
})
|
||||
|
||||
export default router
|
121
CampusExpressDelivery/src/router/routes.ts
Normal file
@ -0,0 +1,121 @@
|
||||
// 将路由规则 routes 导出
|
||||
export const routes = [
|
||||
// 全局路由(无需嵌套上左右整体布局)
|
||||
{
|
||||
path: '/',
|
||||
name: 'Login',
|
||||
component: () => import("../view/Login.vue")
|
||||
},
|
||||
{
|
||||
path: '/test',
|
||||
name: '全局测试页面',
|
||||
component: () => import("../view/Test.vue"),
|
||||
},
|
||||
// 管理端
|
||||
{
|
||||
path: '/manage',
|
||||
component: () => import("../layout/ManageLayout.vue"),
|
||||
children: [
|
||||
// 首页
|
||||
{
|
||||
path: '/index',
|
||||
name: '首页',
|
||||
component: () => import("../view/Index.vue"),
|
||||
},
|
||||
// 账户管理
|
||||
{
|
||||
path: '/userList',
|
||||
name: '用户列表',
|
||||
component: () => import("../view/user/UserList.vue"),
|
||||
},
|
||||
//快送员管理
|
||||
{
|
||||
path: '/errandList',
|
||||
name: '快送员列表',
|
||||
component: () => import("../view/errand/errandList.vue"),
|
||||
},
|
||||
{
|
||||
path: '/errandInfo',
|
||||
name: '快送员审核',
|
||||
component: () => import("../view/errand/errandInfo.vue"),
|
||||
},
|
||||
{
|
||||
path: '/runList',
|
||||
name: '快送员订单',
|
||||
component: () => import("../view/errand/runList.vue"),
|
||||
},
|
||||
{
|
||||
path: '/errandOrderList',
|
||||
name: '快送员订单列表',
|
||||
component: () => import("../view/errand/errandOrderList.vue"),
|
||||
},
|
||||
// 店铺管理
|
||||
{
|
||||
path: '/businessManage',
|
||||
name: '门店管理',
|
||||
component: () => import("../view/shop/business/BusinessManage.vue"),
|
||||
},
|
||||
{
|
||||
path: '/businessInfo',
|
||||
name: '门店详情',
|
||||
component: () => import("../view/shop/business/BusinessInfo.vue"),
|
||||
},
|
||||
{
|
||||
path: '/DishGroup',
|
||||
name: '菜品分组详情',
|
||||
component: () => import("../view/shop/business/DishGroup.vue"),
|
||||
},
|
||||
{
|
||||
path: '/Dish',
|
||||
name: '菜品详情',
|
||||
component: () => import("../view/shop/business/Dish.vue"),
|
||||
},
|
||||
{
|
||||
path: '/storeList',
|
||||
name: '店铺列表',
|
||||
component: () => import("../view/shop/order/StoreList.vue"),
|
||||
},
|
||||
{
|
||||
path: '/orderList',
|
||||
name: '订单列表',
|
||||
component: () => import("../view/shop/order/OrderList.vue"),
|
||||
},
|
||||
{
|
||||
path: '/orderDetail',
|
||||
name: '订单详情',
|
||||
component: () => import("../view/shop/order/OrderDetail.vue"),
|
||||
},
|
||||
{
|
||||
path: '/log',
|
||||
name: '门店操作日志',
|
||||
component: () => import("../view/shop/BusinessLog.vue"),
|
||||
},
|
||||
// 系统管理
|
||||
{
|
||||
path: '/info',
|
||||
name: '公告管理',
|
||||
component: () => import("../view/system/Info.vue"),
|
||||
},
|
||||
{
|
||||
path: '/businessInfoManage',
|
||||
name: '商家公告管理',
|
||||
component: () => import("../view/system/BusinessInfo.vue"),
|
||||
},
|
||||
{
|
||||
path: '/category',
|
||||
name: '分类管理',
|
||||
component: () => import("../view/system/Category.vue"),
|
||||
},
|
||||
{
|
||||
path: '/carousel',
|
||||
name: '轮播图管理',
|
||||
component: () => import("../view/system/Carousel/Carousel.vue"),
|
||||
},
|
||||
{
|
||||
path: '/CustomerService',
|
||||
name: '人工客服',
|
||||
component: () => import("../view/Service/CustomerService.vue"),
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
10
CampusExpressDelivery/src/store/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {createPinia} from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
const pinia = createPinia();
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
|
||||
|
||||
|
||||
|
||||
export default pinia
|
32
CampusExpressDelivery/src/store/userStore.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import {defineStore} from 'pinia'
|
||||
import myAxios from "../api/myAxios";
|
||||
|
||||
export const userStore = defineStore('user', {
|
||||
// 推荐使用 完整类型推断的箭头函数
|
||||
state: () => {
|
||||
return {
|
||||
loginUser: {
|
||||
username: '未登录',
|
||||
avatarUrl: '',
|
||||
userRole: 'notLogin',
|
||||
phone:''
|
||||
}
|
||||
}
|
||||
}, persist: true,
|
||||
|
||||
actions: {
|
||||
// 获取登录用户信息
|
||||
async getLoginUser() {
|
||||
// 请求登录信息
|
||||
const res: any = await myAxios.get('/user/current');
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log("56765765756567")
|
||||
this.updateUser(res.data)
|
||||
}
|
||||
},
|
||||
// 更新用户信息
|
||||
updateUser(payLoad: any) {
|
||||
this.loginUser = payLoad;
|
||||
}
|
||||
}
|
||||
})
|
48
CampusExpressDelivery/src/style.css
Normal file
@ -0,0 +1,48 @@
|
||||
html {
|
||||
/* 滚动时采用平滑过渡 */
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 管理页面全局样式 */
|
||||
|
||||
.main-card {
|
||||
min-height: calc(100vh - 100px);
|
||||
}
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
background-color: white;
|
||||
height: auto;
|
||||
box-shadow: 0 0 1px 1px #dedede;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.middle-button {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.data-box {
|
||||
margin-top: 20px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 1px 1px #dedede;
|
||||
border-radius: 5px;
|
||||
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin: 20px 0 20px 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.txt {
|
||||
font-weight: 900;
|
||||
font-size: 500px;
|
||||
}
|
11
CampusExpressDelivery/src/utils/TableConfig.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// 时间处理
|
||||
import router from "../router";
|
||||
|
||||
export const formatTime = (row: any) => {
|
||||
let data = row.value;
|
||||
return data.slice(0, 16).replace('T', '~');
|
||||
}
|
||||
|
||||
export const backPage = () => {
|
||||
router.back()
|
||||
}
|
338
CampusExpressDelivery/src/view/Index.vue
Normal file
@ -0,0 +1,338 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import BrokenLine from "./echarts/BrokenLine.vue";
|
||||
import myAxios from "../api/myAxios.ts";
|
||||
import { ElDatePicker,ElAlert} from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
const isLoading = ref(true)
|
||||
|
||||
const dailyTransactions = ref('')
|
||||
const fiscalRevenue = ref('')
|
||||
const value1:any = ref<[Date, Date] | null>(null)
|
||||
const defaultTime1 = new Date(2000, 1, 1, 12, 0, 0)
|
||||
|
||||
// 日期格式化函数
|
||||
const formatDate:any = (date: Date | null | undefined): string => {
|
||||
if (!date) return ""
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
// 监听日期选择变化
|
||||
watch(value1, (newVal) => {
|
||||
let startTime = ""
|
||||
let endTime = ""
|
||||
if (newVal && newVal.length === 2) {
|
||||
startTime = formatDate(newVal[0])
|
||||
endTime = formatDate(newVal[1])
|
||||
}
|
||||
fetchRevenue(startTime, endTime)
|
||||
totalNumber(startTime, endTime)
|
||||
})
|
||||
|
||||
// 获取财政收入数据
|
||||
const fetchRevenue:any = async (startTime: string = "", endTime: string = "") => {
|
||||
try {
|
||||
const response:any = await myAxios.post('/orders/count', {
|
||||
businessId: "",
|
||||
businessName: "",
|
||||
businessState: 0,
|
||||
categoryId: 0,
|
||||
endTime: endTime,
|
||||
startTime: startTime,
|
||||
state: 0,
|
||||
type: "money"
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
if (response.code === 0) {
|
||||
fiscalRevenue.value = parseFloat(response.data).toFixed(2)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching revenue:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取交易单量数据
|
||||
const totalNumber:any = async (startTime: string = "", endTime: string = "") => {
|
||||
try {
|
||||
const response:any = await myAxios.post('/orders/count', {
|
||||
businessId: "",
|
||||
businessName: "",
|
||||
businessState: 0,
|
||||
categoryId: 0,
|
||||
endTime: endTime,
|
||||
startTime: startTime,
|
||||
state: 0,
|
||||
type: "number"
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
if (response.code === 0) {
|
||||
dailyTransactions.value = response.data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching total number:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const refundList = ref<string[]>([]) // 明确类型为字符串数组
|
||||
|
||||
const getReasonRefund = async () => {
|
||||
try {
|
||||
const response:any = await myAxios.post('/refund/list/reson', {}, { // 添加空请求体
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
if (response.code === 0) {
|
||||
console.log(response)
|
||||
// 确保数据是数组格式(根据你的接口返回结构调整)
|
||||
refundList.value = Array.isArray(response.data) ? response.data : []
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('请求失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await Promise.all([
|
||||
fetchRevenue(),
|
||||
totalNumber(),
|
||||
getReasonRefund()
|
||||
])
|
||||
} catch (error) {
|
||||
console.error('数据加载失败:', error)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<a-spin v-if="isLoading" class="loading-spinner" />
|
||||
<div v-if="!isLoading">
|
||||
<div class="container">
|
||||
<div class="box">
|
||||
<div class="number">每日交易量</div>
|
||||
<div class="number">{{ dailyTransactions }}</div>
|
||||
<div class="number">食堂总共交易量为{{ dailyTransactions }}</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="number">财政收入</div>
|
||||
<div class="number">¥{{ fiscalRevenue }}</div>
|
||||
<div class="number">每日财政收入金额为¥{{ fiscalRevenue }}</div>
|
||||
</div>
|
||||
<div class="boxTime">
|
||||
<div class="boxTime-number">时间选择器</div>
|
||||
<el-date-picker
|
||||
v-model="value1"
|
||||
type="datetimerange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="defaultTime1"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert-chart-container">
|
||||
<div class="alert-container">
|
||||
<div class="boxTime-number">退款原因申请</div>
|
||||
<template v-if="refundList.length === 0">
|
||||
<a-empty />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="refund-list">
|
||||
<el-alert
|
||||
v-for="(item, index) in refundList"
|
||||
:key="index"
|
||||
:title="`退款原因 ${index + 1}`"
|
||||
type="error"
|
||||
:description="item"
|
||||
show-icon
|
||||
:closable="false"
|
||||
class="alert-item"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<BrokenLine />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
overflow: auto;
|
||||
}
|
||||
.box {
|
||||
float: left;
|
||||
width: 30%;
|
||||
margin: 1%;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
.boxTime {
|
||||
float: left;
|
||||
margin: 1%;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
border-radius: 15px;
|
||||
}
|
||||
.boxTime-number {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.number:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.number:nth-child(2) {
|
||||
font-size: 24px;
|
||||
color: #4CAF50; /* Green color for the revenue amount */
|
||||
}
|
||||
|
||||
.number:nth-child(3) {
|
||||
color: #4CAF50; /* Green color for the change since last week */
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.brokenLine {
|
||||
margin: 0 auto;
|
||||
width: 60%;
|
||||
height: 40%;
|
||||
}
|
||||
.ordermethod {
|
||||
width: 100%;
|
||||
height: 40%;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.el-alert {
|
||||
margin: 20px 0 0;
|
||||
}
|
||||
.el-alert:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
.alertMessage {
|
||||
width: 50%;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
margin: 1%;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
/* 新增布局样式 */
|
||||
.alert-chart-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin: 1%;
|
||||
height: 500px;
|
||||
width: calc(100% - 2%); /* 补偿左右margin */
|
||||
}
|
||||
|
||||
.alert-container {
|
||||
flex: 0 0 30%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16);
|
||||
height: 500px;
|
||||
|
||||
.refund-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-right: 8px;
|
||||
|
||||
.alert-item {
|
||||
margin-bottom: 10px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
.refund-list::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.refund-list::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.refund-list::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.refund-list::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
|
||||
.chart-container {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 1200px) {
|
||||
.alert-chart-container {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.alert-container {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 9999;
|
||||
}
|
||||
</style>
|
293
CampusExpressDelivery/src/view/Login.vue
Normal file
@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<div id="login">
|
||||
<form>
|
||||
<div class="box" @submit.prevent>
|
||||
<h2>校快送后台管理系统</h2>
|
||||
<div class="input-box">
|
||||
<label>账号</label>
|
||||
<input type="text" placeholder="账号" v-model="userAccount"/>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label>密码</label>
|
||||
<div class="password-container">
|
||||
<input
|
||||
class="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
placeholder="密码"
|
||||
v-model="userPassword"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<div @click="togglePassword" class="password-toggle">
|
||||
<img
|
||||
src="../assets/login/hidePassword.png"
|
||||
v-show="!showPassword"
|
||||
alt="隐藏密码"
|
||||
/>
|
||||
<img
|
||||
src="../assets/login/showPassword.png"
|
||||
v-show="showPassword"
|
||||
alt="显示密码"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<div>
|
||||
<button @click="onLogin" @keyup.enter="onLogin" type="button">登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useRouter} from 'vue-router'
|
||||
import {ref} from 'vue'
|
||||
import {userStore} from "../store/userStore.ts";
|
||||
import myAxios from "../api/myAxios";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const store = userStore()
|
||||
const router = useRouter()
|
||||
|
||||
//默认闭眼图标
|
||||
let showPassword = ref(false)
|
||||
const userAccount = ref('');
|
||||
const userPassword = ref('');
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
const onLogin = async () => {
|
||||
try {
|
||||
const res: any = await myAxios.post("/user/login", {
|
||||
appName: 'admin',
|
||||
userAccount: userAccount.value,
|
||||
userPassword: userPassword.value
|
||||
});
|
||||
|
||||
if (res.code === 0 && res?.data) {
|
||||
console.log(res);
|
||||
// 存储用户角色
|
||||
await store.getLoginUser();
|
||||
// 添加调试信息
|
||||
console.log('Redirecting to /index');
|
||||
//await router.replace('/index');
|
||||
router.push('/index');
|
||||
message.success('登录成功');
|
||||
} else {
|
||||
message.error(`登录失败:${res.description}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
message.error('登录失败,请稍后再试');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换密码显示/隐藏
|
||||
*/
|
||||
const togglePassword = () => {
|
||||
showPassword.value = !showPassword.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#login {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-image: url('../assets/background.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
||||
border-left: 1px solid rgba(255, 255, 255, 0.5);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(50, 50, 50, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.box > h2 {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.box .input-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.box .input-box label {
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.box .input-box input {
|
||||
letter-spacing: 1px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
width: 250px;
|
||||
height: 35px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
outline: none;
|
||||
padding: 0 12px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
/* 密码输入框容器 */
|
||||
.password-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.password-container .password {
|
||||
width: 100%;
|
||||
padding-right: 40px; /* 为图标留出空间 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 禁用浏览器默认的密码显示功能 */
|
||||
.password::-ms-reveal,
|
||||
.password::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.password-toggle {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.password-toggle img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.box .input-box input:focus {
|
||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.box .btn-box {
|
||||
width: 250px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.box .btn-box > a {
|
||||
outline: none;
|
||||
display: block;
|
||||
width: 250px;
|
||||
text-align: end;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.box .btn-box > a:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.box .btn-box > div {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.box .btn-box > div > button {
|
||||
outline: none;
|
||||
margin-top: 10px;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.box .btn-box > div > button:nth-of-type(1) {
|
||||
width: 250px;
|
||||
height: 35px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border: 1px solid rgba(64, 149, 229, 0.7);
|
||||
background: rgba(64, 149, 229, 0.5);
|
||||
}
|
||||
|
||||
.box .btn-box > div > button:nth-of-type(2) {
|
||||
width: 120px;
|
||||
height: 35px;
|
||||
margin-left: 10px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border: 1px solid rgba(64, 149, 229, 0.7);
|
||||
background: rgba(64, 149, 229, 0.5);
|
||||
}
|
||||
|
||||
.box .btn-box > div > button:hover {
|
||||
border: 1px solid rgba(64, 149, 229, 0.7);
|
||||
background: rgba(64, 149, 229, 0.5);
|
||||
}
|
||||
|
||||
@media (max-width: 1440px) {
|
||||
.container {
|
||||
width: 28%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1366px) {
|
||||
.container {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
.container {
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
.agileheader h1 {
|
||||
font-size: 41px;
|
||||
}
|
||||
|
||||
.container h2 {
|
||||
font-size: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.container {
|
||||
width: 49%;
|
||||
}
|
||||
}
|
||||
</style>
|
17
CampusExpressDelivery/src/view/Service/CustomerService.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%;">
|
||||
<iframe
|
||||
:src="chatUrl"
|
||||
frameborder="0"
|
||||
style="width: 100%; height: 100%; border: none;"
|
||||
></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const chatUrl = "https://ccs.cloud.alipay.com/bench/online";
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式部分保持不变 */
|
||||
</style>
|
3
CampusExpressDelivery/src/view/Test.vue
Normal file
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div>123</div>
|
||||
</template>
|
202
CampusExpressDelivery/src/view/echarts/BrokenLine.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import myAxios from "../../api/myAxios.ts";
|
||||
|
||||
const main = ref();
|
||||
const orderData = ref<any[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
getNumberOrder();
|
||||
});
|
||||
|
||||
const getNumberOrder = async () => {
|
||||
try {
|
||||
const response:any = await myAxios.post(
|
||||
"/orders/list/numnber",
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (response.code === 0 && Array.isArray(response.data)) {
|
||||
orderData.value = response.data.reverse(); // 反转数组顺序以匹配日期排列
|
||||
updateChart();
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("请求失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
const myChart = echarts.init(main.value);
|
||||
// 初始空配置
|
||||
myChart.setOption(getChartOption());
|
||||
};
|
||||
|
||||
const updateChart = () => {
|
||||
const myChart = echarts.getInstanceByDom(main.value);
|
||||
if (myChart) {
|
||||
myChart.setOption(getChartOption());
|
||||
}
|
||||
};
|
||||
|
||||
const getChartOption = () => {
|
||||
// 提取数据并处理为图表需要的格式
|
||||
const dates = orderData.value.map((item) => item.date);
|
||||
const takeOutData = orderData.value.map((item) => parseInt(item.takeOutNum));
|
||||
const eatInData = orderData.value.map((item) => parseInt(item.eatInNum));
|
||||
const selfLiftData = orderData.value.map((item) => parseInt(item.selfLiftNum));
|
||||
|
||||
return {
|
||||
color: ["#80FFA5", "#00DDFF", "#37A2FF", "#FF0087", "#FFBF00"],
|
||||
title: {
|
||||
text: "订单数据趋势图",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "cross",
|
||||
label: {
|
||||
backgroundColor: "#6a7985",
|
||||
},
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
data: ["外卖订单", "堂食订单", "自提订单"], // 修正中文名称
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {},
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "4%",
|
||||
bottom: "3%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
data: dates, // 动态日期数据
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
name: "订单数量",
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "外卖订单",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 0,
|
||||
},
|
||||
showSymbol: false,
|
||||
areaStyle: {
|
||||
opacity: 0.8,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgb(128, 255, 165)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgb(1, 191, 236)",
|
||||
},
|
||||
]),
|
||||
},
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
},
|
||||
data: takeOutData, // 动态数据
|
||||
},
|
||||
{
|
||||
name: "堂食订单",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 0,
|
||||
},
|
||||
showSymbol: false,
|
||||
areaStyle: {
|
||||
opacity: 0.8,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgb(0, 221, 255)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgb(77, 119, 255)",
|
||||
},
|
||||
]),
|
||||
},
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
},
|
||||
data: eatInData, // 动态数据
|
||||
},
|
||||
{
|
||||
name: "自提订单",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 0,
|
||||
},
|
||||
showSymbol: false,
|
||||
areaStyle: {
|
||||
opacity: 0.8,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "rgb(255, 0, 135)",
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "rgb(135, 0, 157)",
|
||||
},
|
||||
]),
|
||||
},
|
||||
emphasis: {
|
||||
focus: "series",
|
||||
},
|
||||
data: selfLiftData, // 动态数据
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="echarts">
|
||||
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||
<div ref="main" style="width: 100%; height: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.echarts {
|
||||
width: 90%;
|
||||
height: 80%;
|
||||
border-radius: 12px;
|
||||
margin: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: #ffffff;
|
||||
min-width: 0;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
</style>
|
||||
|
80
CampusExpressDelivery/src/view/echarts/ordermethod.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
|
||||
const main = ref();
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
const init = () => {
|
||||
const myChart = echarts.init(main.value);
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
padAngle: 5,
|
||||
itemStyle: {
|
||||
borderRadius: 10
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 40,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: 735, name: '跑腿类' },
|
||||
{ value: 580, name: '自提类' },
|
||||
{ value: 484, name: '外卖类' },
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="echarts">
|
||||
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||
|
||||
<div ref="main" style="width: 100%; height: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.echarts {
|
||||
width: 50%;
|
||||
height: 80%;
|
||||
border-radius: 12px;
|
||||
margin: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: #ffffff;
|
||||
min-width: 0;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
</style>
|
||||
|
180
CampusExpressDelivery/src/view/errand/errandInfo.vue
Normal file
@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<a-card :loading="loading">
|
||||
<div >
|
||||
<a-descriptions size="default" bordered class="txt">
|
||||
<a-descriptions-item label="头像">
|
||||
<template v-slot>
|
||||
<a-avatar :src="errandInfo.errandAvatarUrl" style="width: 100px;height: 100px;"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="用户名称">{{ errandInfo?.errandName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="用户性别">
|
||||
<div v-if="errandInfo.gender === 1">
|
||||
<a-tag color="blue">男</a-tag>
|
||||
</div>
|
||||
<div v-else-if="errandInfo.gender === 0">
|
||||
<a-tag color="pink">女</a-tag>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="联系方式">{{ errandInfo?.errandPhone }}</a-descriptions-item>
|
||||
<a-descriptions-item label="配送范围">{{ errandInfo?.distributionScope }}</a-descriptions-item>
|
||||
<a-descriptions-item label="银行卡号">{{ errandInfo?.bankCard }}</a-descriptions-item>
|
||||
<a-descriptions-item label="身份证正面">
|
||||
<template v-slot>
|
||||
<a-image :src="errandInfo.frontIdCard" style="width: 158.5px; height: 100px;"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="身份证反面">
|
||||
<template v-slot>
|
||||
<a-image :src="errandInfo.backIdCard" style="width: 158.5px; height: 100px"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="当前状态">
|
||||
<div v-if="errandInfo.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="errandInfo.state === 1">
|
||||
<a-tag color="green">快送员正常</a-tag>
|
||||
</div>
|
||||
<div v-else-if="errandInfo.state === 2">
|
||||
<a-tag color="red">快送员驳回</a-tag>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar :src="record.businessAvatar"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'license'">
|
||||
<a-image :src="record.license" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'frontIdCard'">
|
||||
<a-image :src="record.frontIdCard" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'backIdCard'">
|
||||
<a-image :src="record.backIdCard" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="green">已通过</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">未通过</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<a-space>
|
||||
<div class="button-box">
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small"
|
||||
type="default"
|
||||
style="color: blue"
|
||||
@click="backPage">返回
|
||||
</a-button>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small" v-if="state === 0"
|
||||
type="primary"
|
||||
style="color: white; margin-left: 15px"
|
||||
danger
|
||||
@click="update(2)">未通过
|
||||
</a-button>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small" v-if="state === 0"
|
||||
type="primary"
|
||||
style="color: white; margin-left: 15px"
|
||||
@click="update(1)">通过
|
||||
</a-button>
|
||||
</div>
|
||||
</a-space>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useRoute} from "vue-router";
|
||||
import {onMounted, ref} from "vue";
|
||||
import myAxios from "../../api/myAxios";
|
||||
import {backPage} from "../../utils/TableConfig";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "../../router";
|
||||
|
||||
const state = ref(0)
|
||||
const route = useRoute();
|
||||
const loading = ref(false);
|
||||
const errandInfo: any = ref({});
|
||||
const errandId = ref<string | null>(null);
|
||||
|
||||
|
||||
if (typeof route.query.id === 'string') {
|
||||
errandId.value = route.query.id;
|
||||
}
|
||||
|
||||
console.log(errandId.value);
|
||||
|
||||
onMounted(() => {
|
||||
if(errandId.value !== null) {
|
||||
getErrandVO(errandId.value);
|
||||
}
|
||||
});
|
||||
|
||||
const getErrandVO = async (id: string) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 修改参数传递方式为query params
|
||||
const res: any = await myAxios.post('/errand/get/id', null, {
|
||||
params: {
|
||||
errandId1: id // 直接使用参数id
|
||||
}
|
||||
});
|
||||
|
||||
console.log(res)
|
||||
if (res.code === 0 && res.data) {
|
||||
errandInfo.value = res.data || {};
|
||||
state.value = res.data.state ?? 0;
|
||||
}else if(res.code===40000){
|
||||
message.error(res.description);
|
||||
router.go(-1)
|
||||
}else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
message.error('请求过程中出现错误,请稍后再试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const update = async (newState: number) => {
|
||||
try {
|
||||
// 构建请求体,仅包含'id'和'state'
|
||||
const requestBody = {
|
||||
id: errandId.value || '',
|
||||
state: newState,
|
||||
};
|
||||
|
||||
const res: any = await myAxios.post("/errand/update", requestBody, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json', // 修改为JSON格式,如果你的后端接受JSON的话
|
||||
}
|
||||
});
|
||||
|
||||
if (res.code === 0) {
|
||||
message.success("已审核");
|
||||
state.value = newState; // 更新本地状态
|
||||
} else {
|
||||
message.error(`审核失败:${res.message}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("更新状态失败:", error);
|
||||
message.error('请求过程中出现错误');
|
||||
}
|
||||
}
|
||||
</script>
|
228
CampusExpressDelivery/src/view/errand/errandList.vue
Normal file
@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-form-item label="快送员名称">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入快送员名称"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearch"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
style="width: 200px;"
|
||||
placeholder="默认查询全部状态"
|
||||
allowClear
|
||||
v-model:value="searchParams.state"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option value="0">未审核</a-select-option>
|
||||
<a-select-option value="1">已审核</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入手机号"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearchPhone"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'errandAvatarUrl'">
|
||||
<a-avatar :src="record.errandAvatarUrl"/>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="green">已审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">封禁</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button v-if="record.state === 0" size="small" type="link" @click="toInfoPage(record.id)">审核</a-button>
|
||||
<a-button v-else size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="toInfoPage(record.id)">查看
|
||||
</a-button>
|
||||
<a-button :disabled="record.state === 0" size="small" type="link" danger
|
||||
@click="doBan(record.id, record.state === 1)">
|
||||
{{ record.state === 1 ? '禁用' : '启用' }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 个快送员`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import myAxios from "../../api/myAxios";
|
||||
import { formatTime } from "../../utils/TableConfig";
|
||||
import { message } from "ant-design-vue";
|
||||
import router from "../../router";
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false);
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
// 请求参数
|
||||
const searchParams: any = ref({
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend",
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
errandName: "",
|
||||
state: "", // 默认为空,表示查询所有状态
|
||||
errandPhone:""
|
||||
});
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({ index }: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{ title: '快送员名称', dataIndex: 'errandName', width: 100, fixed: 'left', align: 'center' },
|
||||
{ title: '快送员头像', key: 'errandAvatarUrl', width: 50, align: 'center' },
|
||||
{ title: '手机号', dataIndex: 'errandPhone', width: 150, align: 'center' },
|
||||
{ title: '状态', key: 'state', width: 70, align: 'center' },
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row);
|
||||
}
|
||||
},
|
||||
{ title: '操作', key: '操作', fixed: 'right', width: 100, align: 'center' },
|
||||
];
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getErrandList(1);
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取快送员数据
|
||||
*/
|
||||
const getErrandList = async (current: number) => {
|
||||
searchParams.value.current = current;
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post("/errand/page", { ...searchParams.value });
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
const doBan = async (id: string, isBan: boolean) => {
|
||||
const res: any = await myAxios.post("/errand/update", { id: id, state: isBan ? 2 : 1 });
|
||||
if (res.code === 0 && res.data) {
|
||||
message.success(`操作成功`);
|
||||
await getErrandList(1);
|
||||
} else {
|
||||
message.error(`封禁商家失败:${res.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
const onSearch = (errandName: string) => {
|
||||
searchParams.value.errandName = errandName;
|
||||
searchParams.value.current = 1;
|
||||
getErrandList(1);
|
||||
};
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
const onSearchPhone = (errandPhone: string) => {
|
||||
searchParams.value.errandPhone = errandPhone;
|
||||
searchParams.value.current = 1;
|
||||
getErrandList(1);
|
||||
};
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getErrandList(pageNumber);
|
||||
};
|
||||
|
||||
/**
|
||||
* 跳转到快送员信息
|
||||
*/
|
||||
const toInfoPage = (id: string) => {
|
||||
console.log(id); // 打印传递的ID值
|
||||
router.push({
|
||||
name: '快送员审核',
|
||||
// path: '/errandInfo',
|
||||
query: {
|
||||
id: String(id) // 确保ID值是字符串类型
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 当状态选择器值改变时触发
|
||||
*/
|
||||
const handleChange = () => {
|
||||
getErrandList(1);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
371
CampusExpressDelivery/src/view/errand/errandOrderList.vue
Normal file
@ -0,0 +1,371 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<a-button style="margin-bottom: 30px" type="primary" @click="back">返回</a-button>
|
||||
快送员订单
|
||||
<div class="data-box">
|
||||
<div style="display: flex;justify-content: space-around">
|
||||
<a-descriptions :column=3 style="width: 85%">
|
||||
<a-descriptions-item label="快送员姓名">{{ errandData?.errandName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="配送单位">{{ errandData?.distributionScope }}</a-descriptions-item>
|
||||
<a-descriptions-item label="联系方式">{{ errandData?.errandPhone }}</a-descriptions-item>
|
||||
<a-descriptions-item label="银行卡号">{{ errandData?.bankCard }}</a-descriptions-item>
|
||||
<a-descriptions-item label="当前接单量">{{ errandData?.totalOrders }}</a-descriptions-item>
|
||||
<a-descriptions-item label="最大送单量">{{ errandData?.maxOrders }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<div style="width: 15%;display: flex;white-space: nowrap">
|
||||
图片:
|
||||
<div style="width: 45%">
|
||||
<a-image :src="errandData.errandAvatarUrl"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-box" style="margin-top: 2%;display: inline-block;width: 100%">
|
||||
<div style="display: flex;justify-content: space-between;margin-bottom: 2%">
|
||||
<!-- 查询信息 -->
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-input-search
|
||||
style="width: 400px"
|
||||
placeholder="请输入订单号"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearch"
|
||||
/>
|
||||
<a-select
|
||||
v-model:value="searchParams.state"
|
||||
style="width: 120px"
|
||||
@change="getOrdersList(1)"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option value="0">未支付</a-select-option>
|
||||
<a-select-option value="1">已支付</a-select-option>
|
||||
<a-select-option value="2">已退款</a-select-option>
|
||||
<a-select-option value="3">已取消</a-select-option>
|
||||
<a-select-option value="4">已出餐</a-select-option>
|
||||
<a-select-option value="5">已完成</a-select-option>
|
||||
</a-select>
|
||||
</a-space>
|
||||
</a-form>
|
||||
<a-space>
|
||||
<!-- 导出信息 -->
|
||||
<a-button type="primary" @click="download">EXCEL导出</a-button>
|
||||
<!--筛选时间-->
|
||||
<a-range-picker @change="searchTime" format="YYYY-MM-DD"/>
|
||||
</a-space>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 800, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:rowKey="(record: any) => record.id"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="purple">未支付</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="blue">已支付</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">已退款</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 3">
|
||||
<a-tag color="gray">已取消</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 4">
|
||||
<a-tag color="blue">已出餐</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 5">
|
||||
<a-tag color="green">已完成</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'totalPrice'">
|
||||
<a-tag color="purple">{{ record.totalPrice }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="router.push({path:'/orderDetail',query:{id:record.id}})">查看
|
||||
</a-button>
|
||||
<a-button v-if="[1, 4, 5].includes(record.state)"
|
||||
size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="modalOpen = true; recordId=record.orderNo">退款
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!--订单金额信息 -->
|
||||
<div style="margin: 20px 0 20px 0;float: left;">
|
||||
<span class="ant-pagination-total-text">总金额:{{ ordersCount }}元</span>
|
||||
</div>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-size-changer
|
||||
show-quick-jumper
|
||||
:total="total"
|
||||
:show-total="() => `共 ${total} 条订单`"
|
||||
@change="onChange"
|
||||
@showSizeChange="onShowSizeChange"
|
||||
/>
|
||||
</div>
|
||||
<!--退款弹出框-->
|
||||
<a-modal v-model:open="modalOpen" title="退款" destroyOnClose @ok="refund()">
|
||||
<span>确定退款吗</span>
|
||||
</a-modal>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {formatTime} from "../../utils/TableConfig";
|
||||
import router from "../../router";
|
||||
import myAxios from "../../api/myAxios.ts";
|
||||
|
||||
const route = useRoute();
|
||||
//订单信息
|
||||
const tableData: any = ref([])
|
||||
//店铺信息
|
||||
const errandData: any = ref({})
|
||||
//订单总金额
|
||||
const ordersCount: any = ref<Number>()
|
||||
//加载按钮
|
||||
const loading = ref(false)
|
||||
//弹出框开关
|
||||
const modalOpen = ref<boolean>(false);
|
||||
//退款id
|
||||
const recordId = ref<Number>();
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
//查询条件
|
||||
const searchParams: any = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
orderId: null,
|
||||
searchTime: null,
|
||||
state: ''
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{title: '订单号', dataIndex: 'id', key: 'id', width: 100, fixed: 'left', align: 'center'},
|
||||
{
|
||||
title: '下单时间', dataIndex: 'createTime', key: 'createTime', width: 100, align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '卖家昵称', dataIndex: 'userName', key: 'userName', width: 150, align: 'center'},
|
||||
{title: '支付状态', dataIndex: 'state', key: 'state', width: 150, align: 'center'},
|
||||
{title: '订单金额', dataIndex: 'totalPrice', key: 'totalPrice', width: 150, align: 'center'},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 80, align: 'center'},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
getOrdersList(1)
|
||||
getBusinessVO()
|
||||
getOrdersCount()
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取订单信息列表
|
||||
*/
|
||||
console.log(route.query.id)
|
||||
const getOrdersList = async (current: any) => {
|
||||
let errandId = route.query.id; //商家id
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post('/orders/list/page', {
|
||||
errandId: errandId,
|
||||
businessId: "",
|
||||
current: current,
|
||||
pageSize: searchParams.value.pageSize,
|
||||
id: searchParams.value.orderId,
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend",
|
||||
state: searchParams.value.state,
|
||||
startTime: searchParams.value.searchTime == null ? '' : searchParams.value.searchTime[0],
|
||||
endTime: searchParams.value.searchTime == null ? '' : searchParams.value.searchTime[1]
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
searchParams.value.current = current
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
console.log("没有获取订单")
|
||||
console.log(res.data)
|
||||
message.error(`获取数据失败:${res.description}`);
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺信息
|
||||
*/
|
||||
const getBusinessVO = async () => {
|
||||
let errandId:any = route.query.id;
|
||||
if (!errandId) {
|
||||
console.error("商家ID未定义或为空");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new URLSearchParams();
|
||||
formData.append('errandId1', errandId);
|
||||
|
||||
try {
|
||||
const res:any = await myAxios.post('/errand/get/id', formData.toString(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
});
|
||||
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
errandData.value = res.data;
|
||||
} else {
|
||||
console.log(res)
|
||||
message.error(`获取数据失败:${res.description}`);
|
||||
back();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('请求异常:', error);
|
||||
message.error('接口请求异常,请检查控制台');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取该店铺收入
|
||||
*/
|
||||
const getOrdersCount = async () => {
|
||||
let errandId = route.query.id; //商家id
|
||||
const res: any = await myAxios.post('/orders/count', {
|
||||
"errandId": errandId,
|
||||
"type": "money",
|
||||
"state": 5
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
ordersCount.value = res.data;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.description}`);
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出Excel表
|
||||
*/
|
||||
const download = async () => {
|
||||
let errandId = route.query.id //商家id
|
||||
const res: any = await myAxios.post('/orders/download/errand', {
|
||||
errandId: errandId,
|
||||
// 添加时间参数(与列表查询保持一致)
|
||||
startTime: searchParams.value.searchTime?.[0] || '',
|
||||
endTime: searchParams.value.searchTime?.[1] || '',
|
||||
// 保留其他必要参数
|
||||
current: searchParams.value.current,
|
||||
pageSize: searchParams.value.pageSize,
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend"
|
||||
},
|
||||
{
|
||||
responseType: "blob"
|
||||
}
|
||||
)
|
||||
downloadCallback(res, '快送员订单信息表.xlsx')
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
// const refund = async () => {
|
||||
// const res: any = await myAxios.get('/Alipay/test/refund', {orderNo: recordId.value})
|
||||
// if (res.code === 0 && res.data) {
|
||||
// message.success('退款成功');
|
||||
// modalOpen.value = false
|
||||
// await getOrdersList(1)
|
||||
// await getOrdersCount()
|
||||
// } else {
|
||||
// message.error(`退款失败:${res.description}`);
|
||||
// }
|
||||
// }
|
||||
const refund = async () => {
|
||||
const res: any = await myAxios.get(`/Alipay/test/refund?orderNo=${recordId.value}`);
|
||||
if (res.code === 0 && res.data) {
|
||||
message.success('退款成功');
|
||||
modalOpen.value = false;
|
||||
await getOrdersList(1);
|
||||
await getOrdersCount();
|
||||
} else {
|
||||
message.error(`退款失败:${res.description}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
const onSearch = async (ordersId: number) => {
|
||||
searchParams.value.orderId = ordersId
|
||||
await getOrdersList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询时间
|
||||
*/
|
||||
const searchTime = async (dateTime: any) => {
|
||||
searchParams.value.searchTime = dateTime
|
||||
await getOrdersList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onShowSizeChange = (current: number, pageSize: number) => {
|
||||
searchParams.value.pageSize = pageSize;
|
||||
getOrdersList(current);
|
||||
}
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getOrdersList(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回
|
||||
*/
|
||||
const back = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
//生成下载文件
|
||||
const downloadCallback = (res: any, fileName: any) => {
|
||||
const blob = new Blob([res]);
|
||||
if ("download" in document.createElement("a")) {
|
||||
// 非IE下载
|
||||
const elink = document.createElement("a");
|
||||
elink.download = fileName;
|
||||
elink.style.display = "none";
|
||||
elink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
URL.revokeObjectURL(elink.href); // 释放URL 对象
|
||||
document.body.removeChild(elink);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
177
CampusExpressDelivery/src/view/errand/runList.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space warp>
|
||||
<a-form-item
|
||||
label="快送员名"
|
||||
>
|
||||
<a-input allow-clear @change="change" @pressEnter="getBusinessList(1)"
|
||||
v-model:value="searchParams.errandName"
|
||||
placeholder="请输入快送员名"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="配送范围">
|
||||
<a-select
|
||||
style="width: 200px;"
|
||||
placeholder="默认查询全部快送员"
|
||||
allowClear
|
||||
v-model:value="searchParams.distributionScope"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option value='1公寓'>1公寓</a-select-option>
|
||||
<a-select-option value='2公寓'>2公寓</a-select-option>
|
||||
<a-select-option value='3公寓'>3公寓</a-select-option>
|
||||
<a-select-option value='4公寓'>4公寓</a-select-option>
|
||||
<a-select-option value='5公寓'>5公寓</a-select-option>
|
||||
<a-select-option value='6公寓'>6公寓</a-select-option>
|
||||
<a-select-option value='7公寓'>7公寓</a-select-option>
|
||||
<a-select-option value='8公寓'>8公寓</a-select-option>
|
||||
<a-select-option value='9公寓'>9公寓</a-select-option>
|
||||
<a-select-option value='10公寓'>10公寓</a-select-option>
|
||||
<a-select-option value='11公寓'>11公寓</a-select-option>
|
||||
<a-select-option value='12公寓'>12公寓</a-select-option>
|
||||
<a-select-option value='育才大厦'>育才大厦</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-button type="primary" @click="getBusinessList(1)">查询</a-button>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1000, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar :src="record.errandAvatarUrl"/>
|
||||
</template>
|
||||
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="router.push({path: '/errandOrderList',query: {id: record.id}})">查看
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 位快送员`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import myAxios from "../../api/myAxios";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "../../router";
|
||||
|
||||
//表单数据
|
||||
const tableData: any = ref([]);
|
||||
//加载按钮
|
||||
const loading = ref(false)
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
//查询条件
|
||||
const searchParams: any = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
errandName: '',
|
||||
distributionScope: null
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({index}: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{title: '图片', dataIndex: 'businessAvatar', key: 'businessAvatar', width: 50, align: 'center'},
|
||||
{title: '快送员名', dataIndex: 'errandName', key: 'errandName', width: 50, align: 'center'},
|
||||
{title: '当前接单量', dataIndex: 'totalOrders', key: 'totalOrders', width: 50, align: 'center'},
|
||||
{title: '最大接单量', dataIndex: 'maxOrders', key: 'maxOrders', width: 50, align: 'center'},
|
||||
{title: '配送范围', dataIndex: 'distributionScope', key: 'distributionScope', width: 50, align: 'center'},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 50, align: 'center'},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
getBusinessList(1)
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取商家信息列表
|
||||
*/
|
||||
const getBusinessList = async (current: number) => {
|
||||
searchParams.value.current = current
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post('/errand/page', {...searchParams.value})
|
||||
console.log(res)
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择用户身份
|
||||
*/
|
||||
const handleChange = (distributionScope: string) => {
|
||||
searchParams.value.distributionScope = distributionScope;
|
||||
getBusinessList(1)
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置查询条件
|
||||
*/
|
||||
const reset = () => {
|
||||
searchParams.value.errandName = ''
|
||||
searchParams.value.distributionScope = null
|
||||
getBusinessList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getBusinessList(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除输入框的回调
|
||||
*/
|
||||
const change = (row: any) => {
|
||||
if (row.type === 'click') getBusinessList(1)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
169
CampusExpressDelivery/src/view/shop/BusinessLog.vue
Normal file
@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-form-item label="手机号">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入手机号"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearchByPhone"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar v-if="record.business!=null" :src="record?.business.businessAvatar"/>
|
||||
<div v-else>
|
||||
<a-tag color="blue">Boss账号</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'businessName'">
|
||||
<div v-if="record.business!=null">{{ record?.business.businessName }}</div>
|
||||
<div v-else>
|
||||
<a-tag color="blue">Boss账 号</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'businessPhone'">
|
||||
<div v-if="record.business!=null">{{ record?.business.businessPhone }}</div>
|
||||
<div v-else>
|
||||
<a-tag color="blue">Boss账号</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'content'">
|
||||
<a-tag :color="getTagColor(record.content)">{{ record.content }}</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 条数据`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {formatTime} from "../../utils/TableConfig";
|
||||
import myAxios from "../../api/myAxios";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const getTagColor = (content: string) => {
|
||||
const blueOperations = ['修改菜品', '修改菜品分组'];
|
||||
const redOperations = [ '删除菜品', '删除菜品分组'];
|
||||
const greenOperations = ['添加菜品', '添加菜品分组'];
|
||||
|
||||
if (blueOperations.includes(content)) return 'blue';
|
||||
if (greenOperations.includes(content)) return 'green';
|
||||
if (redOperations.includes(content)) return 'red';
|
||||
return 'red'; // 其他操作保持红色
|
||||
};
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false)
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
// 请求参数
|
||||
const searchParams: any = ref({
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend",
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
businessPhone: '',
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({index}: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{title: '门店名称', key: 'businessName', width: 100, align: 'center'},
|
||||
{title: '门店头像', key: 'businessAvatar', width: 50, align: 'center'},
|
||||
{title: '手机号', key: 'businessPhone', width: 150, align: 'center'},
|
||||
{title: '执行操作', key: 'content', width: 150, align: 'center'},
|
||||
{title: 'ip地址', dataIndex: 'ip', key: 'ip', width: 150, align: 'center'},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getBusinessLogList();
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取商家操作日志
|
||||
*/
|
||||
const getBusinessLogList = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post("/log/business/logs", {...searchParams.value})
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号搜索功能
|
||||
*/
|
||||
const onSearchByPhone = (businessPhone: number) => {
|
||||
searchParams.value.businessPhone = businessPhone;
|
||||
searchParams.value.current = 1;
|
||||
getBusinessLogList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getBusinessLogList();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
155
CampusExpressDelivery/src/view/shop/business/BusinessInfo.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<a-card title="商家信息" :loading="loading">
|
||||
<div class="main-card" >
|
||||
<a-descriptions size="default" bordered class="txt">
|
||||
<a-descriptions-item label="头像">
|
||||
<template v-slot>
|
||||
<a-avatar :src="businessInfo.businessAvatar" style="width: 100px;height: 100px;"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="店铺名称">{{ businessInfo?.businessName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="店主姓名">{{ businessInfo?.shopkeeper }}</a-descriptions-item>
|
||||
<a-descriptions-item label="联系方式">{{ businessInfo?.businessPhone }}</a-descriptions-item>
|
||||
<a-descriptions-item label="店铺地址">{{ businessInfo.address }}</a-descriptions-item>
|
||||
<a-descriptions-item label="银行卡号">{{ businessInfo?.bankCard }}</a-descriptions-item>
|
||||
<a-descriptions-item label="营业执照">
|
||||
<template v-slot>
|
||||
<a-image :src="businessInfo.license" style="width: 158.5px; height: 100px;"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="身份证正面">
|
||||
<template v-slot>
|
||||
<a-image :src="businessInfo.frontIdCard" style="width: 158.5px; height: 100px;"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="身份证反面">
|
||||
<template v-slot>
|
||||
<a-image :src="businessInfo.backIdCard" style="width: 158.5px; height: 100px"/>
|
||||
</template>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="当前状态">
|
||||
<div v-if="businessInfo.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="businessInfo.state === 1">
|
||||
<a-tag color="green">正常营业</a-tag>
|
||||
</div>
|
||||
<div v-else-if="businessInfo.state === 2">
|
||||
<a-tag color="red">暂定营业</a-tag>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar :src="record.businessAvatar"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'license'">
|
||||
<a-image :src="record.license" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'frontIdCard'">
|
||||
<a-image :src="record.frontIdCard" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'backIdCard'">
|
||||
<a-image :src="record.backIdCard" style="width: 100px;height: 100px;"></a-image>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="green">已通过</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">未通过</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<a-space>
|
||||
<div class="button-box">
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small"
|
||||
type="default"
|
||||
style="color: blue"
|
||||
@click="backPage">返回
|
||||
</a-button>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small" v-if="state === 0"
|
||||
type="primary"
|
||||
style="color: white; margin-left: 15px"
|
||||
danger
|
||||
@click="update(2)">未通过
|
||||
</a-button>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small" v-if="state === 0"
|
||||
type="primary"
|
||||
style="color: white; margin-left: 15px"
|
||||
@click="update(1)">通过
|
||||
</a-button>
|
||||
</div>
|
||||
</a-space>
|
||||
</a-card>
|
||||
<!-- 菜品列表展示区 -->
|
||||
<a-divider />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useRoute} from "vue-router";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {backPage} from "../../../utils/TableConfig";
|
||||
|
||||
const state = ref(0)
|
||||
const route = useRoute();
|
||||
const loading = ref(false);
|
||||
const businessInfo: any = ref({});
|
||||
const businessId = route.query.businessId; //商家id
|
||||
|
||||
onMounted(() => {
|
||||
getBusinessVO();
|
||||
// listDishGroup();
|
||||
})
|
||||
|
||||
const getBusinessVO = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.get('/business/getById', {params: {"id": businessId}})
|
||||
console.log(res)
|
||||
if (res.code === 0 && res.data) {
|
||||
businessInfo.value = res.data;
|
||||
state.value = res.data.state
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
backPage()
|
||||
}
|
||||
}
|
||||
|
||||
const update = async (state: number) => {
|
||||
const res: any = await myAxios.post("/business/update", {id: businessId, state: state})
|
||||
if (res.code === 0) {
|
||||
message.success("已审核")
|
||||
} else {
|
||||
message.error(`审核失败:${res.description}`);
|
||||
}
|
||||
backPage()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.button-box {
|
||||
margin: 100px 0 500px 1100px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.button-s {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
</style>
|
203
CampusExpressDelivery/src/view/shop/business/BusinessManage.vue
Normal file
@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-form-item label="门店名称">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入门店名称"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearch"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar :src="record.businessAvatar"/>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="orange">未审核</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="green">正常营业</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">封禁</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button v-if="record.state === 0" size="small" type="link" @click="toInfoPage(record.id)">审核</a-button>
|
||||
<a-button v-else size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="toInfoPage(record.id)">查看
|
||||
</a-button>
|
||||
<a-button :disabled="record.state === 0" size="small" type="link" danger
|
||||
@click="doBan(record.id, record.state === 1)">
|
||||
{{ record.state === 1 ? '禁用' : '启用' }}
|
||||
</a-button>
|
||||
<a-button type="link"
|
||||
style="color: rgba(71, 214, 213);"
|
||||
@click="toDishGroupPage(record.id)">查看菜品
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 家店铺`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {formatTime} from "../../../utils/TableConfig";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "../../../router";
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false);
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
// 请求参数
|
||||
const searchParams: any = ref({
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend",
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
businessName: '',
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({index}: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{title: '门店名称', dataIndex: 'businessName', width: 100, fixed: 'left', align: 'center'},
|
||||
{title: '门店头像', key: 'businessAvatar', width: 50, align: 'center'},
|
||||
{title: '手机号', dataIndex: 'businessPhone', width: 150, align: 'center'},
|
||||
{title: '状态', key: 'state', width: 70, align: 'center'},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 100, align: 'center'},
|
||||
];
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getBusinessList(1);
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取商家数据
|
||||
*/
|
||||
const getBusinessList = async (current: number) => {
|
||||
searchParams.value.current = current
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post("/business/list/page", {...searchParams.value})
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
const doBan = async (id: string, isBan: boolean) => {
|
||||
const res: any = await myAxios.post("/business/update", {id: id, state: isBan ? 2 : 1})
|
||||
if (res.code === 0 && res.data) {
|
||||
message.success(`操作成功`);
|
||||
await getBusinessList(1);
|
||||
} else {
|
||||
message.error(`封禁商家失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
const onSearch = (businessName: string) => {
|
||||
searchParams.value.businessName = businessName;
|
||||
searchParams.value.current = 1;
|
||||
getBusinessList(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getBusinessList(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到商家信息
|
||||
*/
|
||||
const toInfoPage = (businessId: any) => {
|
||||
router.push({
|
||||
name: '门店详情',
|
||||
query: {
|
||||
businessId: businessId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const toDishGroupPage = (businessId: any) => {
|
||||
router.push({
|
||||
name: '菜品分组详情',
|
||||
query: {
|
||||
businessId: businessId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
123
CampusExpressDelivery/src/view/shop/business/Dish.vue
Normal file
@ -0,0 +1,123 @@
|
||||
<script setup lang="ts">
|
||||
import {useRoute} from "vue-router";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {backPage} from "../../../utils/TableConfig";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const route = useRoute();
|
||||
const businessId = route.query.businessId;
|
||||
const dishGroupId = route.query.dishGroupId;
|
||||
const dishGroup = ref([]);
|
||||
// const loading = ref(false);
|
||||
const searchParams: any = ref({
|
||||
businessId: businessId,
|
||||
current: 1,
|
||||
dishesGroupId: dishGroupId,
|
||||
dishesName: "",
|
||||
pageSize: 10,
|
||||
sortField: "",
|
||||
sortOrder: "",
|
||||
status: ""
|
||||
})
|
||||
const getDishGroup = async () => {
|
||||
console.log(businessId);
|
||||
try {
|
||||
// loading.value = true;
|
||||
const res: any = await myAxios.post('/dishes/list/dishes', {
|
||||
...searchParams.value
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
dishGroup.value = res.data
|
||||
} else {
|
||||
message.error(res.description)
|
||||
backPage()
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
message.error("请求失败,请检查网络或后端服务");
|
||||
backPage();
|
||||
}
|
||||
}
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '菜品名称',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'dishesName',
|
||||
},
|
||||
{
|
||||
title: '菜品图片',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
key: 'dishesImage',
|
||||
},
|
||||
{
|
||||
title: '菜品价格',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'dishesPrice',
|
||||
},
|
||||
{
|
||||
title: '菜品打包费',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'packPrice',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'createTime',
|
||||
customRender: ({ text }: { text: string }) => text ? dayjs(text).format('YYYY-MM-DD') : '-',
|
||||
}
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
getDishGroup();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="dishGroup"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'dishesImage'">
|
||||
<a-avatar :src="record.dishesImage"></a-avatar>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small"
|
||||
type="default"
|
||||
style="color: blue"
|
||||
@click="backPage">返回
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
109
CampusExpressDelivery/src/view/shop/business/DishGroup.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<script setup lang="ts">
|
||||
import {useRoute} from "vue-router";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {backPage} from "../../../utils/TableConfig";
|
||||
import dayjs from "dayjs";
|
||||
import router from "../../../router";
|
||||
|
||||
const route = useRoute();
|
||||
const businessId = route.query.businessId;
|
||||
const dishGroup = ref([]);
|
||||
// const loading = ref(false);
|
||||
const getDishGroup = async () => {
|
||||
console.log(businessId);
|
||||
try {
|
||||
// loading.value = true;
|
||||
const res: any = await myAxios.post('/dishesGroup/list/dishesGroup', {
|
||||
businessId: businessId,
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
dishGroup.value = res.data
|
||||
} else {
|
||||
message.error(res.description)
|
||||
backPage()
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
message.error("请求失败,请检查网络或后端服务");
|
||||
backPage();
|
||||
}
|
||||
}
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'id',
|
||||
},
|
||||
{
|
||||
title: '菜品分组名称',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'groupName',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
dataIndex: 'createTime',
|
||||
customRender: ({ text }: { text: string }) => text ? dayjs(text).format('YYYY-MM-DD') : '-',
|
||||
},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 100, align: 'center'},
|
||||
];
|
||||
|
||||
const toDishPage = (businessId: any, dishGroupId:any) => {
|
||||
router.push({
|
||||
name: '菜品详情',
|
||||
query: {
|
||||
businessId: businessId,
|
||||
dishGroupId: dishGroupId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDishGroup();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-card>
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="dishGroup"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-button
|
||||
type="link"
|
||||
style="color: rgba(71, 214, 213);"
|
||||
@click="toDishPage(businessId, record.id)">查看菜品
|
||||
</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-button
|
||||
class="button-s"
|
||||
size="small"
|
||||
type="default"
|
||||
style="color: blue"
|
||||
@click="backPage">返回
|
||||
</a-button>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
102
CampusExpressDelivery/src/view/shop/order/OrderDetail.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!--订单详情-->
|
||||
<a-descriptions :column=2>
|
||||
<a-descriptions-item>
|
||||
<div style="display: flex;align-items: center">
|
||||
<span>商家信息:</span>
|
||||
<a-avatar :src="businessData.businessAvatar"/>
|
||||
<span>{{ businessData?.businessName }}</span>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="取餐码">
|
||||
<a-tag color="processing" v-if="orderData?.pickupCode">{{ orderData?.pickupCode }}</a-tag>
|
||||
<a-tag color="red" v-else>暂未支付</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="支付方式">
|
||||
<div v-if="orderData.payMethod === 0">微信支付</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="用户电话">{{ orderData?.phone }}</a-descriptions-item>
|
||||
<a-descriptions-item label="支付金额">{{ orderData?.totalPrice }}元</a-descriptions-item>
|
||||
<a-descriptions-item label="订单编号">{{ orderData.id }}</a-descriptions-item>
|
||||
<a-descriptions-item label="下单时间">{{ orderData?.createTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="支付时间">{{ orderData?.updateTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="订单备注">{{ orderData?.notes }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-list :loading="loading" size="default" bordered :data-source="orderDetail">
|
||||
<template #header>
|
||||
<div>订单列表</div>
|
||||
</template>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item style="display: flex">
|
||||
<a-list-item-meta :description="item.attributeNames === '' ? '未选择规格' : item.attributeNames">
|
||||
<template #title>
|
||||
<div>{{ item.dishesVO.dishesName }}</div>
|
||||
</template>
|
||||
<template #avatar>
|
||||
<a-image style="width: 4rem" :src="item.dishesVO.dishesImage"/>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
<a-list-item-meta style="display: flex; align-items: end">
|
||||
<template #title>
|
||||
<div style="float: right;margin-left: 10%">{{ item.subtotal }}元</div>
|
||||
<div style="float: right">×{{ item.quantity }}</div>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
<a-button style="margin-top: 30px" type="primary" @click="back">返回</a-button>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "../../../router";
|
||||
|
||||
const route = useRoute();
|
||||
//加载按钮
|
||||
const loading = ref(false);
|
||||
//订单信息
|
||||
const orderData: any = ref({});
|
||||
//商家信息
|
||||
const businessData: any = ref({});
|
||||
//订单详情
|
||||
const orderDetail: any = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
getOrderDetail()
|
||||
})
|
||||
|
||||
const getOrderDetail = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.get('/orders/get', {
|
||||
params: {id: route.query.id}
|
||||
})
|
||||
if (res.code === 0 && res.data)
|
||||
{
|
||||
console.log(res)
|
||||
loading.value = false;
|
||||
orderData.value = res.data
|
||||
businessData.value = res.data.businessVO
|
||||
orderDetail.value = res.data.orderDetailsVOList
|
||||
orderData.value.createTime = orderData.value.createTime.slice(0, 16).replace('T', '~')
|
||||
orderData.value.updateTime = orderData.value.updateTime.slice(0, 16).replace('T', '~')
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回
|
||||
*/
|
||||
const back = () => {
|
||||
router.back()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
349
CampusExpressDelivery/src/view/shop/order/OrderList.vue
Normal file
@ -0,0 +1,349 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<a-button style="margin-bottom: 30px" type="primary" @click="back">返回</a-button>
|
||||
店铺信息
|
||||
<div class="data-box">
|
||||
<div style="display: flex;justify-content: space-around">
|
||||
<a-descriptions :column=3 style="width: 85%">
|
||||
<a-descriptions-item label="店铺名">{{ businessData?.businessName }}</a-descriptions-item>
|
||||
<a-descriptions-item label="店主姓名">{{ businessData?.shopkeeper }}</a-descriptions-item>
|
||||
<a-descriptions-item label="店铺地">{{ businessData.address }}</a-descriptions-item>
|
||||
<a-descriptions-item label="联系方式">{{ businessData?.businessPhone }}</a-descriptions-item>
|
||||
<a-descriptions-item label="银行卡号">{{ businessData?.bankCard }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<div style="width: 15%;display: flex;white-space: nowrap">
|
||||
图片:
|
||||
<div style="width: 45%">
|
||||
<a-image :src="businessData.businessAvatar"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-box" style="margin-top: 2%;display: inline-block;width: 100%">
|
||||
<div style="display: flex;justify-content: space-between;margin-bottom: 2%">
|
||||
<!-- 查询信息 -->
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-input-search
|
||||
style="width: 400px"
|
||||
placeholder="请输入订单号"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearch"
|
||||
/>
|
||||
<a-select
|
||||
v-model:value="searchParams.state"
|
||||
style="width: 120px"
|
||||
@change="getOrdersList(1)"
|
||||
>
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option value="0">未支付</a-select-option>
|
||||
<a-select-option value="1">已支付</a-select-option>
|
||||
<a-select-option value="2">已退款</a-select-option>
|
||||
<a-select-option value="3">已取消</a-select-option>
|
||||
<a-select-option value="4">已出餐</a-select-option>
|
||||
<a-select-option value="5">已完成</a-select-option>
|
||||
</a-select>
|
||||
</a-space>
|
||||
</a-form>
|
||||
<a-space>
|
||||
<!-- 导出信息 -->
|
||||
<a-button type="primary" @click="download">EXCEL导出</a-button>
|
||||
<!--筛选时间-->
|
||||
<a-range-picker @change="searchTime" format="YYYY-MM-DD"/>
|
||||
</a-space>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 800, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:rowKey="(record: any) => record.id"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="purple">未支付</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="blue">已支付</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 2">
|
||||
<a-tag color="red">已退款</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 3">
|
||||
<a-tag color="gray">已取消</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 4">
|
||||
<a-tag color="blue">已出餐</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 5">
|
||||
<a-tag color="green">已完成</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === 'totalPrice'">
|
||||
<a-tag color="purple">{{ record.totalPrice }}</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="router.push({path:'/orderDetail',query:{id:record.id}})">查看
|
||||
</a-button>
|
||||
<a-button v-if="record.state === 1"
|
||||
size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="modalOpen = true; recordId=record.orderNo">退款
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!--订单金额信息 -->
|
||||
<div style="margin: 20px 0 20px 0;float: left;">
|
||||
<span class="ant-pagination-total-text">总金额:{{ ordersCount }}元</span>
|
||||
</div>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-size-changer
|
||||
show-quick-jumper
|
||||
:total="total"
|
||||
:show-total="() => `共 ${total} 条订单`"
|
||||
@change="onChange"
|
||||
@showSizeChange="onShowSizeChange"
|
||||
/>
|
||||
</div>
|
||||
<!--退款弹出框-->
|
||||
<a-modal v-model:open="modalOpen" title="退款" destroyOnClose @ok="refund()">
|
||||
<span>确定退款吗</span>
|
||||
</a-modal>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import {useRoute} from "vue-router";
|
||||
import {formatTime} from "../../../utils/TableConfig";
|
||||
import router from "../../../router";
|
||||
import myAxios from "../../../api/myAxios.ts";
|
||||
|
||||
const route = useRoute();
|
||||
//订单信息
|
||||
const tableData: any = ref([])
|
||||
//店铺信息
|
||||
const businessData: any = ref({})
|
||||
//订单总金额
|
||||
const ordersCount: any = ref<Number>()
|
||||
//加载按钮
|
||||
const loading = ref(false)
|
||||
//弹出框开关
|
||||
const modalOpen = ref<boolean>(false);
|
||||
//退款id
|
||||
const recordId = ref<Number>();
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
//查询条件
|
||||
const searchParams: any = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
orderId: null,
|
||||
searchTime: null,
|
||||
state: ''
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{title: '订单号', dataIndex: 'id', key: 'id', width: 100, fixed: 'left', align: 'center'},
|
||||
{
|
||||
title: '下单时间', dataIndex: 'createTime', key: 'createTime', width: 100, align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '卖家昵称', dataIndex: 'userName', key: 'userName', width: 150, align: 'center'},
|
||||
{title: '支付状态', dataIndex: 'state', key: 'state', width: 150, align: 'center'},
|
||||
{title: '订单金额', dataIndex: 'totalPrice', key: 'totalPrice', width: 150, align: 'center'},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 80, align: 'center'},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
getOrdersList(1)
|
||||
getBusinessVO()
|
||||
getOrdersCount()
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取订单信息列表
|
||||
*/
|
||||
const getOrdersList = async (current: any) => {
|
||||
let businessId = route.query.id; //商家id
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post('/orders/list/page', {
|
||||
businessId: businessId,
|
||||
errandId: "",
|
||||
current: current,
|
||||
pageSize: searchParams.value.pageSize,
|
||||
id: searchParams.value.orderId,
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend",
|
||||
state: searchParams.value.state,
|
||||
startTime: searchParams.value.searchTime == null ? '' : searchParams.value.searchTime[0],
|
||||
endTime: searchParams.value.searchTime == null ? '' : searchParams.value.searchTime[1]
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
searchParams.value.current = current
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺信息
|
||||
*/
|
||||
const getBusinessVO = async () => {
|
||||
let businessId = route.query.id; //商家id
|
||||
const res: any = await myAxios.get('/business/getById', {params: {"id": businessId}})
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
businessData.value = res.data;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
console.log(res)
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该店铺收入
|
||||
*/
|
||||
const getOrdersCount = async () => {
|
||||
let businessId = route.query.id; //商家id
|
||||
const res: any = await myAxios.post('/orders/count', {
|
||||
"businessId": businessId,
|
||||
"type": "money",
|
||||
"state": 5
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
ordersCount.value = res.data;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出Excel表
|
||||
*/
|
||||
const download = async () => {
|
||||
let businessId = route.query.id //商家id
|
||||
const res: any = await myAxios.post('/orders/download', {
|
||||
businessId: businessId,
|
||||
startTime: searchParams.value.searchTime?.[0] || '',
|
||||
endTime: searchParams.value.searchTime?.[1] || '',
|
||||
current: searchParams.value.current,
|
||||
pageSize: searchParams.value.pageSize,
|
||||
sortField: "createTime",
|
||||
sortOrder: "descend"
|
||||
},
|
||||
{
|
||||
responseType: "blob"
|
||||
}
|
||||
|
||||
)
|
||||
console.log(res)
|
||||
downloadCallback(res, '商家订单信息表.xlsx')
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
// const refund = async () => {
|
||||
// const res: any = await myAxios.get('/Alipay/test/refund', {orderNo: recordId.value})
|
||||
// if (res.code === 0 && res.data) {
|
||||
// message.success('退款成功');
|
||||
// modalOpen.value = false
|
||||
// await getOrdersList(1)
|
||||
// await getOrdersCount()
|
||||
// } else {
|
||||
// message.error(`退款失败:${res.message}`);
|
||||
// }
|
||||
// }
|
||||
const refund = async () => {
|
||||
const res: any = await myAxios.get(`/Alipay/test/refund?orderNo=${recordId.value}`);
|
||||
if (res.code === 0 && res.data) {
|
||||
message.success('退款成功');
|
||||
modalOpen.value = false;
|
||||
await getOrdersList(1);
|
||||
await getOrdersCount();
|
||||
} else {
|
||||
message.error(`退款失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
const onSearch = async (ordersId: number) => {
|
||||
searchParams.value.orderId = ordersId
|
||||
await getOrdersList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询时间
|
||||
*/
|
||||
const searchTime = async (dateTime: any) => {
|
||||
searchParams.value.searchTime = dateTime
|
||||
await getOrdersList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onShowSizeChange = (current: number, pageSize: number) => {
|
||||
searchParams.value.pageSize = pageSize;
|
||||
getOrdersList(current);
|
||||
}
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getOrdersList(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回
|
||||
*/
|
||||
const back = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
//生成下载文件
|
||||
const downloadCallback = (res: any, fileName: any) => {
|
||||
const blob = new Blob([res]);
|
||||
if ("download" in document.createElement("a")) {
|
||||
// 非IE下载
|
||||
const elink = document.createElement("a");
|
||||
elink.download = fileName;
|
||||
elink.style.display = "none";
|
||||
elink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(elink);
|
||||
elink.click();
|
||||
URL.revokeObjectURL(elink.href); // 释放URL 对象
|
||||
document.body.removeChild(elink);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
179
CampusExpressDelivery/src/view/shop/order/StoreList.vue
Normal file
@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space warp>
|
||||
<a-form-item
|
||||
label="店铺名"
|
||||
>
|
||||
<a-input allow-clear @change="change" @pressEnter="getBusinessList(1)"
|
||||
v-model:value="searchParams.businessName"
|
||||
placeholder="请输入店铺名"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="店铺地"
|
||||
>
|
||||
<a-input allow-clear @change="change" @pressEnter="getBusinessList(1)" v-model:value="searchParams.address"
|
||||
placeholder="请输入店铺地"/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
style="width: 200px;"
|
||||
placeholder="默认查询全部商家"
|
||||
allowClear
|
||||
v-model:value="searchParams.state"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option value=0>休业</a-select-option>
|
||||
<a-select-option value=1>营业</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-button type="primary" @click="getBusinessList(1)">查询</a-button>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1000, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'businessAvatar'">
|
||||
<a-avatar :src="record.businessAvatar"/>
|
||||
</template>
|
||||
<template v-if="column.key === 'state'">
|
||||
<div v-if="record.state === 0">
|
||||
<a-tag color="purple">休业中</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.state === 1">
|
||||
<a-tag color="blue">营业中</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small"
|
||||
type="link"
|
||||
style="color: rgba(255, 141, 26, 1);"
|
||||
@click="router.push({path: '/orderList',query: {id: record.id}})">查看
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 家店铺`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import myAxios from "../../../api/myAxios";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
import router from "../../../router";
|
||||
|
||||
//表单数据
|
||||
const tableData: any = ref([]);
|
||||
//加载按钮
|
||||
const loading = ref(false)
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
//查询条件
|
||||
const searchParams: any = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
businessName: '',
|
||||
address: '',
|
||||
state: null
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 60,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({index}: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{title: '图片', dataIndex: 'businessAvatar', key: 'businessAvatar', width: 30, align: 'center'},
|
||||
{title: '店铺名', dataIndex: 'businessName', key: 'businessName', width: 50, align: 'center'},
|
||||
{title: '店铺地', dataIndex: 'address', key: 'address', width: 150, align: 'center'},
|
||||
{title: '状态', dataIndex: 'state', key: 'state', width: 150, align: 'center'},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 50, align: 'center'},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
getBusinessList(1)
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取商家信息列表
|
||||
*/
|
||||
const getBusinessList = async (current: number) => {
|
||||
searchParams.value.current = current
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post('/business/list/page', {...searchParams.value})
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择用户身份
|
||||
*/
|
||||
const handleChange = (state: string) => {
|
||||
searchParams.value.state = state;
|
||||
getBusinessList(1)
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置查询条件
|
||||
*/
|
||||
const reset = () => {
|
||||
searchParams.value.businessName = ''
|
||||
searchParams.value.address = ''
|
||||
searchParams.value.state = null
|
||||
getBusinessList(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getBusinessList(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除输入框的回调
|
||||
*/
|
||||
const change = (row: any) => {
|
||||
if (row.type === 'click') getBusinessList(1)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
3
CampusExpressDelivery/src/view/system/BusinessInfo.vue
Normal file
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div>管理员根据商家发布的公告进行查看管理</div>
|
||||
</template>
|
160
CampusExpressDelivery/src/view/system/Carousel/Carousel.vue
Normal file
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<a-card :loading="loading">
|
||||
<div style="display: flex;justify-content: right;margin-bottom: 1%">
|
||||
<a-button type="primary" @click="showModal">增加</a-button>
|
||||
</div>
|
||||
<div style="display: flex;flex-wrap: wrap;">
|
||||
<div v-for="item in carouselData" style="margin: 1.8%">
|
||||
<a-card>
|
||||
<template #cover>
|
||||
<a-image :src="item?.content" style="width: 200px;height: 100px"/>
|
||||
</template>
|
||||
<template #actions>
|
||||
<a-button type="primary" danger @click="deleteCarousel(item.id)">删除</a-button>
|
||||
</template>
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
<div>
|
||||
<a-modal v-model:open="modalOpen" :afterClose="onClose" keyboard title="新增轮播图" @ok="submit">
|
||||
<a-upload
|
||||
style="margin: 5%"
|
||||
:max-count="1"
|
||||
name="avatar"
|
||||
:show-upload-list="false"
|
||||
:customRequest="handleChange"
|
||||
list-type="picture-card"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" alt="example" style="width: 100%"/>
|
||||
<div v-else>
|
||||
<div class="ant-upload-text">+</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
</a-modal>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import myAxios from "../../../api/myAxios.ts";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
//加载按钮
|
||||
const loading = ref(false)
|
||||
//轮播图信息
|
||||
const carouselData: any = ref({})
|
||||
//弹出框开关
|
||||
const modalOpen = ref<boolean>(false);
|
||||
//图片地址
|
||||
const imageUrl = ref('')
|
||||
|
||||
onMounted(() => {
|
||||
getCarousel()
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取轮播图列表
|
||||
*/
|
||||
const getCarousel = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post('/system/list', {
|
||||
type: 1
|
||||
})
|
||||
console.log(res)
|
||||
if (res.code === 0 && res.data) {
|
||||
loading.value = false;
|
||||
carouselData.value = res.data
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除轮播图
|
||||
*/
|
||||
const deleteCarousel = async (id: number) => {
|
||||
const res: any = await myAxios.post('/system/delete', {
|
||||
id: id
|
||||
})
|
||||
if (res.code !== 0) {
|
||||
message.error(`删除失败:${res.message}`);
|
||||
}
|
||||
await getCarousel()
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开弹出框
|
||||
*/
|
||||
const showModal = () => {
|
||||
if (carouselData.value.length > 7) {
|
||||
message.error(`添加失败,轮播图不能大于8张`);
|
||||
return
|
||||
}
|
||||
modalOpen.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭弹出框
|
||||
*/
|
||||
const onClose = () => {
|
||||
imageUrl.value = ""
|
||||
modalOpen.value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
const handleChange = async (row: any) => {
|
||||
let formData = new FormData()
|
||||
formData.append("file", row.file)
|
||||
const result = await myAxios({
|
||||
url: '/file/upload/server',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: {
|
||||
//biz: "user_avatar",
|
||||
biz: "system",
|
||||
// 需根据名字取出,否则为空
|
||||
file: formData.get("file")
|
||||
}
|
||||
})
|
||||
// 传出图片地址
|
||||
if (result.data) {
|
||||
imageUrl.value = result.data
|
||||
} else {
|
||||
message.error(`图片上传失败`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 确认添加
|
||||
*/
|
||||
const submit = async () => {
|
||||
if (imageUrl.value === '' || undefined) {
|
||||
message.error(`请上传图片`);
|
||||
return
|
||||
}
|
||||
const res: any = await myAxios.post('/system/add', {
|
||||
type: 1,
|
||||
content: imageUrl.value
|
||||
})
|
||||
if (res.code !== 0) {
|
||||
message.error(`更新失败:${res.message}`);
|
||||
}
|
||||
await getCarousel()
|
||||
modalOpen.value = false;
|
||||
imageUrl.value = '';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
193
CampusExpressDelivery/src/view/system/Category.vue
Normal file
@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<div class="middle-button">
|
||||
<a-button type="primary" @click="showDrawer">添加</a-button>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:rowKey="(record: any) => record.id"
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'image'">
|
||||
<a-avatar :src="record.image"/>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small" type="link" danger @click="handleDelete(record.id)">删除</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-drawer
|
||||
:destroyOnClose="true"
|
||||
title="添加分类"
|
||||
placement="right"
|
||||
:closable="false"
|
||||
:visible="visible"
|
||||
@close="onClose"
|
||||
>
|
||||
<a-form :model="drawerData" :rules="rules" layout="vertical">
|
||||
<a-form-item name="content">
|
||||
<a-input v-model:value="drawerData.name" placeholder="请输入分类名称"/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-upload
|
||||
style="margin: 5%"
|
||||
:max-count="1"
|
||||
name="avatar"
|
||||
:show-upload-list="false"
|
||||
:customRequest="upload"
|
||||
list-type="picture-card"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img v-if="drawerData.image" :src="drawerData.image" alt="example" style="width: 100%"/>
|
||||
<div v-else>
|
||||
<div class="ant-upload-text">+</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" @click="onSubmit">确认</a-button>
|
||||
</a-drawer>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {formatTime} from "../../utils/TableConfig";
|
||||
import myAxios from "../../api/myAxios";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false)
|
||||
// 抽屉开关
|
||||
const visible = ref<boolean>(false);
|
||||
// 抽屉数据
|
||||
const drawerData: any = ref({})
|
||||
|
||||
const columns: any = [
|
||||
{title: '分类名', dataIndex: 'name', width: 30, align: 'center'},
|
||||
{title: '分类图片', key: 'image', width: 30, align: 'center'},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 30,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 30, align: 'center'},
|
||||
];
|
||||
|
||||
const rules = {
|
||||
name: [{required: true, message: '请输入分类名称'}],
|
||||
image: [{required: true, message: '请输入分类图片'}],
|
||||
};
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getCategoryList();
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取分类列表
|
||||
*/
|
||||
const getCategoryList = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.get("/category/list");
|
||||
console.log(res)
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data;
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
const upload = async (row: any) => {
|
||||
let formData = new FormData()
|
||||
formData.append("file", row.file)
|
||||
const result = await myAxios({
|
||||
url: '/file/upload/server',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: {
|
||||
biz: "system",
|
||||
// 需根据名字取出,否则为空
|
||||
file: formData.get("file")
|
||||
}
|
||||
})
|
||||
// 传出图片地址
|
||||
if (result.data) {
|
||||
drawerData.value.image = result.data
|
||||
console.log(drawerData.value.image)
|
||||
} else {
|
||||
message.error(`图片上传失败`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽屉
|
||||
*/
|
||||
const showDrawer = () => {
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭弹出框
|
||||
*/
|
||||
const onClose = () => {
|
||||
drawerData.value = ref({})
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
const res: any = await myAxios.post('/category/add', {
|
||||
name: drawerData.value.name,
|
||||
image: drawerData.value.image
|
||||
})
|
||||
console.log(res)
|
||||
if (res.code === 0) {
|
||||
drawerData.value = ref('')
|
||||
await getCategoryList()
|
||||
message.success('添加分类成功')
|
||||
} else {
|
||||
message.error(`添加分类失败:${res.message}`);
|
||||
}
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
const handleDelete = async (id: any) => {
|
||||
const res: any = await myAxios.post("/category/delete", {id: id});
|
||||
if (res.code === 0 && res.data) {
|
||||
await getCategoryList();
|
||||
message.success(`删除成功`);
|
||||
} else {
|
||||
message.error(`删除分类失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
145
CampusExpressDelivery/src/view/system/Info.vue
Normal file
@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<div class="middle-button">
|
||||
<a-button type="primary" @click="showDrawer">添加</a-button>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:rowKey="(record: any) => record.id"
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button size="small" type="link" danger @click="handleDelete(record.id)">删除</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-drawer
|
||||
:destroyOnClose="true"
|
||||
title="添加公告"
|
||||
placement="right"
|
||||
:closable="false"
|
||||
:visible="visible"
|
||||
@close="visible=false;drawerData = {}"
|
||||
>
|
||||
<a-form :model="drawerData" :rules="rules" layout="vertical">
|
||||
<a-form-item name="content">
|
||||
<a-textarea
|
||||
v-model:value="drawerData.content"
|
||||
placeholder="请输入公告信息"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" @click="onSubmit">确认</a-button>
|
||||
</a-drawer>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import {formatTime} from "../../utils/TableConfig";
|
||||
import myAxios from "../../api/myAxios";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false)
|
||||
// 抽屉开关
|
||||
const visible = ref<boolean>(false);
|
||||
// 抽屉数据
|
||||
const drawerData: any = ref({})
|
||||
|
||||
const columns: any = [
|
||||
{title: '公告内容', dataIndex: 'content', width: 100, align: 'center'},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 50,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 30, align: 'center'},
|
||||
];
|
||||
|
||||
const rules = {
|
||||
content: [{required: true, message: '请输入公告信息'}],
|
||||
};
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getInfoList();
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取公告列表
|
||||
*/
|
||||
const getInfoList = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post("/system/list", {type: 0});
|
||||
if (res.code === 0 && res.data) {
|
||||
tableData.value = res.data;
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽屉
|
||||
*/
|
||||
const showDrawer = () => {
|
||||
visible.value = true;
|
||||
};
|
||||
const onClose = () => {
|
||||
drawerData.value = {}
|
||||
visible.value = false;
|
||||
};
|
||||
const onSubmit = async () => {
|
||||
if (drawerData.value.content?.indexOf(' ') !== -1 || drawerData.value.content == '') {
|
||||
message.error(`格式错误,不允许存在空格`);
|
||||
return
|
||||
}
|
||||
const res: any = await myAxios.post('/system/add', {
|
||||
type: 0,
|
||||
content: drawerData.value.content
|
||||
})
|
||||
if (res.code === 0) {
|
||||
drawerData.value = {}
|
||||
await getInfoList()
|
||||
message.success('添加公告成功')
|
||||
} else {
|
||||
message.error(`添加公告失败:${res.message}`);
|
||||
}
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
const handleDelete = async (id: any) => {
|
||||
const res: any = await myAxios.post("/system/delete", {id: id});
|
||||
if (res.code === 0 && res.data) {
|
||||
await getInfoList();
|
||||
message.success(`删除成功`);
|
||||
} else {
|
||||
message.error(`删除公告失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
222
CampusExpressDelivery/src/view/user/UserList.vue
Normal file
@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<a-card>
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-box">
|
||||
<a-form layout="inline">
|
||||
<a-space>
|
||||
<a-form-item label="身份">
|
||||
<a-select
|
||||
style="width: 200px;"
|
||||
placeholder="默认查询全部用户"
|
||||
allowClear
|
||||
v-model:value="searchParams.userRole"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-select-option value="user">普通用户</a-select-option>
|
||||
<a-select-option value="business">商家用户</a-select-option>
|
||||
<a-select-option value="errand">快送员</a-select-option>
|
||||
<a-select-option value="admin">管理员</a-select-option>
|
||||
<a-select-option value="ban">已封禁</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="用户昵称">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入用户昵称"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearch"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号">
|
||||
<a-input-search
|
||||
style="width: 300px"
|
||||
placeholder="请输入手机号"
|
||||
enter-button
|
||||
allow-clear
|
||||
@search="onSearchPhone"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<!-- 数据展示部分 -->
|
||||
<a-table
|
||||
:scroll="{ x: 1500, y: 1000 }"
|
||||
:data-source="tableData"
|
||||
:columns="columns"
|
||||
:pagination=false
|
||||
:loading="loading"
|
||||
bordered
|
||||
class="data-box"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'avatarUrl'">
|
||||
<a-avatar :src="record.avatarUrl"/>
|
||||
</template>
|
||||
<template v-if="column.key === 'userRole'">
|
||||
<div v-if="record.userRole === 'boss'">
|
||||
<a-tag color="purple">Boss</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.userRole === 'admin'">
|
||||
<a-tag color="blue">管理员</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.userRole === 'user'">
|
||||
<a-tag color="green">普通用户</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.userRole === 'errand'">
|
||||
<a-tag color="yellow">快送员</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.userRole === 'business'">
|
||||
<a-tag color="orange">商家</a-tag>
|
||||
</div>
|
||||
<div v-else-if="record.userRole === 'ban'">
|
||||
<a-tag color="red">已封禁</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.key === '操作'">
|
||||
<a-space>
|
||||
<a-button :disabled="validRole(record.userRole)"
|
||||
size="small" type="link" danger @click="doBan(record.id, record.userRole === 'user')">
|
||||
{{ record.userRole === 'ban' ? '解封' : '封禁' }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- 分页部分 -->
|
||||
<div class="pagination">
|
||||
<a-pagination v-model:current="searchParams.current"
|
||||
v-model:pageSize="searchParams.pageSize"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
:show-total="(total: any) => `共 ${total} 人`"
|
||||
:total="total"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
import myAxios from "../../api/myAxios.ts";
|
||||
import {message} from "ant-design-vue";
|
||||
import {formatTime} from "../../utils/TableConfig.ts";
|
||||
|
||||
|
||||
const tableData: any = ref([]);
|
||||
const loading = ref(false)
|
||||
// 分页
|
||||
const total: any = ref(0);
|
||||
// 请求参数
|
||||
const searchParams: any = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
userRole: null,
|
||||
})
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 40,
|
||||
fixed: 'left',
|
||||
align: 'center',
|
||||
customRender: ({index}: any) => {
|
||||
return `${(searchParams.value.current - 1) * searchParams.value.pageSize + index + 1}`;
|
||||
}
|
||||
},
|
||||
{title: '用户昵称', dataIndex: 'userAccount', width: 50, key: 'userAccount', fixed: 'left', align: 'center'},
|
||||
{title: '头像', dataIndex: 'avatarUrl', key: 'avatarUrl', width: 30, align: 'center'},
|
||||
{title: '身份', dataIndex: 'userRole', key: 'userRole', width: 50, align: 'center'},
|
||||
{title: '手机号', dataIndex: 'phone', key: 'phone', width: 50, align: 'center'},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
customRender: (row: any) => {
|
||||
return formatTime(row)
|
||||
}
|
||||
},
|
||||
{title: '操作', key: '操作', fixed: 'right', width: 30, align: 'center'},
|
||||
];
|
||||
|
||||
/**
|
||||
* 页面加载时,请求数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getUserList();
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取用户数据
|
||||
*/
|
||||
const getUserList = async () => {
|
||||
loading.value = true;
|
||||
const res: any = await myAxios.post("/user/list/page", {...searchParams.value})
|
||||
if (res.code === 0 && res.data) {
|
||||
console.log(res)
|
||||
tableData.value = res.data.records;
|
||||
total.value = parseInt(res.data.total);
|
||||
loading.value = false;
|
||||
} else {
|
||||
message.error(`获取数据失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
const doBan = async (id: string, isBan: boolean) => {
|
||||
const res: any = await myAxios.post("/user/update", {id: id, userRole: isBan ? 'ban' : 'user'})
|
||||
if (res.code === 0 && res.data) {
|
||||
message.success(`操作成功`);
|
||||
await getUserList();
|
||||
} else {
|
||||
message.error(`封禁用户失败:${res.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择用户身份
|
||||
*/
|
||||
const handleChange = (userRole: string) => {
|
||||
searchParams.value.userRole = userRole;
|
||||
searchParams.value.current = 1;
|
||||
getUserList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
const onSearch = (data: string) => {
|
||||
searchParams.value.userAccount = data;
|
||||
searchParams.value.current = 1;
|
||||
getUserList();
|
||||
}
|
||||
const onSearchPhone = (data: string) => {
|
||||
searchParams.value.phone = data;
|
||||
searchParams.value.current = 1;
|
||||
getUserList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
const onChange = (pageNumber: number) => {
|
||||
searchParams.value.current = pageNumber;
|
||||
getUserList();
|
||||
}
|
||||
|
||||
// 判断用户权限
|
||||
const validRole = (userRole: string) => {
|
||||
return !(userRole === 'user' || userRole === 'ban');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
10
CampusExpressDelivery/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/// <reference types="vite/client" />
|
||||
declare module '*.vue' {
|
||||
import type {DefineComponent} from 'vue'
|
||||
const vueComponent: DefineComponent<{}, {}, any>
|
||||
export default vueComponent
|
||||
}
|
||||
declare module '*.mjs'
|
||||
declare module 'dayjs'
|
||||
|
||||
|
26
CampusExpressDelivery/tsconfig.app.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "Bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
25
CampusExpressDelivery/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
11
CampusExpressDelivery/tsconfig.node.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
1
CampusExpressDelivery/tsconfig.node.tsbuildinfo
Normal file
1
CampusExpressDelivery/tsconfig.tsbuildinfo
Normal file
@ -0,0 +1 @@
|
||||
{"root":["./src/main.ts","./src/vite-env.d.ts","./src/api/myaxios.ts","./src/router/index.ts","./src/router/routes.ts","./src/store/index.ts","./src/store/userstore.ts","./src/utils/tableconfig.ts","./src/app.vue","./src/layout/managelayout.vue","./src/layout/manage/manageheader.vue","./src/layout/manage/managesidebar.vue","./src/view/index.vue","./src/view/login.vue","./src/view/test.vue","./src/view/service/customerservice.vue","./src/view/echarts/brokenline.vue","./src/view/echarts/ordermethod.vue","./src/view/errand/errandinfo.vue","./src/view/errand/errandlist.vue","./src/view/errand/errandorderlist.vue","./src/view/errand/runlist.vue","./src/view/shop/businesslog.vue","./src/view/shop/business/businessinfo.vue","./src/view/shop/business/businessmanage.vue","./src/view/shop/business/dish.vue","./src/view/shop/business/dishgroup.vue","./src/view/shop/order/orderdetail.vue","./src/view/shop/order/orderlist.vue","./src/view/shop/order/storelist.vue","./src/view/system/businessinfo.vue","./src/view/system/category.vue","./src/view/system/info.vue","./src/view/system/carousel/carousel.vue","./src/view/user/userlist.vue"],"version":"5.6.3"}
|
2
CampusExpressDelivery/vite.config.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
declare const _default: import("vite").UserConfig;
|
||||
export default _default;
|
40
CampusExpressDelivery/vite.config.js
Normal file
@ -0,0 +1,40 @@
|
||||
// import {defineConfig} from 'vite'
|
||||
// import vue from '@vitejs/plugin-vue'
|
||||
// import Components from 'unplugin-vue-components/vite';
|
||||
// import {AntDesignVueResolver} from "unplugin-vue-components/resolvers";
|
||||
//
|
||||
//
|
||||
// export default defineConfig({
|
||||
// plugins: [vue(),
|
||||
// Components({
|
||||
// resolvers: [
|
||||
// AntDesignVueResolver({
|
||||
// importStyle: false, // css in js
|
||||
// }),
|
||||
// ],
|
||||
// }),],
|
||||
// })
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [
|
||||
AntDesignVueResolver({
|
||||
importStyle: false, // css in js
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
// server: {
|
||||
// https: true,
|
||||
// https: {
|
||||
// key: fs.readFileSync('/SSL/xiaokuaisong.shop.key'),
|
||||
// cert: fs.readFileSync('/SSL/xiaokuaisong.shop.pem'),
|
||||
// },
|
||||
// },
|
||||
});
|
41
CampusExpressDelivery/vite.config.ts
Normal file
@ -0,0 +1,41 @@
|
||||
// import {defineConfig} from 'vite'
|
||||
// import vue from '@vitejs/plugin-vue'
|
||||
// import Components from 'unplugin-vue-components/vite';
|
||||
// import {AntDesignVueResolver} from "unplugin-vue-components/resolvers";
|
||||
//
|
||||
//
|
||||
// export default defineConfig({
|
||||
// plugins: [vue(),
|
||||
// Components({
|
||||
// resolvers: [
|
||||
// AntDesignVueResolver({
|
||||
// importStyle: false, // css in js
|
||||
// }),
|
||||
// ],
|
||||
// }),],
|
||||
// })
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [
|
||||
AntDesignVueResolver({
|
||||
importStyle: false, // css in js
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
// server: {
|
||||
// https: true,
|
||||
// https: {
|
||||
// key: fs.readFileSync('/SSL/xiaokuaisong.shop.key'),
|
||||
// cert: fs.readFileSync('/SSL/xiaokuaisong.shop.pem'),
|
||||
// },
|
||||
// },
|
||||
})
|