后台管理系统
This commit is contained in:
parent
5aa0643b94
commit
25319d4122
|
@ -12,6 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"axios": "^1.7.2",
|
||||
"element-plus": "^2.7.6",
|
||||
"pinia": "^2.1.7",
|
||||
|
|
325
pnpm-lock.yaml
325
pnpm-lock.yaml
|
@ -11,6 +11,9 @@ importers:
|
|||
'@element-plus/icons-vue':
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1(vue@3.5.10)
|
||||
'@vueup/vue-quill':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0(vue@3.5.10)
|
||||
axios:
|
||||
specifier: ^1.7.2
|
||||
version: 1.7.2
|
||||
|
@ -459,6 +462,11 @@ packages:
|
|||
'@vue/shared@3.5.10':
|
||||
resolution: {integrity: sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==}
|
||||
|
||||
'@vueup/vue-quill@1.2.0':
|
||||
resolution: {integrity: sha512-kd5QPSHMDpycklojPXno2Kw2JSiKMYduKYQckTm1RJoVDA557MnyUXgcuuDpry4HY/Rny9nGNcK+m3AHk94wag==}
|
||||
peerDependencies:
|
||||
vue: ^3.2.41
|
||||
|
||||
'@vueuse/core@9.13.0':
|
||||
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
|
||||
|
||||
|
@ -525,6 +533,18 @@ packages:
|
|||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bind@1.0.8:
|
||||
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bound@1.0.3:
|
||||
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -537,6 +557,10 @@ packages:
|
|||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
clone@2.1.2:
|
||||
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
@ -578,9 +602,21 @@ packages:
|
|||
supports-color:
|
||||
optional: true
|
||||
|
||||
deep-equal@1.1.2:
|
||||
resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
define-data-property@1.1.4:
|
||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
define-properties@1.2.1:
|
||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
@ -589,6 +625,10 @@ packages:
|
|||
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
element-plus@2.7.6:
|
||||
resolution: {integrity: sha512-36sw1K23hYjgeooR10U6CiCaCp2wvOqwoFurADZVlekeQ9v5U1FhJCFGEXO6i/kZBBMwsE1c9fxjLs9LENw2Rg==}
|
||||
peerDependencies:
|
||||
|
@ -598,6 +638,18 @@ packages:
|
|||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
es-define-property@1.0.1:
|
||||
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-errors@1.3.0:
|
||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-object-atoms@1.0.0:
|
||||
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild@0.21.5:
|
||||
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -679,9 +731,21 @@ packages:
|
|||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
eventemitter3@2.0.3:
|
||||
resolution: {integrity: sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==}
|
||||
|
||||
extend@3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
|
||||
fast-diff@1.1.2:
|
||||
resolution: {integrity: sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==}
|
||||
|
||||
fast-diff@1.2.0:
|
||||
resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==}
|
||||
|
||||
fast-diff@1.3.0:
|
||||
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
|
||||
|
||||
|
@ -738,6 +802,16 @@ packages:
|
|||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
functions-have-names@1.2.3:
|
||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||
|
||||
get-intrinsic@1.2.6:
|
||||
resolution: {integrity: sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -754,6 +828,10 @@ packages:
|
|||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
gopd@1.2.0:
|
||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
|
@ -761,6 +839,21 @@ packages:
|
|||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
has-property-descriptors@1.0.2:
|
||||
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
|
||||
|
||||
has-symbols@1.1.0:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ignore@5.3.1:
|
||||
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
|
||||
engines: {node: '>= 4'}
|
||||
|
@ -783,10 +876,18 @@ packages:
|
|||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
is-arguments@1.2.0:
|
||||
resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-date-object@1.1.0:
|
||||
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-extglob@2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -803,6 +904,10 @@ packages:
|
|||
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-regex@1.2.1:
|
||||
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
|
@ -847,6 +952,12 @@ packages:
|
|||
lodash: '*'
|
||||
lodash-es: '*'
|
||||
|
||||
lodash.clonedeep@4.5.0:
|
||||
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
|
||||
|
||||
lodash.isequal@4.5.0:
|
||||
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
|
||||
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
|
@ -859,6 +970,10 @@ packages:
|
|||
magic-string@0.30.11:
|
||||
resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
memoize-one@6.0.0:
|
||||
resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
|
||||
|
||||
|
@ -909,6 +1024,14 @@ packages:
|
|||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
object-is@1.1.6:
|
||||
resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
object-keys@1.1.1:
|
||||
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
|
@ -924,6 +1047,9 @@ packages:
|
|||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
parchment@1.1.4:
|
||||
resolution: {integrity: sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==}
|
||||
|
||||
parent-module@1.0.1:
|
||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -1013,10 +1139,24 @@ packages:
|
|||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
quill-delta@3.6.3:
|
||||
resolution: {integrity: sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
quill-delta@4.2.2:
|
||||
resolution: {integrity: sha512-qjbn82b/yJzOjstBgkhtBjN2TNK+ZHP/BgUQO+j6bRhWQQdmj2lH6hXG7+nwwLF41Xgn//7/83lxs9n2BkTtTg==}
|
||||
|
||||
quill@1.3.7:
|
||||
resolution: {integrity: sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==}
|
||||
|
||||
readdirp@3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
regexp.prototype.flags@1.5.3:
|
||||
resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
resolve-from@4.0.0:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -1051,6 +1191,14 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
set-function-length@1.2.2:
|
||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
set-function-name@2.0.2:
|
||||
resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1533,6 +1681,12 @@ snapshots:
|
|||
|
||||
'@vue/shared@3.5.10': {}
|
||||
|
||||
'@vueup/vue-quill@1.2.0(vue@3.5.10)':
|
||||
dependencies:
|
||||
quill: 1.3.7
|
||||
quill-delta: 4.2.2
|
||||
vue: 3.5.10
|
||||
|
||||
'@vueuse/core@9.13.0(vue@3.5.10)':
|
||||
dependencies:
|
||||
'@types/web-bluetooth': 0.0.16
|
||||
|
@ -1609,6 +1763,23 @@ snapshots:
|
|||
dependencies:
|
||||
fill-range: 7.1.1
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
call-bind@1.0.8:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
es-define-property: 1.0.1
|
||||
get-intrinsic: 1.2.6
|
||||
set-function-length: 1.2.2
|
||||
|
||||
call-bound@1.0.3:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
get-intrinsic: 1.2.6
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
chalk@4.1.2:
|
||||
|
@ -1628,6 +1799,8 @@ snapshots:
|
|||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
clone@2.1.2: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
@ -1658,14 +1831,41 @@ snapshots:
|
|||
dependencies:
|
||||
ms: 2.1.2
|
||||
|
||||
deep-equal@1.1.2:
|
||||
dependencies:
|
||||
is-arguments: 1.2.0
|
||||
is-date-object: 1.1.0
|
||||
is-regex: 1.2.1
|
||||
object-is: 1.1.6
|
||||
object-keys: 1.1.1
|
||||
regexp.prototype.flags: 1.5.3
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
define-data-property@1.1.4:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
define-properties@1.2.1:
|
||||
dependencies:
|
||||
define-data-property: 1.1.4
|
||||
has-property-descriptors: 1.0.2
|
||||
object-keys: 1.1.1
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
doctrine@3.0.0:
|
||||
dependencies:
|
||||
esutils: 2.0.3
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
element-plus@2.7.6(vue@3.5.10):
|
||||
dependencies:
|
||||
'@ctrl/tinycolor': 3.6.1
|
||||
|
@ -1689,6 +1889,14 @@ snapshots:
|
|||
|
||||
entities@4.5.0: {}
|
||||
|
||||
es-define-property@1.0.1: {}
|
||||
|
||||
es-errors@1.3.0: {}
|
||||
|
||||
es-object-atoms@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
esbuild@0.21.5:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.21.5
|
||||
|
@ -1822,8 +2030,16 @@ snapshots:
|
|||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
eventemitter3@2.0.3: {}
|
||||
|
||||
extend@3.0.2: {}
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
fast-diff@1.1.2: {}
|
||||
|
||||
fast-diff@1.2.0: {}
|
||||
|
||||
fast-diff@1.3.0: {}
|
||||
|
||||
fast-glob@3.3.2:
|
||||
|
@ -1876,6 +2092,23 @@ snapshots:
|
|||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
functions-have-names@1.2.3: {}
|
||||
|
||||
get-intrinsic@1.2.6:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
dunder-proto: 1.0.1
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.0.0
|
||||
function-bind: 1.1.2
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
@ -1897,10 +2130,26 @@ snapshots:
|
|||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-property-descriptors@1.0.2:
|
||||
dependencies:
|
||||
es-define-property: 1.0.1
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
has-tostringtag@1.0.2:
|
||||
dependencies:
|
||||
has-symbols: 1.1.0
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
ignore@5.3.1: {}
|
||||
|
||||
immutable@4.3.6: {}
|
||||
|
@ -1919,10 +2168,20 @@ snapshots:
|
|||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
is-arguments@1.2.0:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
has-tostringtag: 1.0.2
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
dependencies:
|
||||
binary-extensions: 2.3.0
|
||||
|
||||
is-date-object@1.1.0:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
has-tostringtag: 1.0.2
|
||||
|
||||
is-extglob@2.1.1: {}
|
||||
|
||||
is-glob@4.0.3:
|
||||
|
@ -1933,6 +2192,13 @@ snapshots:
|
|||
|
||||
is-path-inside@3.0.3: {}
|
||||
|
||||
is-regex@1.2.1:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
gopd: 1.2.0
|
||||
has-tostringtag: 1.0.2
|
||||
hasown: 2.0.2
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
js-tokens@9.0.0: {}
|
||||
|
@ -1973,6 +2239,10 @@ snapshots:
|
|||
lodash: 4.17.21
|
||||
lodash-es: 4.17.21
|
||||
|
||||
lodash.clonedeep@4.5.0: {}
|
||||
|
||||
lodash.isequal@4.5.0: {}
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
@ -1985,6 +2255,8 @@ snapshots:
|
|||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
memoize-one@6.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
@ -2029,6 +2301,13 @@ snapshots:
|
|||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
||||
object-is@1.1.6:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
define-properties: 1.2.1
|
||||
|
||||
object-keys@1.1.1: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
@ -2050,6 +2329,8 @@ snapshots:
|
|||
dependencies:
|
||||
p-limit: 3.1.0
|
||||
|
||||
parchment@1.1.4: {}
|
||||
|
||||
parent-module@1.0.1:
|
||||
dependencies:
|
||||
callsites: 3.1.0
|
||||
|
@ -2117,10 +2398,38 @@ snapshots:
|
|||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
quill-delta@3.6.3:
|
||||
dependencies:
|
||||
deep-equal: 1.1.2
|
||||
extend: 3.0.2
|
||||
fast-diff: 1.1.2
|
||||
|
||||
quill-delta@4.2.2:
|
||||
dependencies:
|
||||
fast-diff: 1.2.0
|
||||
lodash.clonedeep: 4.5.0
|
||||
lodash.isequal: 4.5.0
|
||||
|
||||
quill@1.3.7:
|
||||
dependencies:
|
||||
clone: 2.1.2
|
||||
deep-equal: 1.1.2
|
||||
eventemitter3: 2.0.3
|
||||
extend: 3.0.2
|
||||
parchment: 1.1.4
|
||||
quill-delta: 3.6.3
|
||||
|
||||
readdirp@3.6.0:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
regexp.prototype.flags@1.5.3:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
define-properties: 1.2.1
|
||||
es-errors: 1.3.0
|
||||
set-function-name: 2.0.2
|
||||
|
||||
resolve-from@4.0.0: {}
|
||||
|
||||
reusify@1.0.4: {}
|
||||
|
@ -2165,6 +2474,22 @@ snapshots:
|
|||
|
||||
semver@7.6.2: {}
|
||||
|
||||
set-function-length@1.2.2:
|
||||
dependencies:
|
||||
define-data-property: 1.1.4
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
get-intrinsic: 1.2.6
|
||||
gopd: 1.2.0
|
||||
has-property-descriptors: 1.0.2
|
||||
|
||||
set-function-name@2.0.2:
|
||||
dependencies:
|
||||
define-data-property: 1.1.4
|
||||
es-errors: 1.3.0
|
||||
functions-have-names: 1.2.3
|
||||
has-property-descriptors: 1.0.2
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
shebang-regex: 3.0.0
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
|
@ -1,31 +1,30 @@
|
|||
<script setup>
|
||||
defineProps({
|
||||
title: {
|
||||
Required: true,
|
||||
type: String,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card style="height: 100%">
|
||||
<el-card style="height: 100%; width: 100%;">
|
||||
<template #header>
|
||||
<div class="header">
|
||||
<span>{{ title }}</span>
|
||||
<div>
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
<div>
|
||||
<slot name="search"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<div style="height: calc(100% - 48px);">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
height: 30px;
|
||||
height: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
:deep().el-card__body {
|
||||
height: calc(100% - 68px);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const imageUrl = ref('')
|
||||
const onSelectFile = (file) => {
|
||||
// 预览图片
|
||||
imageUrl.value = URL.createObjectURL(file.raw)
|
||||
articleForm.value.url = file.raw
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="onSelectFile"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
|
||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 图片上传框样式
|
||||
.avatar-uploader {
|
||||
:deep() {
|
||||
.avatar {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -11,12 +11,8 @@ const router = createRouter({
|
|||
{
|
||||
path: '/',
|
||||
component: () => import('../views/2_layout/Layout.vue'),
|
||||
redirect: '/homePage',
|
||||
redirect: '/hospital',
|
||||
children: [
|
||||
{
|
||||
path: '/homePage',
|
||||
component: () => import('../views/3_homePage/HomePage.vue')
|
||||
},
|
||||
{
|
||||
path: '/hospital',
|
||||
component: () => import('../views/4_hospital/Hospital.vue')
|
||||
|
@ -32,6 +28,10 @@ const router = createRouter({
|
|||
{
|
||||
path: '/userInfo',
|
||||
component: () => import('../views/7_userInfo/UserInfo.vue')
|
||||
},
|
||||
{
|
||||
path: '/appoint',
|
||||
component: () => import('../views/8_appoint/Appoint.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ export const useUserStore = defineStore(
|
|||
}
|
||||
const user = ref({})
|
||||
const getUser = async() => {
|
||||
const res = await userGetInfoService()
|
||||
user.value = res.data.data
|
||||
// const res = await userGetInfoService()
|
||||
// user.value = res.data.data
|
||||
}
|
||||
const setUser = (newUser) => {
|
||||
user.value = newUser
|
||||
|
|
|
@ -131,7 +131,7 @@ const getVerification = async () => {
|
|||
border-radius: 50%;
|
||||
margin-top: 16px;
|
||||
opacity: 0.8;
|
||||
background: url('@/assets/logo.png') center / cover;
|
||||
background: url('/logo.png') center / cover;
|
||||
}
|
||||
.button {
|
||||
width: 100%;
|
||||
|
|
|
@ -1,71 +1,101 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import {
|
||||
Management,
|
||||
Promotion,
|
||||
UserFilled,
|
||||
Avatar,
|
||||
CirclePlusFilled
|
||||
CirclePlusFilled,
|
||||
List,
|
||||
Expand,
|
||||
Fold
|
||||
} from '@element-plus/icons-vue'
|
||||
import avatar from '@/assets/default.png'
|
||||
import { useUserStore } from '@/stores'
|
||||
import { onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const isCollapse = ref(false)
|
||||
|
||||
// 视口宽度变化时,菜单栏自动收起
|
||||
const handleResize = () => {
|
||||
if (document.documentElement.clientWidth <= 768) {
|
||||
isCollapse.value = true
|
||||
} else {
|
||||
isCollapse.value = false
|
||||
}
|
||||
}
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
// 获取用户信息
|
||||
onMounted(() => {
|
||||
userStore.getUser()
|
||||
handleResize()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-container class="layout-container">
|
||||
<el-aside width="200px">
|
||||
<div class="el-aside__logo"></div>
|
||||
<el-menu
|
||||
class="el-menu"
|
||||
active-text-color="#409EFF"
|
||||
background-color="#444"
|
||||
:default-active="$route.path"
|
||||
text-color="#fff"
|
||||
router
|
||||
>
|
||||
<el-menu-item index="/homePage">
|
||||
<el-icon><Promotion /></el-icon>
|
||||
<span>首页</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/hospital">
|
||||
<el-icon><CirclePlusFilled /></el-icon>
|
||||
<span>医院管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/doctor">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
<span>医生管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/article">
|
||||
<el-icon><Management /></el-icon>
|
||||
<span>医说管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/userInfo">
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<span>用户信息管理</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-menu
|
||||
class="el-menu el-menu-vertical-demo"
|
||||
:collapse="isCollapse"
|
||||
:default-active="$route.path"
|
||||
active-text-color="#409EFF"
|
||||
background-color="#444"
|
||||
text-color="#fff"
|
||||
router
|
||||
>
|
||||
<div class="logo"></div>
|
||||
<el-menu-item index="/hospital">
|
||||
<el-icon><CirclePlusFilled /></el-icon>
|
||||
<span>医院管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/doctor">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
<span>医生管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/article">
|
||||
<el-icon><Management /></el-icon>
|
||||
<span>文章管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/appoint">
|
||||
<el-icon><List /></el-icon>
|
||||
<span>预约管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/userInfo">
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<span>用户信息管理</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<el-container>
|
||||
<el-header>
|
||||
<div>
|
||||
后台管理员:<strong>{{ userStore.user.name }}</strong>
|
||||
<div style="display: flex; font-size: 20px">
|
||||
<span
|
||||
@click="isCollapse = !isCollapse"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 16px;
|
||||
cursor: pointer;
|
||||
"
|
||||
>
|
||||
<el-icon v-if="!isCollapse" size="24"><Fold /></el-icon>
|
||||
<el-icon v-else size="24"><Expand /></el-icon>
|
||||
</span>
|
||||
<strong>后台管理员:{{ userStore.user.name || 'admin' }}</strong>
|
||||
</div>
|
||||
<el-avatar :src="userStore.user.avatarUrl || avatar" />
|
||||
</el-header>
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="scale" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="scale" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</el-config-provider>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
|
@ -74,15 +104,17 @@ onMounted(() => {
|
|||
<style lang="scss" scoped>
|
||||
.layout-container {
|
||||
height: 100vh;
|
||||
.el-aside {
|
||||
background-color: #444;
|
||||
&__logo {
|
||||
height: 120px;
|
||||
width: 100%;
|
||||
background: url('@/assets/logo.png') no-repeat center / 80px auto;
|
||||
}
|
||||
:deep().el-menu {
|
||||
border: none;
|
||||
.logo {
|
||||
height: 100px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 4px;
|
||||
background: url('/logo.png') no-repeat center / 50%;
|
||||
}
|
||||
:deep() .el-menu {
|
||||
width: auto;
|
||||
.el-menu-item {
|
||||
padding-left: 30px !important;
|
||||
padding-right: 30px !important;
|
||||
}
|
||||
}
|
||||
.el-header {
|
||||
|
@ -111,3 +143,26 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--
|
||||
<el-menu-item index="/hospital">
|
||||
<el-icon><CirclePlusFilled /></el-icon>
|
||||
<template #title>医院管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/doctor">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
<template #title>医生管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/article">
|
||||
<el-icon><Management /></el-icon>
|
||||
<template #title>文章管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/appoint">
|
||||
<el-icon><FirstAidKit /></el-icon>
|
||||
<template #title>预约管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/userInfo">
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<template #title>用户信息管理</template>
|
||||
</el-menu-item>
|
||||
-->
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="首页">
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
</template>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -1,30 +1,557 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const hospital = ref([
|
||||
import { ref, nextTick, useTemplateRef, onMounted } from 'vue'
|
||||
import { Edit, Delete, Plus } from '@element-plus/icons-vue'
|
||||
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
||||
|
||||
// 获取文章列表
|
||||
const hospital = ref({
|
||||
total: 10,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
hospitalName: '中南大学湘雅医院',
|
||||
districtId: 430105,
|
||||
districtName: '开福区',
|
||||
cityName: '长沙市',
|
||||
provinceId: 43,
|
||||
provinceName: '湖南省',
|
||||
address: '湖南省长沙市开福区湘雅路87号',
|
||||
introduction:
|
||||
'中南大学湘雅医院(Xiangya city Central South University)创建于1906年,坐落在人文荟萃的楚汉名城长沙,是中国最早的西医医院之一,是国家卫生健康委员会直管的三级甲等综合医院、教育部直属高校中南大学的附属医院。\n建院伊始,即将欧美医学最高标准融入办医理念,从长沙西牌楼一幢旧房起步,筚路蓝缕、精勤进取,书写了我国西医发展史的重要篇章。\n新中国成立后,在中国共产党的领导下,经过几代湘雅人的不懈努力,各项事业取得长足发展,现已发展成为我国重要的临床诊疗、医学教育与科技创新中心。\n现有编制床位3500张,总建筑面积51万平方米。开设临床医疗医技科室和亚专科111个,病区76个,护理单元101个。拥有国家重点学科7个,国家临床重点专科25个。神经内科、神经外科、皮肤科、骨科、呼吸内科、老年病学等专科的诊疗水平和科技影响力位居全国前列,是国家老年疾病临床医学研究中心。具备医学本科生、研究生、进修生、住院医师规范化培训等完整的学位教育和继续教育教学体系。2020年6月,入选湖南省开展新冠病毒核酸检测的医疗卫生机构名单。2021年8月,中南大学湘雅医院骨科被评选为第20届全国青年文明号。',
|
||||
phone: '0746-4356788',
|
||||
level: '三甲',
|
||||
url: '',
|
||||
departmentList: [
|
||||
{ id: 1, name: '呼吸内科', belong: '内科' },
|
||||
{ id: 2, name: '内分泌科', belong: '内科' }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
onMounted(async () => {
|
||||
// const res = await getdepatmentList()
|
||||
})
|
||||
|
||||
// 搜索文章
|
||||
const search = ref('')
|
||||
const searchhospital = async () => {
|
||||
console.log(search.value)
|
||||
}
|
||||
// 分页
|
||||
const pageSize = ref(5)
|
||||
const currentPage = ref(1)
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
// 删除文章
|
||||
const deletehospital = async (row) => {
|
||||
console.log(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
// 批量删除医生
|
||||
const hospitalIds = ref([])
|
||||
const select = (val) => {
|
||||
hospitalIds.value = val.map((item) => item.id)
|
||||
}
|
||||
const deletehospitals = async () => {
|
||||
ElMessage.success('批量删除成功')
|
||||
}
|
||||
// 编辑或增加医生
|
||||
const drawerVisible = ref(false)
|
||||
const add = ref(false)
|
||||
const hospitalForm = ref({})
|
||||
const formRef = useTemplateRef('hospitalFormRef')
|
||||
const show = ref(true)
|
||||
const saveOrUpdate = async (row) => {
|
||||
drawerVisible.value = true
|
||||
hospitalForm.value = { ...row }
|
||||
if (row) {
|
||||
hospitalForm.value.cityInfo =
|
||||
row.provinceName + '/' + row.cityName + '/' + row.districtName
|
||||
} else {
|
||||
add.value = true
|
||||
imageUrl.value = ''
|
||||
}
|
||||
}
|
||||
const confirm = async () => {
|
||||
await formRef.value.validate()
|
||||
drawerVisible.value = false
|
||||
if (add.value) {
|
||||
add.value = false
|
||||
ElMessage.success('添加成功')
|
||||
} else {
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 分类筛选
|
||||
const levelList = ref([
|
||||
{ text: '内科', value: '内科' },
|
||||
{ text: '外科', value: '外科' },
|
||||
{ text: '儿科', value: '儿科' },
|
||||
{ text: '妇产科', value: '妇产科' },
|
||||
{ text: '眼科', value: '眼科' }
|
||||
])
|
||||
const levelFilter = (value, row) => {
|
||||
return row.level === value
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
const imageUrl = ref('')
|
||||
const onSelectFile = (file) => {
|
||||
// 预览图片
|
||||
imageUrl.value = URL.createObjectURL(file.raw)
|
||||
hospitalForm.value.url = file.raw
|
||||
}
|
||||
// 选择城市和等级
|
||||
const cityChoose = ref([
|
||||
{
|
||||
id:1,
|
||||
name:'12',
|
||||
alias:'123',
|
||||
value: '43',
|
||||
label: '湖南省',
|
||||
children: [
|
||||
{
|
||||
value: '4301',
|
||||
label: '长沙市',
|
||||
children: [
|
||||
{
|
||||
value: '430101-岳麓区',
|
||||
label: '岳麓区'
|
||||
},
|
||||
{
|
||||
value: '430102-天心区',
|
||||
label: '天心区'
|
||||
},
|
||||
{
|
||||
value: '430103-开福区',
|
||||
label: '开福区'
|
||||
},
|
||||
{
|
||||
value: '430104-芙蓉区',
|
||||
label: '芙蓉区'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '42',
|
||||
label: '湖北省',
|
||||
children: [
|
||||
{
|
||||
value: '4201',
|
||||
label: '武汉市',
|
||||
children: [
|
||||
{
|
||||
value: '420101-武昌区',
|
||||
label: '武昌区'
|
||||
},
|
||||
{
|
||||
value: '420102-洪山区',
|
||||
label: '洪山区'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
const cityChange = (val) => {
|
||||
const cityId = val[2].split('-')[0]
|
||||
const cityName = val[2].split('-')[1]
|
||||
console.log(cityId, cityName)
|
||||
}
|
||||
const levelChange = (val) => {
|
||||
hospitalForm.value.type = val
|
||||
console.log(val)
|
||||
}
|
||||
|
||||
// 科室
|
||||
const dialogVisible = ref(false)
|
||||
const departmentAdd = ref(false)
|
||||
const options = ref([
|
||||
{
|
||||
value: '内科',
|
||||
label: '内科',
|
||||
children: [
|
||||
{
|
||||
value: '呼吸内科',
|
||||
label: '呼吸内科'
|
||||
},
|
||||
{
|
||||
value: '消化内科',
|
||||
label: '消化内科'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '外科',
|
||||
label: '外科',
|
||||
children: [
|
||||
{
|
||||
value: '神经外科',
|
||||
label: '神经外科'
|
||||
},
|
||||
{
|
||||
value: '肝胆外科',
|
||||
label: '肝胆外科'
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
/// 删除科室
|
||||
const deletedoctorDepartment = (row) => {
|
||||
console.log(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
/// 添加科室
|
||||
const selectDepartment = ref([])
|
||||
const departmentChange = (val) => {
|
||||
selectDepartment.value = val
|
||||
console.log(val)
|
||||
}
|
||||
const saveDepartment = async (row) => {
|
||||
dialogVisible.value = true
|
||||
if (!row) {
|
||||
departmentAdd.value = true
|
||||
}
|
||||
}
|
||||
const department = async () => {
|
||||
dialogVisible.value = false
|
||||
if (departmentAdd.value) {
|
||||
ElMessage.success('添加成功')
|
||||
departmentAdd.value = false
|
||||
} else {
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 标签
|
||||
const inputValue = ref('')
|
||||
const dynamicTags = ref(['综合医院', '专科医院', '社区医院'])
|
||||
const inputVisible = ref(false)
|
||||
const InputRef = useTemplateRef('InputRef')
|
||||
const handleClose = (tag) => {
|
||||
dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
|
||||
}
|
||||
const handleInputConfirm = () => {
|
||||
if (inputValue.value) {
|
||||
dynamicTags.value.push(inputValue.value)
|
||||
}
|
||||
inputVisible.value = false
|
||||
inputValue.value = ''
|
||||
}
|
||||
const showInput = () => {
|
||||
inputVisible.value = true
|
||||
nextTick(() => {
|
||||
InputRef.value.input.focus()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="医院管理">
|
||||
<page-container>
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
<el-button @click="saveOrUpdate(null)" type="primary">
|
||||
添加医院
|
||||
</el-button>
|
||||
<el-button @click="deletehospitals" type="danger"> 批量删除 </el-button>
|
||||
</template>
|
||||
<el-table :data="hospital" stripe>
|
||||
<el-table-column prop="id" label="序号"></el-table-column>
|
||||
<el-table-column prop="name" label="分类名称"></el-table-column>
|
||||
<el-table-column prop="alias" label="分类别名"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作">
|
||||
<template #default="{row}">
|
||||
<el-button type="primary" size="small">
|
||||
编辑
|
||||
<template #search>
|
||||
<el-cascader
|
||||
@change="cityChange"
|
||||
placeholder="请选择辖区"
|
||||
filterable
|
||||
clearable
|
||||
style="width: fit-content; margin-right: 16px"
|
||||
:options="cityChoose"
|
||||
/>
|
||||
<el-input
|
||||
v-model="search"
|
||||
placeholder="搜索医院名称"
|
||||
clearable
|
||||
@keyup.enter="searchhospital"
|
||||
style="width: 220px"
|
||||
>
|
||||
</el-input>
|
||||
</template>
|
||||
|
||||
<el-drawer
|
||||
v-model="drawerVisible"
|
||||
title="编辑或增加"
|
||||
size="50%"
|
||||
@closed="show = true"
|
||||
>
|
||||
<el-form
|
||||
ref="hospitalFormRef"
|
||||
:model="hospitalForm"
|
||||
label-width="auto"
|
||||
inline
|
||||
label-position="left"
|
||||
style="padding: 0 24px"
|
||||
>
|
||||
<el-form-item
|
||||
label="医院名称"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医院名称', trigger: 'blur' }
|
||||
]"
|
||||
prop="hospitalName"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入医院名称"
|
||||
v-model="hospitalForm.hospitalName"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="所在辖区"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择所在辖区', trigger: 'blur' }
|
||||
]"
|
||||
prop="cityInfo"
|
||||
>
|
||||
<el-select
|
||||
v-if="hospitalForm.cityInfo && show"
|
||||
v-model="hospitalForm.cityInfo"
|
||||
@click="show = false"
|
||||
/>
|
||||
<el-cascader
|
||||
v-else
|
||||
@change="cityChange"
|
||||
placeholder="请选择辖区"
|
||||
filterable
|
||||
style="width: fit-content"
|
||||
:options="cityChoose"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医院地址"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医院地址', trigger: 'blur' }
|
||||
]"
|
||||
prop="address"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入医院地址"
|
||||
v-model="hospitalForm.address"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="等  级"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择医院等级', trigger: 'blur' }
|
||||
]"
|
||||
prop="level"
|
||||
>
|
||||
<el-select
|
||||
v-model="hospitalForm.level"
|
||||
placeholder="请选择医院等级"
|
||||
@change="levelChange"
|
||||
>
|
||||
<el-option v-for="item in levelList" :key="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医院电话"
|
||||
prop="phone"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医院电话', trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input placeholder="请输入医院电话" v-model="hospitalForm.phone" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医院照片"
|
||||
:rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]"
|
||||
prop="url"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="onSelectFile"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img
|
||||
v-if="imageUrl || hospitalForm.url"
|
||||
:src="imageUrl || hospitalForm.url"
|
||||
class="avatar"
|
||||
/>
|
||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医院简介"
|
||||
style="width: 100%"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医院简介', trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入医院简介"
|
||||
type="textarea"
|
||||
:rows="10"
|
||||
v-model="hospitalForm.introduction"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div style="width: 100%; display: flex; justify-content: space-evenly">
|
||||
<el-button @click="drawerVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="confirm()"> 确定 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<el-dialog v-model="dialogVisible" title="增加" width="400">
|
||||
<el-cascader-panel
|
||||
@change="departmentChange"
|
||||
style="width: fit-content"
|
||||
:options="options"
|
||||
/>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="department()">确定 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-table
|
||||
stripe
|
||||
:data="hospital.records"
|
||||
height="100%"
|
||||
@selection-change="select"
|
||||
>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div class="expand-content">
|
||||
<div>
|
||||
<h3 style="margin-bottom: 8px">医院简介:</h3>
|
||||
<p
|
||||
v-html="
|
||||
row.introduction
|
||||
.replace(/\n/g, '<br/>')
|
||||
.replace(/\t/g, ' ')
|
||||
"
|
||||
></p>
|
||||
</div>
|
||||
<div style="display: flex">
|
||||
<h3 style="margin-bottom: 20px">标签:</h3>
|
||||
<el-tag
|
||||
v-for="tag in dynamicTags"
|
||||
:key="tag"
|
||||
closable
|
||||
style="margin-right: 8px"
|
||||
:disable-transitions="false"
|
||||
@close="handleClose(tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
v-if="inputVisible"
|
||||
ref="InputRef"
|
||||
v-model="inputValue"
|
||||
size="small"
|
||||
style="height: 100%; width: 82px"
|
||||
@keyup.enter="handleInputConfirm"
|
||||
@blur="handleInputConfirm"
|
||||
/>
|
||||
<el-button v-else size="small" @click="showInput">
|
||||
+ 添加科室
|
||||
</el-button>
|
||||
</div>
|
||||
<div style="display: flex">
|
||||
<h3 style="margin-bottom: 8px">科室列表:</h3>
|
||||
<el-button
|
||||
size="small"
|
||||
@click="saveDepartment(null)"
|
||||
type="primary"
|
||||
>
|
||||
添加科室
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="row.departmentList" max-height="300">
|
||||
<el-table-column prop="id" label="id" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
prop="belong"
|
||||
label="科室"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="具体科室"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="删除" width="108">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="deletedoctorDepartment(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="id"
|
||||
show-overflow-tooltip
|
||||
width="60px"
|
||||
/>
|
||||
<el-table-column width="100px" label="图片">
|
||||
<template #default>
|
||||
<el-image :src="hospital.url || '/logo.png'" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="hospitalName"
|
||||
label="医院名称"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="cityName" label="所在市" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" label="地址" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
prop="level"
|
||||
label="等级"
|
||||
:filters="levelList"
|
||||
:filter-method="levelFilter"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.level }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="phone" label="电话" show-overflow-tooltip />
|
||||
<el-table-column label="编辑/删除" width="108" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="saveOrUpdate(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
</el-button>
|
||||
<el-button type="danger" size="small">
|
||||
删除
|
||||
<el-button
|
||||
plain
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="deletehospital(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -32,7 +559,67 @@ const hospital = ref([
|
|||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="+hospital.total"
|
||||
style="height: 48px; justify-content: center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.el-form-item {
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
.expand-content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
p {
|
||||
border-radius: 12px;
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
padding: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.el-table {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片上传框样式
|
||||
.avatar-uploader {
|
||||
:deep() {
|
||||
.avatar {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,23 +1,524 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const cate_data = ref([])
|
||||
import { ref, useTemplateRef, onMounted } from 'vue'
|
||||
import { Edit, Delete, Plus } from '@element-plus/icons-vue'
|
||||
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
||||
|
||||
// 获取文章列表
|
||||
const doctor = ref({
|
||||
total: 10,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
doctorName: '王强',
|
||||
level: '主任医师',
|
||||
expertise: '内分泌科专家',
|
||||
source: '中南大学湘雅医院博士生导师',
|
||||
department: '内分泌科',
|
||||
briefly:
|
||||
'内分泌专家,甲状腺综合手术治疗专家,省级内分泌科委员会委员,独创中医疗法,内分泌科疑难杂症综合治疗',
|
||||
url: '',
|
||||
hospitalInfo: {
|
||||
id: 1,
|
||||
hospitalName: '中南大学湘雅医院'
|
||||
},
|
||||
appointmentTimeList: [
|
||||
{
|
||||
id: 1,
|
||||
fee: 100,
|
||||
date: '2024-12-23'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
onMounted(async () => {
|
||||
// const res = await getdepatmentList()
|
||||
hospitalList.value = doctor.value.records.map(
|
||||
(item) => item.hospitalInfo.id + '. ' + item.hospitalInfo.hospitalName
|
||||
)
|
||||
})
|
||||
|
||||
// 搜索文章
|
||||
const search = ref('')
|
||||
const searchdoctor = async () => {
|
||||
console.log(search.value)
|
||||
}
|
||||
// 分页
|
||||
const pageSize = ref(5)
|
||||
const currentPage = ref(1)
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
// 删除文章
|
||||
const deletedoctor = async (row) => {
|
||||
console.log(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
// 批量删除医生
|
||||
const doctorIds = ref([])
|
||||
const select = (val) => {
|
||||
doctorIds.value = val.map((item) => item.id)
|
||||
}
|
||||
const deletedoctors = async () => {
|
||||
ElMessage.success('批量删除成功')
|
||||
}
|
||||
// 编辑或增加医生
|
||||
const drawerVisible = ref(false)
|
||||
const add = ref(false)
|
||||
const doctorForm = ref({})
|
||||
const saveOrUpdate = async (row) => {
|
||||
drawerVisible.value = true
|
||||
doctorForm.value = { ...row }
|
||||
if (row) {
|
||||
doctorForm.value.hospital =
|
||||
row.hospitalInfo.id + '. ' + row.hospitalInfo.hospitalName
|
||||
} else {
|
||||
add.value = true
|
||||
imageUrl.value = ''
|
||||
}
|
||||
}
|
||||
const formRef = useTemplateRef('doctorFormRef')
|
||||
const confirm = async () => {
|
||||
await formRef.value.validate()
|
||||
drawerVisible.value = false
|
||||
if (add.value) {
|
||||
add.value = false
|
||||
ElMessage.success('添加成功')
|
||||
} else {
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 分类筛选
|
||||
const departmentList = ref([
|
||||
{ text: '内科', value: '内科' },
|
||||
{ text: '外科', value: '外科' },
|
||||
{ text: '儿科', value: '儿科' },
|
||||
{ text: '妇产科', value: '妇产科' },
|
||||
{ text: '眼科', value: '眼科' }
|
||||
])
|
||||
const departmentFilter = (value, row) => {
|
||||
return row.department === value
|
||||
}
|
||||
const hospitalCategoryList = ref([
|
||||
{ text: '北京协和医院', value: '北京协和医院' },
|
||||
{ text: '北京儿童医院', value: '北京儿童医院' }
|
||||
])
|
||||
const hospitalFilter = (value, row) => {
|
||||
return row.hospitalInfo.hospitalName === value
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
const imageUrl = ref('')
|
||||
const onSelectFile = (file) => {
|
||||
// 预览图片
|
||||
imageUrl.value = URL.createObjectURL(file.raw)
|
||||
doctorForm.value.url = file.raw
|
||||
}
|
||||
// 选择医生和类型
|
||||
const hospitalList = ref([])
|
||||
const hospitalChange = (val) => {
|
||||
// 在‘-’之前截取id
|
||||
const id = val.split('. ')[0]
|
||||
doctorForm.value.hospitalInfo = { id, hospitalName: val.split('. ')[1] }
|
||||
console.log(id)
|
||||
}
|
||||
const departmentChange = (val) => {
|
||||
doctorForm.value.type = val
|
||||
console.log(val)
|
||||
}
|
||||
|
||||
// 预约
|
||||
const dialogVisible = ref(false)
|
||||
const appointForm = ref({})
|
||||
const appointAdd = ref(false)
|
||||
/// 删除预约
|
||||
const deletedoctorAppoint = (row) => {
|
||||
console.log(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
/// 添加和修改预约
|
||||
const saveOrUpdateAppoint = async (row) => {
|
||||
dialogVisible.value = true
|
||||
appointForm.value = { ...row }
|
||||
console.log(row)
|
||||
if (!row) {
|
||||
appointAdd.value = true
|
||||
}
|
||||
}
|
||||
const appointRef = useTemplateRef('appointRef')
|
||||
const appoint = async () => {
|
||||
await appointRef.value.validate()
|
||||
dialogVisible.value = false
|
||||
if (appointAdd.value) {
|
||||
ElMessage.success('添加成功')
|
||||
appointAdd.value = false
|
||||
} else {
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="医生管理">
|
||||
<page-container>
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
<el-button @click="saveOrUpdate(null)" type="primary">
|
||||
添加医院
|
||||
</el-button>
|
||||
<el-button @click="deletedoctors" type="danger"> 批量删除 </el-button>
|
||||
</template>
|
||||
<el-table :data="cate_data">
|
||||
<el-table-column prop="id" label="序号"></el-table-column>
|
||||
<el-table-column prop="cate_name" label="分类名称"></el-table-column>
|
||||
<el-table-column prop="cate_alias" label="分类别名"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作"></el-table-column>
|
||||
<template #search>
|
||||
<el-input
|
||||
v-model="search"
|
||||
placeholder="请输入医生名称"
|
||||
clearable
|
||||
@keyup.enter="searchdoctor"
|
||||
style="width: 250px"
|
||||
>
|
||||
</el-input>
|
||||
</template>
|
||||
|
||||
<!-- 医生弹出层 -->
|
||||
<el-drawer v-model="drawerVisible" title="编辑或增加" size="50%">
|
||||
<el-form
|
||||
ref="doctorFormRef"
|
||||
:model="doctorForm"
|
||||
label-width="auto"
|
||||
inline
|
||||
label-position="left"
|
||||
style="padding: 0 24px"
|
||||
>
|
||||
<el-form-item
|
||||
label="医生姓名"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医生姓名', trigger: 'blur' }
|
||||
]"
|
||||
prop="doctorName"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入医生姓名"
|
||||
v-model="doctorForm.doctorName"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="职  称"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医生职称', trigger: 'blur' }
|
||||
]"
|
||||
prop="level"
|
||||
>
|
||||
<el-input placeholder="请输入医生职称" v-model="doctorForm.level" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="头  衔"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医生学历', trigger: 'blur' }
|
||||
]"
|
||||
prop="source"
|
||||
>
|
||||
<el-input placeholder="请输入医生学历" v-model="doctorForm.source" />
|
||||
</el-form-item>
|
||||
<el-form-item label=" 擅长领域" prop="expertise">
|
||||
<el-input
|
||||
placeholder="请输入医生头衔"
|
||||
v-model="doctorForm.expertise"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="所属科室"
|
||||
:rules="[{ required: true, message: '请选择医生', trigger: 'blur' }]"
|
||||
prop="department"
|
||||
>
|
||||
<el-select
|
||||
v-model="doctorForm.department"
|
||||
placeholder="请选择科室"
|
||||
@change="departmentChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in departmentList"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="所属医院"
|
||||
:rules="[{ required: true, message: '请选择医院', trigger: 'blur' }]"
|
||||
prop="hospital"
|
||||
>
|
||||
<el-select
|
||||
v-model="doctorForm.hospital"
|
||||
placeholder="请选择医院"
|
||||
@change="hospitalChange"
|
||||
>
|
||||
<el-option v-for="item in hospitalList" :key="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医生照片"
|
||||
:rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]"
|
||||
prop="url"
|
||||
>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="onSelectFile"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img
|
||||
v-if="imageUrl || doctorForm.url"
|
||||
:src="imageUrl || doctorForm.url"
|
||||
class="avatar"
|
||||
/>
|
||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="医生简介"
|
||||
style="width: 100%"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入医生简介', trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入医生简介"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
v-model="doctorForm.introduction"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div style="width: 100%; display: flex; justify-content: space-evenly">
|
||||
<el-button @click="drawerVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="confirm()"> 确定 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 预约弹出框 -->
|
||||
<el-dialog v-model="dialogVisible" title="编辑或增加" width="400">
|
||||
<el-form
|
||||
ref="appointRef"
|
||||
:model="appointForm"
|
||||
label-width="100px"
|
||||
style="width: 350px"
|
||||
>
|
||||
<el-form-item
|
||||
label="日期"
|
||||
prop="date"
|
||||
:rules="{ required: true, message: '请输入日期', trigger: 'blur' }"
|
||||
>
|
||||
<el-input placeholder="请输入日期" v-model="appointForm.date" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="费用"
|
||||
prop="fee"
|
||||
:rules="{ required: true, message: '请输入费用', trigger: 'blur' }"
|
||||
>
|
||||
<el-input placeholder="请输入费用" v-model="appointForm.fee" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="appoint()">确定 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-table
|
||||
stripe
|
||||
:data="doctor.records"
|
||||
height="100%"
|
||||
@selection-change="select"
|
||||
>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div class="expand-content">
|
||||
<h3 style="margin-bottom: 8px">医生简介:</h3>
|
||||
<p
|
||||
v-html="
|
||||
row.briefly.replace(/\n/g, '<br/>').replace(/\t/g, ' ')
|
||||
"
|
||||
></p>
|
||||
<!-- 预约列表 -->
|
||||
<div style="display: flex">
|
||||
<h3 style="margin-bottom: 8px">预约列表:</h3>
|
||||
<el-button
|
||||
size="small"
|
||||
@click="saveOrUpdateAppoint(null)"
|
||||
type="primary"
|
||||
>
|
||||
添加预约
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="row.appointmentTimeList" max-height="300">
|
||||
<el-table-column prop="id" label="id" show-overflow-tooltip />
|
||||
<el-table-column prop="date" label="日期" show-overflow-tooltip />
|
||||
<el-table-column prop="fee" label="费用" show-overflow-tooltip />
|
||||
<el-table-column label="编辑/删除" width="108">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="saveOrUpdateAppoint(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="deletedoctorAppoint(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="id"
|
||||
show-overflow-tooltip
|
||||
width="60px"
|
||||
/>
|
||||
<el-table-column width="100px" label="图片">
|
||||
<template #default>
|
||||
<el-image :src="doctor.url || '/logo.png'" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="doctorName"
|
||||
label="医生姓名"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="level" label="职称" show-overflow-tooltip />
|
||||
<el-table-column prop="source" label="头衔" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
prop="expertise"
|
||||
label="擅长领域"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="department"
|
||||
label="所属科室"
|
||||
:filters="departmentList"
|
||||
:filter-method="departmentFilter"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.department }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="hospitalInfo.hospitalName"
|
||||
label="所属医院"
|
||||
:filters="hospitalCategoryList"
|
||||
:filter-method="hospitalFilter"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.hospitalInfo.hospitalName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="编辑/删除" width="108" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="saveOrUpdate(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="deletedoctor(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="+doctor.total"
|
||||
style="height: 48px; justify-content: center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.el-form-item {
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
.expand-content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
p {
|
||||
border-radius: 12px;
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
padding: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.el-table {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片上传框样式
|
||||
.avatar-uploader {
|
||||
:deep() {
|
||||
.avatar {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,23 +1,402 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const cate_data = ref([])
|
||||
import { ref, useTemplateRef, onMounted } from 'vue'
|
||||
import { Edit, Delete, Plus } from '@element-plus/icons-vue'
|
||||
import { QuillEditor } from '@vueup/vue-quill'
|
||||
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
||||
|
||||
// 获取文章列表
|
||||
const article = ref({
|
||||
total: 10,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
titleBig: '空腹能不能吃汤圆?无糖汤圆不“胖人”吗?',
|
||||
titleSmall: '元宵吃汤圆,有什么禁忌吗?',
|
||||
content:
|
||||
'\t空腹不建议吃汤圆,因为汤圆主要成分是糯米,糯米较难消化,空腹食用可能会刺激胃酸分泌,导致胃部不适。另外,汤圆通常含有较多的糖分和油脂,空腹食用可能会引起血糖快速上升,对糖尿病患者或血糖控制不佳的人尤其不利。\r\n\r\n\t至于无糖汤圆,虽然去掉了糖分,但糯米本身和其他配料(如豆沙、芝麻等)仍含有较高的热量和脂肪。因此,无糖汤圆并不能完全做到“不胖人”。如果担心体重问题,即使是无糖汤圆也应适量食用,不宜过量。同时,要注意汤圆的整体热量摄入,合理安排饮食,配合适当的运动,才能更好地控制体重。\r\n\r\n\t元宵节吃汤圆是中国传统习俗,但在享受这一美食时,也需要注意以下禁忌:\r\n\r\n\t糖尿病患者和血糖控制不佳者:汤圆含有较多糖分和淀粉,即使是无糖汤圆,也含有较高的碳水化合物,可能会引起血糖快速升高,应尽量少吃或不吃。\r\n消化系统疾病患者:汤圆的外皮主要由糯米制成,糯米较难消化,患有胃病、胃溃疡、胃炎、消化不良等疾病的人应谨慎食用。\r\n\r\n\t1、老年人:老年人的消化功能相对较弱,应适量食用,避免过量导致消化不良。\r\n\t2、婴幼儿:婴幼儿的消化系统尚未完全成熟,汤圆不易咀嚼和消化,且含有较多的糖和油脂,不适合婴幼儿食用。\r\n\t3、肥胖和正在减肥的人:汤圆热量较高,应适量食用,以免影响减肥效果。\r\n\t4、食用时不宜过快:汤圆应慢慢咀嚼,以免噎到。\r\n\t5、不宜空腹食用:空腹吃汤圆可能会刺激胃酸分泌,导致胃部不适。\r\n\t6、注意汤圆的食用温度:汤圆应煮熟后食用,不宜过热,以免烫伤口腔和食道。\r\n\t7、不宜与油腻食物同食:汤圆本身较油腻,不宜与其他油腻食物同食,以免加重消化负担。\r\n\t8、注意食品卫生:自制汤圆时应确保食材新鲜,煮熟煮透;购买现成的汤圆时应选择信誉良好的品牌和商家。\r\n\r\n\t遵循以上禁忌,可以更健康地享受汤圆带来的节日氛围。',
|
||||
type: '健康养生',
|
||||
publishTime: '2023-02-01',
|
||||
doctorInfo: {
|
||||
id: 1,
|
||||
doctorName: '王强'
|
||||
},
|
||||
url: '/logo.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
titleBig: '空腹能不能吃汤圆?无糖汤圆不“胖人”吗?',
|
||||
titleSmall: '元宵吃汤圆,有什么禁忌吗?',
|
||||
content:
|
||||
'\t空腹不建议吃汤圆,因为汤圆主要成分是糯米,糯米较难消化,空腹食用可能会刺激胃酸分泌,导致胃部不适。另外,汤圆通常含有较多的糖分和油脂,空腹食用可能会引起血糖快速上升,对糖尿病患者或血糖控制不佳的人尤其不利。\r\n\r\n\t至于无糖汤圆,虽然去掉了糖分,但糯米本身和其他配料(如豆沙、芝麻等)仍含有较高的热量和脂肪。因此,无糖汤圆并不能完全做到“不胖人”。如果担心体重问题,即使是无糖汤圆也应适量食用,不宜过量。同时,要注意汤圆的整体热量摄入,合理安排饮食,配合适当的运动,才能更好地控制体重。\r\n\r\n\t元宵节吃汤圆是中国传统习俗,但在享受这一美食时,也需要注意以下禁忌:\r\n\r\n\t糖尿病患者和血糖控制不佳者:汤圆含有较多糖分和淀粉,即使是无糖汤圆,也含有较高的碳水化合物,可能会引起血糖快速升高,应尽量少吃或不吃。\r\n消化系统疾病患者:汤圆的外皮主要由糯米制成,糯米较难消化,患有胃病、胃溃疡、胃炎、消化不良等疾病的人应谨慎食用。\r\n\r\n\t1、老年人:老年人的消化功能相对较弱,应适量食用,避免过量导致消化不良。\r\n\t2、婴幼儿:婴幼儿的消化系统尚未完全成熟,汤圆不易咀嚼和消化,且含有较多的糖和油脂,不适合婴幼儿食用。\r\n\t3、肥胖和正在减肥的人:汤圆热量较高,应适量食用,以免影响减肥效果。\r\n\t4、食用时不宜过快:汤圆应慢慢咀嚼,以免噎到。\r\n\t5、不宜空腹食用:空腹吃汤圆可能会刺激胃酸分泌,导致胃部不适。\r\n\t6、注意汤圆的食用温度:汤圆应煮熟后食用,不宜过热,以免烫伤口腔和食道。\r\n\t7、不宜与油腻食物同食:汤圆本身较油腻,不宜与其他油腻食物同食,以免加重消化负担。\r\n\t8、注意食品卫生:自制汤圆时应确保食材新鲜,煮熟煮透;购买现成的汤圆时应选择信誉良好的品牌和商家。\r\n\r\n\t遵循以上禁忌,可以更健康地享受汤圆带来的节日氛围。',
|
||||
type: '健康饮食',
|
||||
publishTime: '2023-02-01',
|
||||
doctorInfo: {
|
||||
id: 2,
|
||||
doctorName: '李康'
|
||||
},
|
||||
url: ''
|
||||
}
|
||||
]
|
||||
})
|
||||
const doctorList = ref()
|
||||
onMounted(async () => {
|
||||
// const res = await getDoctorList()
|
||||
doctorList.value = article.value.records.map(
|
||||
(item) => item.doctorInfo.id + '. ' + item.doctorInfo.doctorName
|
||||
)
|
||||
})
|
||||
|
||||
// 搜索文章
|
||||
const search = ref('')
|
||||
const searchArticle = async () => {
|
||||
console.log(search.value)
|
||||
}
|
||||
// 分页
|
||||
const pageSize = ref(5)
|
||||
const currentPage = ref(1)
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
// 删除文章
|
||||
const deleteArticle = async (row) => {
|
||||
console.log(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
// 批量删除文章
|
||||
const articleIds = ref([])
|
||||
const select = (val) => {
|
||||
articleIds.value = val.map((item) => item.id)
|
||||
}
|
||||
const deleteArticles = async () => {
|
||||
ElMessage.success('批量删除成功')
|
||||
}
|
||||
// 编辑或增加文章
|
||||
const drawerVisible = ref(false)
|
||||
const add = ref(false)
|
||||
const articleForm = ref({})
|
||||
const saveOrUpdate = async (row) => {
|
||||
drawerVisible.value = true
|
||||
articleForm.value = { ...row }
|
||||
if (row) {
|
||||
articleForm.value.doctor =
|
||||
row.doctorInfo.id + '. ' + row.doctorInfo.doctorName
|
||||
} else {
|
||||
add.value = true
|
||||
imageUrl.value = ''
|
||||
articleForm.value.content = '\n'
|
||||
}
|
||||
}
|
||||
const formRef = useTemplateRef('articleFormRef')
|
||||
const confirm = async () => {
|
||||
await formRef.value.validate()
|
||||
drawerVisible.value = false
|
||||
if (add.value) {
|
||||
add.value = false
|
||||
ElMessage.success('添加成功')
|
||||
} else {
|
||||
ElMessage.success('修改成功')
|
||||
}
|
||||
}
|
||||
// 分类筛选
|
||||
const categoryList = ref([
|
||||
{ text: '抗疫专区', value: '1' },
|
||||
{ text: '健康养生', value: '2' },
|
||||
{ text: '医疗动态', value: '3' },
|
||||
{ text: '育儿专区', value: '4' }
|
||||
])
|
||||
const filter = (value, row) => {
|
||||
return row.type === value
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
const imageUrl = ref('')
|
||||
const onSelectFile = (file) => {
|
||||
// 预览图片
|
||||
imageUrl.value = URL.createObjectURL(file.raw)
|
||||
articleForm.value.url = file.raw
|
||||
}
|
||||
// 选择医生和类型
|
||||
const doctorChange = (val) => {
|
||||
// 在‘-’之前截取id
|
||||
const id = val.split('. ')[0]
|
||||
articleForm.value.doctorInfo = { id, doctorName: val.split('. ')[1] }
|
||||
console.log(id)
|
||||
}
|
||||
const typeChange = (val) => {
|
||||
articleForm.value.type = val
|
||||
console.log(val)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="医说管理">
|
||||
<page-container>
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
<el-button @click="saveOrUpdate(null)" type="primary">
|
||||
添加医院
|
||||
</el-button>
|
||||
<el-button @click="deleteArticles" type="danger"> 批量删除 </el-button>
|
||||
</template>
|
||||
<el-table :data="cate_data">
|
||||
<el-table-column prop="id" label="序号"></el-table-column>
|
||||
<el-table-column prop="cate_name" label="分类名称"></el-table-column>
|
||||
<el-table-column prop="cate_alias" label="分类别名"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作"></el-table-column>
|
||||
<template #search>
|
||||
<el-input
|
||||
v-model="search"
|
||||
placeholder="请输入文章名称"
|
||||
clearable
|
||||
@keyup.enter="searchArticle"
|
||||
style="width: 250px"
|
||||
>
|
||||
</el-input>
|
||||
</template>
|
||||
|
||||
<el-drawer v-model="drawerVisible" title="编辑或增加" size="50%">
|
||||
<el-form
|
||||
ref="articleFormRef"
|
||||
:model="articleForm"
|
||||
label-width="auto"
|
||||
inline
|
||||
label-position="left"
|
||||
style="padding: 0 24px"
|
||||
>
|
||||
<el-form-item
|
||||
label="标  题"
|
||||
:rules="[{ required: true, message: '请输入标题', trigger: 'blur' }]"
|
||||
prop="titleBig"
|
||||
>
|
||||
<el-input placeholder="请输入标题" v-model="articleForm.titleBig" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="副 标 题"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入副标题', trigger: 'blur' }
|
||||
]"
|
||||
prop="titleSmall"
|
||||
>
|
||||
<el-input
|
||||
placeholder="请输入副标题"
|
||||
v-model="articleForm.titleSmall"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="所属医生"
|
||||
:rules="[{ required: true, message: '请选择医生', trigger: 'blur' }]"
|
||||
prop="doctor"
|
||||
>
|
||||
<el-select
|
||||
v-model="articleForm.doctor"
|
||||
placeholder="请选择医生"
|
||||
@change="doctorChange"
|
||||
>
|
||||
<el-option v-for="item in doctorList" :key="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="文章分类"
|
||||
:rules="[{ required: true, message: '请选择分类', trigger: 'blur' }]"
|
||||
prop="type"
|
||||
>
|
||||
<el-select
|
||||
v-model="articleForm.type"
|
||||
placeholder="请选择分类"
|
||||
@change="typeChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in categoryList"
|
||||
:key="item.value"
|
||||
:label="item.text"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="文章图片"
|
||||
:rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]"
|
||||
prop="url"
|
||||
>
|
||||
<el-upload
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="onSelectFile"
|
||||
class="avatar-uploader"
|
||||
>
|
||||
<img
|
||||
v-if="imageUrl || articleForm.url"
|
||||
:src="imageUrl || articleForm.url"
|
||||
class="avatar"
|
||||
/>
|
||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<!-- <UploadImage @onSelectFile="onSelectFile" /> -->
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="文章内容"
|
||||
:rules="[{ required: true, message: '请输入内容', trigger: 'blur' }]"
|
||||
prop="content"
|
||||
style="width: 100%"
|
||||
>
|
||||
<div class="editor">
|
||||
<quillEditor
|
||||
theme="snow"
|
||||
v-model:content="articleForm.content"
|
||||
contentType="html"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div style="width: 100%; display: flex; justify-content: space-evenly">
|
||||
<el-button @click="drawerVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="confirm()"> 确定 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<el-table
|
||||
stripe
|
||||
:data="article.records"
|
||||
height="100%"
|
||||
@selection-change="select"
|
||||
>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div class="expand-content">
|
||||
<h3 style="margin-bottom: 8px">文章内容:</h3>
|
||||
<p
|
||||
v-html="
|
||||
row.content.replace(/\n/g, '<br/>').replace(/\t/g, ' ')
|
||||
"
|
||||
></p>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="id"
|
||||
show-overflow-tooltip
|
||||
width="60px"
|
||||
/>
|
||||
<el-table-column width="100px" label="图片">
|
||||
<template #default>
|
||||
<el-image :src="'/logo.png'" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="titleBig" label="标题" show-overflow-tooltip />
|
||||
<el-table-column prop="titleSmall" label="副标题" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
prop="type"
|
||||
label="分类"
|
||||
:filters="categoryList"
|
||||
:filter-method="filter"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.type }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="doctorInfo.doctorName"
|
||||
label="作者"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="publishTime"
|
||||
label="发布时间"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="编辑/删除" width="108" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="saveOrUpdate(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="deleteArticle(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="+article.total"
|
||||
style="height: 48px; justify-content: center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.el-form-item {
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
.expand-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 16px;
|
||||
p {
|
||||
border-radius: 12px;
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片上传框样式
|
||||
.avatar-uploader {
|
||||
:deep() {
|
||||
.avatar {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
.el-upload {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑器样式
|
||||
.editor {
|
||||
width: 100%;
|
||||
:deep() {
|
||||
.ql-editor {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,22 +1,114 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const cate_data = ref([])
|
||||
import { Close, Delete } from '@element-plus/icons-vue'
|
||||
|
||||
const userInfo = ref({
|
||||
total: 10,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
nickname: '张三-5667',
|
||||
appointNum: '14',
|
||||
phone: '13345678901',
|
||||
url: '',
|
||||
status: '1'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const search = ref('')
|
||||
const searchUser = () => {
|
||||
console.log(search.value)
|
||||
}
|
||||
// 分页
|
||||
const pageSize = ref(5)
|
||||
const currentPage = ref(1)
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
const forbiddenUser = (row) => {
|
||||
if (row.status === '1') {
|
||||
ElMessage(row.nickname + '已禁用')
|
||||
row.status = '0'
|
||||
} else {
|
||||
ElMessage.success(row.nickname + '已启用')
|
||||
row.status = '1'
|
||||
}
|
||||
}
|
||||
|
||||
const deleteUser = (row) => {
|
||||
ElMessageBox.confirm('确定要删除该用户吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功')
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="用户信息管理">
|
||||
<page-container>
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
<el-input
|
||||
v-model="search"
|
||||
placeholder="请输入用户昵称"
|
||||
clearable
|
||||
@keyup.enter="searchUser"
|
||||
style="width: 250px"
|
||||
>
|
||||
</el-input>
|
||||
</template>
|
||||
<el-table :data="cate_data">
|
||||
<el-table-column prop="id" label="序号"></el-table-column>
|
||||
<el-table-column prop="cate_name" label="分类名称"></el-table-column>
|
||||
<el-table-column prop="cate_alias" label="分类别名"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作"></el-table-column>
|
||||
|
||||
<el-table stripe :data="userInfo.records" height="100%">
|
||||
<el-table-column prop="id" label="id" width="60"></el-table-column>
|
||||
<el-table-column prop="url" label="头像">
|
||||
<template #default="{ row }">
|
||||
<el-avatar :size="40" :src="row.url || './src/assets/default.png'" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="nickname" label="昵称" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="phone" label="手机号" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="appointNum" label="预约次数"></el-table-column>
|
||||
<el-table-column label="禁用/删除" width="108" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="forbiddenUser(row)"
|
||||
>
|
||||
<el-icon><Close /></el-icon>
|
||||
</el-button>
|
||||
<el-button plain type="danger" size="small" @click="deleteUser(row)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="+userInfo.total"
|
||||
style="height: 48px; justify-content: center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Delete } from '@element-plus/icons-vue'
|
||||
|
||||
const appoint = ref({
|
||||
total: 10,
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: '张三',
|
||||
appointHospital: '北京医院',
|
||||
appointDoctor: '李四',
|
||||
appointTime: '2023-01-01',
|
||||
phone: '13800138000',
|
||||
fee: 100,
|
||||
appointUser: '王五-5667',
|
||||
appointStatus: 1,
|
||||
meno: '备注'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const search = ref('')
|
||||
const searchUser = () => {
|
||||
console.log(search.value)
|
||||
}
|
||||
// 分页
|
||||
const pageSize = ref(5)
|
||||
const currentPage = ref(1)
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
const deleteUser = () => {
|
||||
ElMessageBox.confirm('确定要删除该用户吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage.success('删除成功')
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const userFilters = ref([
|
||||
{ text: '王五-5667', value: '王五-5667' },
|
||||
{ text: '王五-5667', value: '王五-5667' }
|
||||
])
|
||||
const userFilterTag = (value, row) => {
|
||||
return row.appointStatus === value
|
||||
}
|
||||
const filters = ref([
|
||||
{ text: '未就诊', value: 1 },
|
||||
{ text: '已就诊', value: 2 }
|
||||
])
|
||||
const filterTag = (value, row) => {
|
||||
return row.appointStatus === value
|
||||
}
|
||||
const handleUpdate = (row) => {
|
||||
if (row.appointStatus === 1) {
|
||||
row.appointStatus = 2
|
||||
} else {
|
||||
row.appointStatus = 1
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container>
|
||||
<template #extra>
|
||||
<el-input
|
||||
v-model="search"
|
||||
placeholder="请输入就诊人姓名"
|
||||
clearable
|
||||
@keyup.enter="searchUser"
|
||||
style="width: 250px"
|
||||
>
|
||||
</el-input>
|
||||
</template>
|
||||
|
||||
<el-table stripe :data="appoint.records" height="100%">
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<div class="expand-content">
|
||||
<h3 style="margin-bottom: 8px">备注:</h3>
|
||||
<p
|
||||
v-html="
|
||||
row.meno.replace(/\n/g, '<br/>').replace(/\t/g, ' ')
|
||||
"
|
||||
></p>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="id" label="id" width="60"></el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="就诊人"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="appointHospital"
|
||||
label="预约医院"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="appointDoctor"
|
||||
label="预约医生"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="appointTime"
|
||||
label="预约时间"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="phone"
|
||||
label="手机号"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="fee"
|
||||
label="费用"
|
||||
show-overflow-tooltip
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="appointUser"
|
||||
label="预约用户"
|
||||
show-overflow-tooltip
|
||||
:filters="userFilters"
|
||||
:filter-method="userFilterTag"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.appointUser }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="appointStatus"
|
||||
label="状态"
|
||||
fixed="right"
|
||||
width="66"
|
||||
:filters="filters"
|
||||
:filter-method="filterTag"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-text
|
||||
size="small"
|
||||
style="cursor: pointer;"
|
||||
@click="handleUpdate(row)"
|
||||
:type="row.appointStatus === 1 ? 'danger' : 'success'"
|
||||
>{{ row.appointStatus === 1 ? '未就诊' : '已就诊' }}
|
||||
</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="删除" width="60" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button plain type="danger" size="small" @click="deleteUser(row)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:page-size="pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="+appoint.total"
|
||||
style="height: 48px; justify-content: center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.expand-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 16px;
|
||||
p {
|
||||
border-radius: 12px;
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,23 +0,0 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const cate_data = ref([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="文章分类">
|
||||
<template #extra>
|
||||
<el-button type="primary">添加分类</el-button>
|
||||
</template>
|
||||
<el-table :data="cate_data">
|
||||
<el-table-column prop="id" label="序号"></el-table-column>
|
||||
<el-table-column prop="cate_name" label="分类名称"></el-table-column>
|
||||
<el-table-column prop="cate_alias" label="分类别名"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作"></el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -1,24 +0,0 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const article = ref([])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-container title="文章管理">
|
||||
<template #extra>
|
||||
<el-button type="primary">发布文章</el-button>
|
||||
</template>
|
||||
<el-table :data="article">
|
||||
<el-table-column prop="title" label="文章标题"></el-table-column>
|
||||
<el-table-column prop="cate" label="分类"></el-table-column>
|
||||
<el-table-column prop="time" label="发布时间"></el-table-column>
|
||||
<el-table-column prop="status" label="状态"></el-table-column>
|
||||
<el-table-column prop="operate" label="操作"></el-table-column>
|
||||
<template #empty>
|
||||
<el-empty description="没有数据" />
|
||||
</template>
|
||||
</el-table>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -1,183 +0,0 @@
|
|||
<script setup>
|
||||
import {
|
||||
Management,
|
||||
Promotion,
|
||||
UserFilled,
|
||||
User,
|
||||
Crop,
|
||||
EditPen,
|
||||
SwitchButton,
|
||||
CaretBottom
|
||||
} from '@element-plus/icons-vue'
|
||||
import avatar from '@/assets/default.png'
|
||||
import { useUserStore } from '@/stores'
|
||||
import { onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 获取用户信息
|
||||
onMounted(() => {
|
||||
userStore.getUser()
|
||||
})
|
||||
|
||||
// 菜单操作
|
||||
const router = useRouter()
|
||||
const handleCommand = (key) => {
|
||||
if (key === 'logout') {
|
||||
// 退出弹窗
|
||||
ElMessageBox.confirm('确定要退出吗?', '温馨提示', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消'
|
||||
}).then(() => {
|
||||
// 清除本地数据
|
||||
userStore.removeToken()
|
||||
userStore.setUser({})
|
||||
router.push('/login')
|
||||
})
|
||||
} else {
|
||||
router.push(`/user/${key}`)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 1、el-container 布局容器
|
||||
2、el-menu 菜单组件
|
||||
:default-active="$route.path" 配置默认激活高亮的菜单
|
||||
router选项开启, el-menu-item 的 index 就是跳转的路径
|
||||
|
||||
el-menu-item 菜单项
|
||||
index="..." 配置的是访问的跳转路径, 配合 default-active 实现高亮
|
||||
-->
|
||||
<el-container class="layout-container">
|
||||
<el-aside width="200px">
|
||||
<div class="el-aside__logo"></div>
|
||||
<!-- 菜单组件 -->
|
||||
<el-menu
|
||||
active-text-color="#ffd04b"
|
||||
background-color="#232323"
|
||||
:default-active="$route.path"
|
||||
text-color="#fff"
|
||||
router
|
||||
>
|
||||
<!-- 一级菜单 -->
|
||||
<el-menu-item index="/article/channel">
|
||||
<el-icon><Management /></el-icon>
|
||||
<span>文章分类</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/article/manage">
|
||||
<el-icon><Promotion /></el-icon>
|
||||
<span>文章管理</span>
|
||||
</el-menu-item>
|
||||
<!-- 多级菜单 -->
|
||||
<el-sub-menu index="/user">
|
||||
<template #title>
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<span>个人中心</span>
|
||||
</template>
|
||||
<el-menu-item index="/user/profile">
|
||||
<el-icon><User /></el-icon>
|
||||
<span>基本资料</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/user/avatar">
|
||||
<el-icon><Crop /></el-icon>
|
||||
<span>更换头像</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/user/password">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<span>重置密码</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header>
|
||||
<div>
|
||||
前端程序员:<strong>{{ userStore.user.name }}</strong>
|
||||
</div>
|
||||
<!-- 下拉菜单 -->
|
||||
<el-dropdown placement="bottom-end" @command="handleCommand">
|
||||
<span class="el-dropdown__box">
|
||||
<el-avatar :src="userStore.user.avatarUrl || avatar" />
|
||||
<el-icon><CaretBottom /></el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="profile" :icon="User"
|
||||
>基本资料</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item command="avatar" :icon="Crop"
|
||||
>更换头像</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item command="password" :icon="EditPen"
|
||||
>重置密码</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item command="logout" :icon="SwitchButton"
|
||||
>退出登录</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="scale" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-container {
|
||||
height: 100vh;
|
||||
.el-aside {
|
||||
background-color: #232323;
|
||||
&__logo {
|
||||
height: 120px;
|
||||
background: url('@/assets/logo.png') no-repeat center / 80px auto;
|
||||
}
|
||||
.el-menu {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
.el-header {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.el-dropdown__box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-icon {
|
||||
color: #999;
|
||||
margin-left: 10px;
|
||||
}
|
||||
&:active,
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.scale-enter-active,
|
||||
.scale-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.scale-enter-from,
|
||||
.scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,186 +0,0 @@
|
|||
<script setup>
|
||||
import { userLoginService, userGetVerificationService } from '@/api/user'
|
||||
import { User, Lock } from '@element-plus/icons-vue'
|
||||
import { ref, onMounted, useTemplateRef } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/stores'
|
||||
|
||||
const form = useTemplateRef('form')
|
||||
|
||||
// 整个表单用于提交的form数据对象
|
||||
const formModle = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
captchaKey: '',
|
||||
captchaCode: ''
|
||||
})
|
||||
|
||||
let src = ref('')
|
||||
onMounted(async () => {
|
||||
const init = await userGetVerificationService()
|
||||
formModle.value.captchaKey = init.data.data.key
|
||||
src.value = init.data.data.image
|
||||
})
|
||||
|
||||
// 整个表单的校验规则
|
||||
/// 1、非空校验 required:true,message消息提示,trigger触发校验时机 blur change
|
||||
/// 2、长度校验 min最小长度,max最大长度
|
||||
/// 3、正则校验 pattern正则表达式
|
||||
/// 4、自定义校验 validator函数
|
||||
//// validator: (rule, value, callback)
|
||||
///// 1. rule:当前校验规则
|
||||
///// 2. value:所校验的表单元素的值
|
||||
///// 3. callback:无论成功还是失败,都需要callback回调
|
||||
///// - callback() 回调函数,如果校验通过
|
||||
///// - callback(new Error('错误信息')) 如果校验不通过
|
||||
const rules = ref({
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 1, max: 10, message: '用户名必须是 5-10 位字符', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^\S{6,15}$/,
|
||||
message: '密码必须是 6-15 位的非空字符',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
captchaCode: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
// 登录
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const login = async () => {
|
||||
await form.value.validate()
|
||||
const res = await userLoginService(formModle.value)
|
||||
// 保存token
|
||||
userStore.setToken(res.data.data)
|
||||
ElMessage.success('登录成功')
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
const getVerification = async () => {
|
||||
const update = await userGetVerificationService()
|
||||
formModle.value.captchaKey = update.data.data.key
|
||||
src.value = update.data.data.image
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 结构
|
||||
el-form 整个表单组件
|
||||
1、ref="form" 给组件起一个名字,方便后续操作
|
||||
2、size="large" 设置表单大小
|
||||
3、autocomplete="off" 关闭浏览器自动填充功能
|
||||
el-form-item 表单的一行
|
||||
el-input 表单元素
|
||||
:prefix-icon="User" 设置表单前面的元素
|
||||
-->
|
||||
<!-- 校验
|
||||
1、el-form =>
|
||||
:model="formModle" 绑定整个form的数据对象
|
||||
:rules="rules" 绑定整个rules规则的数据对象
|
||||
3、el-form-item =>
|
||||
prop="username"配置生效的是哪个校验规则
|
||||
v-model="formModle.username" 绑定表单元素的数据
|
||||
-->
|
||||
<div class="login-page">
|
||||
<div class="form">
|
||||
<div class="logo"></div>
|
||||
<el-form :model="formModle" :rules ref="form" size="large" class="forms">
|
||||
<el-form-item>
|
||||
<h1 style="margin-bottom: 8px">欢迎来到后台管理!</h1>
|
||||
</el-form-item>
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model="formModle.username"
|
||||
:prefix-icon="User"
|
||||
placeholder="请输入用户名"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model="formModle.password"
|
||||
:prefix-icon="Lock"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="captchaCode" class="verification">
|
||||
<el-input
|
||||
v-model="formModle.captchaCode"
|
||||
:prefix-icon="Lock"
|
||||
type="captchaCode"
|
||||
placeholder="请输入验证码"
|
||||
>
|
||||
</el-input>
|
||||
<img @click="getVerification" :src="src" alt="" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
@click="login"
|
||||
class="button"
|
||||
type="primary"
|
||||
auto-insert-space
|
||||
>
|
||||
登录
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-page {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
background: url('@/assets/login_bg.png') no-repeat center / cover;
|
||||
border-radius: 0 20px 20px 0;
|
||||
.form {
|
||||
width: 420px;
|
||||
height: 500px;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 20px 8px #ccc;
|
||||
user-select: none; // 禁止用户选择页面上的文本
|
||||
.logo {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
margin-top: 16px;
|
||||
opacity: 0.8;
|
||||
background: url('@/assets/logo.png') center / cover;
|
||||
}
|
||||
.button {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.forms {
|
||||
width: 75%;
|
||||
box-sizing: border-box;
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
img {
|
||||
cursor: pointer;
|
||||
border: #ccc 1px solid;
|
||||
border-radius: 4px;
|
||||
margin-left: 6px;
|
||||
height: 38px;
|
||||
width: 68px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,9 +0,0 @@
|
|||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<page-container title="更换头像">
|
||||
其他内容
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -1,9 +0,0 @@
|
|||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<page-container title="重置密码">
|
||||
其他内容
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -1,9 +0,0 @@
|
|||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<page-container title="个人详情">
|
||||
其他内容
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
Loading…
Reference in New Issue