Compare commits
621 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de0c040cb3 | ||
|
|
23276bb0fd | ||
|
|
46c53e09a3 | ||
|
|
209eb019d3 | ||
|
|
10a608c0af | ||
|
|
098d4bc85f | ||
|
|
26f7d67c50 | ||
|
|
42d2525b46 | ||
|
|
d9305c7620 | ||
|
|
185d87c24e | ||
|
|
a4080490bd | ||
|
|
714bcbdbb1 | ||
|
|
9158a38496 | ||
|
|
1f1f7f167f | ||
|
|
9453cc1c3b | ||
|
|
33a03d8119 | ||
|
|
2292fd1df6 | ||
|
|
18ac428a95 | ||
|
|
f0d0c304d6 | ||
|
|
7f041c96fb | ||
|
|
53ca11f85b | ||
|
|
a9f2a0c2ac | ||
|
|
181e2b21bb | ||
|
|
04bc6b4cb8 | ||
|
|
6058a1741b | ||
|
|
455f11af34 | ||
|
|
0b8848d63f | ||
|
|
1b7d6d09a8 | ||
|
|
c9592446c8 | ||
|
|
f2d2055f72 | ||
|
|
21ce0789ef | ||
|
|
794a8fc6aa | ||
|
|
408ef4a7df | ||
|
|
ab9b357c9b | ||
|
|
68d072cd60 | ||
|
|
aae1d37505 | ||
|
|
e927f2ff78 | ||
|
|
c271f3005a | ||
|
|
ca5697fb9c | ||
|
|
9150101498 | ||
|
|
6d0e6d0d16 | ||
|
|
c4236937b7 | ||
|
|
c1c0774572 | ||
|
|
fcb0ea9574 | ||
|
|
f095fde5a7 | ||
|
|
8bc2db1e6e | ||
|
|
7cbc15ea85 | ||
|
|
c2a9c670c4 | ||
|
|
4e5bdf6847 | ||
|
|
0aa6443a20 | ||
|
|
04278f553e | ||
|
|
349a041d71 | ||
|
|
58bf5062bf | ||
|
|
878f24ecae | ||
|
|
a15a374fb0 | ||
|
|
8a90f9d089 | ||
|
|
3007267951 | ||
|
|
710bb97cd3 | ||
|
|
18eb3a7fbf | ||
|
|
1d499b7052 | ||
|
|
36b28d83ed | ||
|
|
04fc03ccf5 | ||
|
|
ffb5898ea1 | ||
|
|
2c2eb0cb8d | ||
|
|
15dd8a60d7 | ||
|
|
65a0a6fb92 | ||
|
|
a0b35f4233 | ||
|
|
a271bc25c6 | ||
|
|
c988ed7988 | ||
|
|
c2ca0b1f29 | ||
|
|
efee87e4c5 | ||
|
|
98a990d9ea | ||
|
|
3a61df42ea | ||
|
|
d62baa0e51 | ||
|
|
dfe8806344 | ||
|
|
f1e95b960a | ||
|
|
7d0fa7f5d1 | ||
|
|
174f247a8e | ||
|
|
9cc41e8558 | ||
|
|
1fe8b9c5c9 | ||
|
|
496861587d | ||
|
|
93764fc5b5 | ||
|
|
22fab8dee0 | ||
|
|
dcbd729944 | ||
|
|
327a7b2a48 | ||
|
|
ad6bd8f39b | ||
|
|
95a91a10b3 | ||
|
|
b50f2b4c7e | ||
|
|
a1e0dac85c | ||
|
|
027f6dd538 | ||
|
|
94f902f788 | ||
|
|
bc5aaff9c9 | ||
|
|
770e8d7310 | ||
|
|
6a881e4613 | ||
|
|
0f36672783 | ||
|
|
7d5a7e0fe8 | ||
|
|
6977e233bb | ||
|
|
dbcb27e41a | ||
|
|
4b5b4464f4 | ||
|
|
4b6241e0b0 | ||
|
|
17fb60c481 | ||
|
|
51575b9f2d | ||
|
|
c943c1fc74 | ||
|
|
b55a45baa2 | ||
|
|
ae5db16d67 | ||
|
|
8f143be4b0 | ||
|
|
9ebafff392 | ||
|
|
e904c3df69 | ||
|
|
8ed1c958af | ||
|
|
a93e65df0a | ||
|
|
2fd861025a | ||
|
|
654c7d650a | ||
|
|
cb75196455 | ||
|
|
dd2b584c3d | ||
|
|
85d1cbff34 | ||
|
|
92d9c532c2 | ||
|
|
24bc61396e | ||
|
|
1655870d4d | ||
|
|
9b1a978cb5 | ||
|
|
fb27fb8aa4 | ||
|
|
a612af4f68 | ||
|
|
eb8e076732 | ||
|
|
0401e97ed3 | ||
|
|
c4f25b7a41 | ||
|
|
ef5b628b31 | ||
|
|
543c13d94b | ||
|
|
b9dad93c9d | ||
|
|
18696ec542 | ||
|
|
5efdffcda8 | ||
|
|
ccd39474c7 | ||
|
|
386ec5ade0 | ||
|
|
ee6b3b535c | ||
|
|
d5ee57f04d | ||
|
|
b6c70bad45 | ||
|
|
921d35367b | ||
|
|
253bd47c75 | ||
|
|
8fa10cd8c1 | ||
|
|
01e5b52500 | ||
|
|
9c921adc5b | ||
|
|
b90962943a | ||
|
|
ad4fc6ea9b | ||
|
|
62310ab863 | ||
|
|
ef7b8cd98f | ||
|
|
5e128ebf04 | ||
|
|
b324d98125 | ||
|
|
8329728b81 | ||
|
|
ba220e9d55 | ||
|
|
6b2ef71296 | ||
|
|
bcf7802f94 | ||
|
|
769e2cb897 | ||
|
|
d55caf2278 | ||
|
|
69ca6677e9 | ||
|
|
3d94626ff1 | ||
|
|
5458819ef5 | ||
|
|
2ff8aef1bf | ||
|
|
16556ddb84 | ||
|
|
aef6fe9229 | ||
|
|
e5460ae3cc | ||
|
|
b6f4cbfb4f | ||
|
|
c83fcb7f26 | ||
|
|
ab0d126c49 | ||
|
|
fd3142bc19 | ||
|
|
af80d8e89b | ||
|
|
c98eefe3ec | ||
|
|
84ec0a7e1c | ||
|
|
4babe3e05d | ||
|
|
8213f6f8d7 | ||
|
|
30329ea4db | ||
|
|
4b856c4905 | ||
|
|
418f4a4785 | ||
|
|
2d31aeecd1 | ||
|
|
b3b3ca3fe4 | ||
|
|
5a4ac549f6 | ||
|
|
f4cdeb3dc5 | ||
|
|
7b01d4722f | ||
|
|
019c73ceca | ||
|
|
10fef4e2d9 | ||
|
|
c613b185da | ||
|
|
1bb7ce6805 | ||
|
|
9b3d8b5a06 | ||
|
|
5f603e6652 | ||
|
|
a20bd6933b | ||
|
|
13ea3ae9b3 | ||
|
|
a73920f4c3 | ||
|
|
543d54f844 | ||
|
|
4bd374e747 | ||
|
|
295cf5e066 | ||
|
|
2824e1325d | ||
|
|
cd9e27bcf3 | ||
|
|
9600e450af | ||
|
|
8e56667760 | ||
|
|
1eac218910 | ||
|
|
27962cd25f | ||
|
|
3de32945f2 | ||
|
|
9593b68d33 | ||
|
|
9166fc50aa | ||
|
|
fb5342594f | ||
|
|
733ff867e9 | ||
|
|
d3f9b43b12 | ||
|
|
30ab479315 | ||
|
|
9d3559cddb | ||
|
|
6d3edff5b6 | ||
|
|
619471369d | ||
|
|
2d328234a1 | ||
|
|
06acfe1ee3 | ||
|
|
a55cba4c1f | ||
|
|
61f8a07753 | ||
|
|
e0da9e1a87 | ||
|
|
3ba3ea6317 | ||
|
|
834e40d6f2 | ||
|
|
f93cccd849 | ||
|
|
0127b43374 | ||
|
|
5cea38e95c | ||
|
|
964b8aa5f6 | ||
|
|
33616de6c8 | ||
|
|
6bf490f7da | ||
|
|
3e31f7783f | ||
|
|
05f5122c0b | ||
|
|
93de208ac0 | ||
|
|
272466bbbf | ||
|
|
8639372513 | ||
|
|
49acf0c7c9 | ||
|
|
232cbad5bd | ||
|
|
aa2f9d4f50 | ||
|
|
99aa7d3361 | ||
|
|
72decd970a | ||
|
|
fa4e0b3752 | ||
|
|
6615229003 | ||
|
|
24300e6e50 | ||
|
|
f8445ab2e4 | ||
|
|
9645decf59 | ||
|
|
f34c33b0d8 | ||
|
|
5cd20b1e22 | ||
|
|
d65c565127 | ||
|
|
2f654a1772 | ||
|
|
380f728de2 | ||
|
|
dffdaa8d68 | ||
|
|
1f33204697 | ||
|
|
0566606bfb | ||
|
|
e6f95d0cd8 | ||
|
|
8eda2cd814 | ||
|
|
961634981a | ||
|
|
50aadb574d | ||
|
|
a114457c6f | ||
|
|
9274d88c76 | ||
|
|
97bf39f031 | ||
|
|
158cab9f9b | ||
|
|
bc42efe703 | ||
|
|
e2e1d2ad78 | ||
|
|
772f2695e7 | ||
|
|
5df1144cd0 | ||
|
|
943a7344f6 | ||
|
|
5867559502 | ||
|
|
fdd1eda9ec | ||
|
|
1d7c17e253 | ||
|
|
95484877a3 | ||
|
|
b01d242cbc | ||
|
|
cfd25b0a8d | ||
|
|
2f08c07c20 | ||
|
|
fd5e02c1f4 | ||
|
|
a549edb174 | ||
|
|
1c8f20440c | ||
|
|
5fb09c1c4a | ||
|
|
b7260ed982 | ||
|
|
aec0150a26 | ||
|
|
5c5dfcac89 | ||
|
|
32b9611eb5 | ||
|
|
12881db9ef | ||
|
|
bb8508abbd | ||
|
|
d6565bd2d9 | ||
|
|
b4633efcba | ||
|
|
0a003359ea | ||
|
|
c7e74774de | ||
|
|
dfefd0452d | ||
|
|
38d69c9e6f | ||
|
|
ac26df6827 | ||
|
|
99787950a8 | ||
|
|
80723496d0 | ||
|
|
ec440f13b1 | ||
|
|
8a9c7e54e2 | ||
|
|
67ca25cec4 | ||
|
|
4ca7b2e023 | ||
|
|
aea8b55e82 | ||
|
|
55a4b0ad1b | ||
|
|
f4124db320 | ||
|
|
e23e5a292d | ||
|
|
1f702c20ae | ||
|
|
9b1b915925 | ||
|
|
11bfefcd04 | ||
|
|
fceefac0ee | ||
|
|
98375f8629 | ||
|
|
d4e0cf7e18 | ||
|
|
62af066234 | ||
|
|
00d368080b | ||
|
|
e43b0d1522 | ||
|
|
400b14cd75 | ||
|
|
f88655e214 | ||
|
|
fc74a000a6 | ||
|
|
eb1a86e5b2 | ||
|
|
2fa3570f85 | ||
|
|
da2cf2acc5 | ||
|
|
f68ffefaa9 | ||
|
|
617fbdf8f7 | ||
|
|
034abb06ad | ||
|
|
46b176fc59 | ||
|
|
506686b11e | ||
|
|
1314cf1c19 | ||
|
|
f1e314fa13 | ||
|
|
3bce7de015 | ||
|
|
1bd035e1ca | ||
|
|
3a9ad5adb8 | ||
|
|
022d5bbd7d | ||
|
|
c905489ea5 | ||
|
|
65377d9236 | ||
|
|
8ead6c59c0 | ||
|
|
ea4e8856c2 | ||
|
|
318cfb5fe2 | ||
|
|
7706126479 | ||
|
|
ba84d0ead3 | ||
|
|
5604c6ece5 | ||
|
|
140f2970c4 | ||
|
|
b2ac98d25e | ||
|
|
1ed37897d5 | ||
|
|
29df3d658b | ||
|
|
576397a042 | ||
|
|
b7c9b84449 | ||
|
|
efbf799218 | ||
|
|
7d578ce363 | ||
|
|
e03e584684 | ||
|
|
e8e6b928cf | ||
|
|
5f6d29a3f8 | ||
|
|
a27d83a5e3 | ||
|
|
ef1154d6f3 | ||
|
|
ae2400fd0b | ||
|
|
fbcd004b7e | ||
|
|
cb307f95ce | ||
|
|
7838cd1a6a | ||
|
|
03dcb7d860 | ||
|
|
62c5470efe | ||
|
|
53b4674da4 | ||
|
|
ff2cf68b08 | ||
|
|
8b55373794 | ||
|
|
dba67d7127 | ||
|
|
762c455b53 | ||
|
|
714d1a36c4 | ||
|
|
0e0ddbbd99 | ||
|
|
497f8cfd1f | ||
|
|
1ff709e6f8 | ||
|
|
ea35871aba | ||
|
|
0e78857645 | ||
|
|
5d7d115910 | ||
|
|
b9384afd5d | ||
|
|
dbe020dc94 | ||
|
|
9673aa7690 | ||
|
|
ec06d30d59 | ||
|
|
356d2e592b | ||
|
|
521c2e7ca6 | ||
|
|
c4014c9333 | ||
|
|
2908a8d8a9 | ||
|
|
c964b98240 | ||
|
|
f7c74b5c96 | ||
|
|
d34c9818b4 | ||
|
|
6414c93116 | ||
|
|
5a12c4a3ce | ||
|
|
97a6ee39e5 | ||
|
|
44db5ab150 | ||
|
|
e9bcd29e36 | ||
|
|
a2ca897fca | ||
|
|
9a34e63d5f | ||
|
|
e501b894c3 | ||
|
|
d97ef84b7e | ||
|
|
0f2dc4d3ba | ||
|
|
49a9eb5460 | ||
|
|
7e7780a754 | ||
|
|
d0770970f0 | ||
|
|
d5a10a5817 | ||
|
|
7b63d8b2ba | ||
|
|
c544de8909 | ||
|
|
89da2ab50f | ||
|
|
a1a6b5967b | ||
|
|
53ffb1b565 | ||
|
|
6efecd123f | ||
|
|
1ec5349a96 | ||
|
|
187abcd10c | ||
|
|
d6ca4429d5 | ||
|
|
86e869ff16 | ||
|
|
dc58f9397f | ||
|
|
97b4ab2f15 | ||
|
|
23a9d02aba | ||
|
|
32ed6c3e97 | ||
|
|
102556dd2a | ||
|
|
2df3f7c56d | ||
|
|
d6fd02ec19 | ||
|
|
c901b4bc06 | ||
|
|
e19c89ccd9 | ||
|
|
a667f1a65e | ||
|
|
9f5829876c | ||
|
|
189d7c4719 | ||
|
|
dfe877c438 | ||
|
|
3a634d7888 | ||
|
|
fd9f3d04d9 | ||
|
|
ac70fc37f6 | ||
|
|
c29aeeee41 | ||
|
|
51c13c7b52 | ||
|
|
fec8c0fe53 | ||
|
|
5da2143212 | ||
|
|
30158ac145 | ||
|
|
ff7eecee55 | ||
|
|
0755a4026a | ||
|
|
9aaf363584 | ||
|
|
0a27cd7403 | ||
|
|
ab8cdd88b9 | ||
|
|
dab4a092d9 | ||
|
|
9d365dbf1e | ||
|
|
16d25fb60d | ||
|
|
50d43a2fc5 | ||
|
|
6d99539730 | ||
|
|
cf43dc8e70 | ||
|
|
95c506c638 | ||
|
|
464b768c55 | ||
|
|
00ca4cc5bd | ||
|
|
bfb81ef60d | ||
|
|
420701bf23 | ||
|
|
88073aaa20 | ||
|
|
8456320884 | ||
|
|
3555b08fe8 | ||
|
|
55ad046e96 | ||
|
|
ea4ddb68f3 | ||
|
|
edde5f8a88 | ||
|
|
de28fd4ca4 | ||
|
|
dd7bbb138a | ||
|
|
4a54eb56a7 | ||
|
|
24cda70cbc | ||
|
|
a0c869d0a1 | ||
|
|
58f85992b0 | ||
|
|
f11f5e1ca4 | ||
|
|
0672698ba7 | ||
|
|
cf37f7c950 | ||
|
|
c7d64554ad | ||
|
|
039021532e | ||
|
|
e39ae170c3 | ||
|
|
8a44fe9d1c | ||
|
|
70649653fb | ||
|
|
db1f241c33 | ||
|
|
c9ed317e62 | ||
|
|
afde26a7ae | ||
|
|
1a2d9ba2b2 | ||
|
|
3943536485 | ||
|
|
e963a4051f | ||
|
|
2b02194a18 | ||
|
|
dd1aec3b60 | ||
|
|
0b05d4d186 | ||
|
|
8f0327604f | ||
|
|
40dddb3316 | ||
|
|
be7ea64c5a | ||
|
|
8eef0e410e | ||
|
|
63f0b20fd6 | ||
|
|
87a685b823 | ||
|
|
4796a494de | ||
|
|
a329ff3796 | ||
|
|
00ab65e720 | ||
|
|
4997e25cdc | ||
|
|
6ce05984d5 | ||
|
|
26e08774b0 | ||
|
|
83ce9fb4c4 | ||
|
|
ac946f4903 | ||
|
|
d6480db609 | ||
|
|
9f9c191240 | ||
|
|
cb781aa4ad | ||
|
|
6a31e88855 | ||
|
|
f862e5ea1b | ||
|
|
b8de3e9867 | ||
|
|
1959160681 | ||
|
|
b665ec5717 | ||
|
|
8ef2c12be1 | ||
|
|
d85e7f0bcb | ||
|
|
544d65c7d0 | ||
|
|
1bd5fc389a | ||
|
|
9149d6de9a | ||
|
|
261d9fcd79 | ||
|
|
5ecac4223d | ||
|
|
215c21ad8a | ||
|
|
5772de888c | ||
|
|
55979e90dc | ||
|
|
5785f5beea | ||
|
|
e8bb256a8d | ||
|
|
729a563545 | ||
|
|
1b38ed5c78 | ||
|
|
483aea5c4f | ||
|
|
a64d493a29 | ||
|
|
2a8d436267 | ||
|
|
7905f82d65 | ||
|
|
dcf82d041a | ||
|
|
9618bd891f | ||
|
|
c63f9de5c5 | ||
|
|
0e6113f0a6 | ||
|
|
71cf85f535 | ||
|
|
2a4f646181 | ||
|
|
0cc326836c | ||
|
|
52b8bc8909 | ||
|
|
844a7b455c | ||
|
|
489a0b6fb8 | ||
|
|
e535133eca | ||
|
|
ea2be7609c | ||
|
|
011d9d639b | ||
|
|
e78e9d8e55 | ||
|
|
89762cad78 | ||
|
|
4788562241 | ||
|
|
5b1ad450d3 | ||
|
|
7b6d8671cf | ||
|
|
01631860f4 | ||
|
|
c65e76bbc3 | ||
|
|
ef35e1cfd9 | ||
|
|
1d535b5d61 | ||
|
|
004cb20132 | ||
|
|
909bdf60e7 | ||
|
|
0cd3bea6bd | ||
|
|
d001a0de15 | ||
|
|
0dca7acee6 | ||
|
|
b5ad7a1721 | ||
|
|
9f23b911c1 | ||
|
|
1db8bb4d13 | ||
|
|
eebafda9e5 | ||
|
|
0fb57a0a2c | ||
|
|
d4c55620f1 | ||
|
|
ef26567850 | ||
|
|
c15c43dba4 | ||
|
|
5d738d99fe | ||
|
|
43120b0017 | ||
|
|
23dc82f042 | ||
|
|
49330536c7 | ||
|
|
781fa7ea1b | ||
|
|
bf17312a5f | ||
|
|
e4da8d4f15 | ||
|
|
cc26bd09e6 | ||
|
|
9dc1c5c9e9 | ||
|
|
442ae94ad5 | ||
|
|
43820f71a3 | ||
|
|
63920e034a | ||
|
|
cddc47305f | ||
|
|
583bebd10c | ||
|
|
7fe9a6c900 | ||
|
|
670e457dc6 | ||
|
|
300d8224ec | ||
|
|
924f5320bb | ||
|
|
dd09fb2283 | ||
|
|
3e18af626b | ||
|
|
89dd5b79d6 | ||
|
|
356f71f13e | ||
|
|
2f5d71a299 | ||
|
|
b581c12edb | ||
|
|
d4d6aeb0b4 | ||
|
|
77114e6cfc | ||
|
|
e14a078440 | ||
|
|
3b38a0d628 | ||
|
|
927d8cb6c9 | ||
|
|
eb8ea2f549 | ||
|
|
208c93bc8f | ||
|
|
93180faa23 | ||
|
|
816858f231 | ||
|
|
fa1d68848f | ||
|
|
bce955a1e1 | ||
|
|
82f70e0ac9 | ||
|
|
fc9b78cfef | ||
|
|
72400a48da | ||
|
|
537b39b3c4 | ||
|
|
47e6e48729 | ||
|
|
d252229777 | ||
|
|
7f4c7f607d | ||
|
|
994ba5dd1a | ||
|
|
e3a06b28dd | ||
|
|
10d512470e | ||
|
|
c1d8040fd5 | ||
|
|
e4b81da386 | ||
|
|
fd7360e6f4 | ||
|
|
62f15e218e | ||
|
|
5c1b91f348 | ||
|
|
378cbd580f | ||
|
|
3994f14010 | ||
|
|
e7f4e743e3 | ||
|
|
b934ce2893 | ||
|
|
5eec076ea2 | ||
|
|
ada36ebff5 | ||
|
|
d9543ca23c | ||
|
|
3871eb3c84 | ||
|
|
4ba696d289 | ||
|
|
2f69e0b96c | ||
|
|
d6b0c56c35 | ||
|
|
d8fe983b9d | ||
|
|
76079faca0 | ||
|
|
5d5c62123c | ||
|
|
6c7b2224b1 | ||
|
|
4d80ae2372 | ||
|
|
c651b60c59 | ||
|
|
90b39d075d | ||
|
|
5099c7e462 | ||
|
|
2f8b5dd229 | ||
|
|
7e427605ab | ||
|
|
512e640c13 | ||
|
|
acb1c6cc99 | ||
|
|
d01c3ff9ca | ||
|
|
3720644153 | ||
|
|
630cfb6769 | ||
|
|
f3061ed643 | ||
|
|
2556c037ba | ||
|
|
0b4626a5a2 | ||
|
|
1c9e993194 | ||
|
|
dc3a465f09 | ||
|
|
6d008efd54 | ||
|
|
6aa970c375 | ||
|
|
1ecd01204b | ||
|
|
33bd8d1cd1 | ||
|
|
31d2c3c98e | ||
|
|
b082ec19aa | ||
|
|
9ccb496069 | ||
|
|
3871a7de84 | ||
|
|
c6931e3492 | ||
|
|
c8b2a38c99 | ||
|
|
a7bdcd8dd8 | ||
|
|
8196cd597a | ||
|
|
52deb6bb79 |
63
.gitattributes
vendored
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
14
.gitignore
vendored
@@ -2,17 +2,11 @@
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
WebFirst/SoEasyPlatform.exe
|
||||
WebFirst/excel
|
||||
WebFirst/wwwroot
|
||||
WebFirst/SoEasyPlatform.exe
|
||||
WebFirst/appsettings.Development.json
|
||||
WebFirst/appsettings.json
|
||||
WebFirst/SoEasyPlatform.pdb
|
||||
WebFirst/SoEasyPlatform.Views.pdb
|
||||
WebFirst/web.config
|
||||
WebFirst/WebFirst.exe
|
||||
dist/
|
||||
|
||||
appsettings.Production.json
|
||||
appsettings.Development.json
|
||||
wwwroot
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
||||
214
LICENSE
@@ -1,201 +1,21 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
MIT License
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
Copyright (c) 2022 jacktang
|
||||
|
||||
1. Definitions.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
334
README.md
@@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
<h1 align="center"><img align="left" height="100px" src="https://user-images.githubusercontent.com/68722157/138828506-f58b7c57-5e10-4178-8f7d-5d5e12050113.png"> Yi框架</h1>
|
||||
<h4 align="center">一套与SqlSugar一样爽的.Net6低代码开源框架</h4>
|
||||
<h1 align="center"><img align="left" height="150px" src="https://user-images.githubusercontent.com/68722157/138828506-f58b7c57-5e10-4178-8f7d-5d5e12050113.png"> Yi框架</h1>
|
||||
<h4 align="center">一套以用户体验出发的.Net6 Web开源框架</h4>
|
||||
<h5 align="center">支持原生版本、Furion版本、Abp版本,前端后台接入Ruoyi Vue3.0</h5>
|
||||
<h2 align="center">集大成者,终究轮子</h2>
|
||||
|
||||
[English](README-en.md) | 简体中文
|
||||
@@ -10,162 +9,245 @@
|
||||
|
||||
****
|
||||
### 简介:
|
||||
**中文:意框架**(和他的名字一样“简易”)
|
||||
**中文:意框架**(和他的名字一样“简易”,同时接入Java的Ruoyi Vue3.0前端)
|
||||
|
||||
模块分化较多,可根据业务自行引用或抛弃,集大成者,大而全乎,也许你能从中学习到一些独特见解
|
||||
|
||||
**英文:YiFramework**
|
||||
|
||||
Yi框架-一套与SqlSugar一样爽的.Net6低代码开源框架。
|
||||
Yi框架-一套与SqlSugar一样爽的.Net6开源框架。
|
||||
与Sqlsugar理念一致,以用户体验出发。
|
||||
架构干净整洁、无业务代码、采用微软风格原生框架封装、WebFrist开发。
|
||||
适合.Net6学习、Sqlsugar学习 、项目二次开发。
|
||||
集大成者,终究轮子
|
||||
|
||||
Yi框架最新版本标签:`v1.0.3` 更新时间:2022/4/18
|
||||
Yi框架最新版本标签:`v3.0.0`,具体版本可以查看标签迭代
|
||||
|
||||
(项目与Sqlsugar同步更新,但这作者老杰哥代码天天爆肝到凌晨两点,我们也尽量会跟上他的脚步。更新频繁,所以可watching持续关注。)
|
||||
|
||||
————这不仅仅是一个程序,更是一个艺术品,面向艺术的开发!
|
||||
|
||||
**分支**:
|
||||
> 核心特点:简单好用,框架不以打包形式引用,而是直接以项目附带源码给出,自由度拉满,遵循Mit协议,允许随意修改(请注明来源即可)
|
||||
|
||||
(本项目由EFCore版本历经3年不断迭代至Sqlsugar版本,现EFcore版本已弃用,目前sqlsugar不带任何业务,之后会更新业务功能)
|
||||
**分支:**
|
||||
|
||||
**SqlSugar**:.Net6 DDD领域驱动设计 简单分层微服务架构
|
||||
(本项目由EFCore版本历经4年不断迭代至Sqlsugar版本,现EFcore版本已弃用,目前sqlsugar已带业务功能)
|
||||
|
||||
**ec**:EFcore完整电商项目
|
||||
- (推荐) **Furion**: 基于Furion分支,回归开发本质,极度简单,用起来贼爽
|
||||
|
||||
- ~~**Framework**~~: 框架分支,所有东西都在这里
|
||||
|
||||
- ~~**SqlSugar**:.Net6 DDD领域驱动设计 简单分层微服务架构~~
|
||||
|
||||
- ~~**SqlSugar-Dev**:为sqlsugar分支的实时开发版本~~
|
||||
|
||||
- ~~**abp**:基于abp.vnext项目~~
|
||||
|
||||
****
|
||||
|
||||
**目录:**
|
||||
|
||||
Yi后端框架分为3个部分:
|
||||
|
||||
- Infrastructure(基础设施,框架底层+sqlsugar+furion)
|
||||
- Module(应用模块,可选项,例如缓存模块、微信模块、文件模块、日志模块等)
|
||||
- Application(业务模块,用于开发)
|
||||
|
||||
另外,光说不练假把式,我们不仅仅提供一个空白的框架,还同时提供3个基于yi框架的业务模块,没有听错,目前为1个后端,支持3个前端。各个模块关系解耦,可单独使用其中的任意业务模块
|
||||
|
||||
- Yi.RuoYi.Vue3:Ruoyi后台管理系统Rbac Vue3前端(推荐)
|
||||
|
||||
- Yi.Furion.Net6:.NET6后端(推荐)
|
||||
|
||||
- Yi.App.Vue3:移动端App Vue3前端
|
||||
|
||||
- Yi.BBS.Vue3:Web网页端BBS论坛 Vue3+Ts前端
|
||||
|
||||
后续我们持续更新各大应用模块及业务模块:shop商场、erp进销存、mes工厂系统等
|
||||
|
||||
业务支持并扩展至各个领域,用于具体项目的二次开发极大复用后端代码及前端代码,以通用的部分+不通的部分快速二开
|
||||
|
||||
|
||||
### 演示地址:
|
||||
|
||||
废话少说直接上地址,**请不要**更改里面的数据
|
||||
|
||||
API服务:~~[yi.ccnetcore.com](http://yi.ccnetcore.com) 管理员账号:admin 、 123~~
|
||||
官网网址:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
网关地址:~~[gate.ccnetcore.com/swagger](http://gate.ccnetcore.com/swagger)~~
|
||||
Bbs社区系统:[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
WebFirst开发:所有代码生成器已经配置完成,无需任何操作数据库及任何代码,只需要网页表格上点点点即可
|
||||
Rbac后台管理系统:[yi.ccnetcore.com](http://yi.ccnetcore.com) (已上线)~~管理员账号:cc 、 123456~~
|
||||
|
||||
[https://www.donet5.com/Doc/11](https://www.donet5.com/Doc/11)
|
||||
App移动端系统:[xxx](xxx)正在部署
|
||||
|
||||
谁能把持的住Sqlsugar作者自己都依赖成瘾的东西呢?这是继DbFirst、CodeFirst下一代的划时代产品!无脑爽!
|
||||
|
||||

|
||||
|
||||
(首次添加实体后,生成代码记得修改对应的路径哦~~)
|
||||
网关地址:~~[gate.ccnetcore.com/swagger](http://gate.ccnetcore.com/swagger)~~(目前使用单体架构部署,无需网关)
|
||||
|
||||
### 支持:
|
||||
|
||||
- [x] 完全支持单体应用架构
|
||||
- [x] 完全支持分布式应用架构
|
||||
- [x] 完全支持微服务架构
|
||||
- [ ] 即将支持网格服务架构(我们将在后续版本加入dapr)
|
||||
|
||||
****
|
||||
### 软件架构:
|
||||
### 详细到爆炸的Yi框架教程导航:
|
||||
|
||||
**架构**:后端.NET6(Asp.NetCore 6)、WebFirst代码生成器~~与.NET5(Asp.NetCore 5)、前端Vue(2.0)~~
|
||||
|
||||
**关系型数据库**:mysql、sql server、sqlite、oracle(正在兼容中)
|
||||
|
||||
**操作系统**:Windows、Linux
|
||||
|
||||
**身份验证**:JWT、IdentityServer4
|
||||
|
||||
**组件**:~~EFcore~~SqlSugar、Autofac、Castle、Swagger、Log4Net、Redis、RabbitMq、ES、Quartz.net、~~T4~~
|
||||
|
||||
**分布式**:CAP、Lock
|
||||
|
||||
**微服务**:Consul、Ocelot、IdentityService、Apollo、Docker、Jenkins、Nginx、K8s、ELK、Polly
|
||||
|
||||
**封装**:Json处理模块,滑动验证码模块,base64图片处理模块,异常捕捉模块、邮件处理模块、linq封装模块、随机数模块、统一接口模块、基于策略的jwt验证、过滤器、数据库连接、跨域、初始化种子数据、Base32、Console输出、日期处理、文件传输、html筛选、http请求、ip过滤、md5加密、Rsa加密、序列化、雪花算法、字符串处理、编码处理、地址处理、xml处理、心跳检查。。。
|
||||
1. [框架快速开始](https://ccnetcore.com/article/1641733850189139969)(已完成)
|
||||
2. [框架模块教程](https://ccnetcore.com/article/1641733991574933505)(已完成)
|
||||
3. [应用模块教程](https://ccnetcore.com/article/1641734073091231745)
|
||||
4. [Yi.RBAC后台系统](https://ccnetcore.com/article/1641734171128893441)
|
||||
5. [Yi.BBS社区系统](https://ccnetcore.com/article/1641734308475572225)
|
||||
|
||||
****
|
||||
### 支持模块:
|
||||
### 它的理念:
|
||||
优雅的进行快速开发,通常,简单程度与优雅程度不可兼得,Yi框架并不一昧的追求极致的解耦,会站在用户使用角度上,在使用难易度进行考虑衡量
|
||||
|
||||
大致如图:
|
||||
例如:我们大部分功能紧密贴合Sqlsugar,虽然缺少其他orm的替换性,但在使用程度上降低的使用难度
|
||||
|
||||

|
||||

|
||||

|
||||
> 一个面向用户的快速开发后端框架
|
||||
|
||||
(删除线代表已实现功能还未迁移过来)
|
||||
- [x] 支持大致`DDD领域驱动设计`进行分层,支持微服务扩展
|
||||
- [x] 支持采用`异步`开发awit/async
|
||||
- [x] 支持数据库主从`读写分离`
|
||||
- [x] 支持功能替换,无需改动代码,只需配置`json文件`进行装配即可
|
||||
- [x] ~~-支持采用DbFirst开发方式,使用`T4模板代码生成器`,自动映射模型一键生成Service及IService所有代码~~
|
||||
- [x] 支持WebFirst,无需改动代码,自动生成全套代码与数据库,只需点点点
|
||||
- [x] ~~-支持`用户-角色-菜单-接口`以及vue2.0前端全部逻辑代码,下载无需修改直接使用~~
|
||||
- [x] 支持`Aop封装`,FilterAop、IocAop、LogAop、SqlAop
|
||||
- [x] 支持`Log4Net日志`记录,自动生成至bin目录下的logs文件夹
|
||||
- [x] 支持`DbSeed数据库种子数据`接入
|
||||
- [x] 支持主流`数据库随意切换`,Mysql/Sqlite/Sqlserver/Oracle
|
||||
- [x] 支持上海杰哥官方`SqlSugar ORM`封装
|
||||
- [x] 支持新版`SwaggerWebAPI`,jwt身份认证接入
|
||||
- [x] 支持`Cors`跨域
|
||||
- [x] 支持`AutoFac`自动映射依赖注入
|
||||
- [x] 支持`consul`服务器注册与发现
|
||||
- [x] 支持`健康检查`
|
||||
- [x] 支持`RabbitMQ`消息队列
|
||||
- [x] 支持`Redis`多级缓存
|
||||
- [x] 支持`Ocelot`网关,路由、服务聚合、服务发现、认证、鉴权、限流、熔断、缓存、Header头传递
|
||||
- [x] 支持`Apollo`全局配置中心;
|
||||
- [x] 支持`docker`镜像制作
|
||||
- [x] ~~-支持页面`静态化处理`,将动态页面生成静态页面~~
|
||||
- [x] 支持`Quartz.net`任务调度,实现任意接口被调度
|
||||
- [x] 支持`ELK`,log4net+kafka+es+logstach+kibana
|
||||
- [x] 支持`IdentityService4`授权中心
|
||||
- [x] 支持`Es`分词查询
|
||||
- [x] 支持多级`缓存`
|
||||
- [x] 支持`CAP`分布式事务,mysql+rabbitMq
|
||||
- [x] 支持`Docker+k8s`部署
|
||||
- [x] 支持`Jenkins+CI/CD`
|
||||
- [x] 支持`AutoMapper`模块映射
|
||||
- [ ] 支持`微信支付`(没账号)
|
||||
- [x] 支持`单表多租户`常用功能
|
||||
- [x] 支持`逻辑删除`常用功能
|
||||
- [x] 支持`操作日志`常用功能
|
||||
- [x] 支持 太多了忘了
|
||||
在真正的使用这,你会明白这一点,极致的简单,也是优雅的一种体现。
|
||||
****
|
||||
|
||||
### 特点:
|
||||
- 面向用户的后端框架,使用简单,适合小型、企业级项目
|
||||
- 项目内置源码,不打包
|
||||
- 开箱即用
|
||||
- 支持模块化
|
||||
- 支持动态Api
|
||||
- 支持属性注入
|
||||
- 内置包含大量通用场景模块
|
||||
- 等等
|
||||
|
||||
### 基础设施简介
|
||||
- Jwt鉴权
|
||||
- 接口级别授权
|
||||
- 对象映射
|
||||
- O/RM
|
||||
- 数据过滤
|
||||
- 多租户
|
||||
- 逻辑删除
|
||||
- 审计日志
|
||||
- 种子数据
|
||||
- 工作单元
|
||||
- 模块化
|
||||
- 动态Api
|
||||
- 属性注入
|
||||
- 自动依赖注入
|
||||
- 当前用户
|
||||
- 仓储
|
||||
- Crud
|
||||
|
||||
|
||||
### 内置模块简介
|
||||
- 后台任务
|
||||
- 本地缓存
|
||||
- 分布式缓存
|
||||
- 事件总线
|
||||
- 字典管理
|
||||
- 文件管理
|
||||
- 图片操作
|
||||
- Excel操作
|
||||
- 操作日志管理
|
||||
- Sms短信
|
||||
- 微信支付
|
||||
- WebFirst代码生成
|
||||
|
||||
### 业务项目
|
||||
- RABC后台管理系统
|
||||
- BBS社区系统
|
||||
- APP移动端系统
|
||||
|
||||
> 重复的东西,无需再写一遍,这也是优雅的体现之一
|
||||
|
||||
****
|
||||
### 目录结构:
|
||||
### 核心技术
|
||||
#### 后端
|
||||
C# Asp.NetCore 6.0
|
||||
- [x] 动态Api:Cike.AutoApi
|
||||
- [x] 鉴权授权:Jwt
|
||||
- [x] 日志:Nlog
|
||||
- [x] 模块化:StartupModules
|
||||
- [x] 依赖注入:Autofac
|
||||
- [x] 对象映射:Mapster
|
||||
- [x] ORM:SqlsugarCore
|
||||
- [x] 多租户:Abp
|
||||
- [x] 后台任务:Quartz.Net
|
||||
- [x] 本地缓存:MemortCache
|
||||
- [x] 分布式缓存:CSRedisCore
|
||||
- [x] 事件总线:Cike.EventBus
|
||||
- [x] 图像操作:SixLabors.ImageSharp
|
||||
- [x] Excle操作:ExcelToObject.Npoi
|
||||
|
||||

|
||||
#### 前端
|
||||
js Vue3.2
|
||||
- [x] 异步请求:axios
|
||||
- [x] 图表:echarts
|
||||
- [x] ui:element-plus
|
||||
- [x] 存储:pinia
|
||||
- [x] 路由:vue-router
|
||||
- [x] 打包:vite
|
||||
|
||||
我们大致依照DDD领域驱动设计分层
|
||||
|
||||
什么?感觉太复杂了?用户只需关注Api、Service其他都是轮子啊!
|
||||
|
||||
~~- BackGround:后台进程(目前可以无视,等待更新)~~
|
||||
- Client:客户端(测试、客户端)
|
||||
- Domain:领域层(Dto、服务接口层、模型层、仓储层、服务层)
|
||||
- Infrastructure:基础实例层(通用工具层、核心层、定时任务Job、国际化、Web扩展层)
|
||||
- MicroServiceInstance:服务层(微服务)
|
||||
#### 运维
|
||||
- [x] 部署:nginx
|
||||
- [x] CICD:gitlab+Jenkins
|
||||
- [x] Docker:harbor
|
||||
|
||||
****
|
||||
### 安装教程:
|
||||
### 业务支持模块:
|
||||
|
||||
我们将在之后更新教程手册!
|
||||
RABC权限管理系统(正在更新)
|
||||
(采用ruoyi前端)
|
||||
- 用户管理
|
||||
- 角色管理
|
||||
- 菜单管理
|
||||
- 部门管理
|
||||
- 岗位管理
|
||||
- 字典管理
|
||||
- 参数管理
|
||||
- 用户在线
|
||||
- 操作日志
|
||||
- 登录日志
|
||||
- 定时任务
|
||||
- 缓存列表
|
||||
- 服务监控
|
||||
- WebFirst代码生成工具
|
||||
|
||||
1. 下载全部源码,默认使用sqlite数据库,已经生成
|
||||
2. 直接点击sln文件运行即可,没有其他依赖
|
||||
**演示截图:**
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
****
|
||||
### 使用说明:
|
||||
BBS论坛系统(持续迭代)
|
||||
- 文章管理
|
||||
- 评论管理
|
||||
- 主题管理
|
||||
- 板块管理
|
||||
- 点赞管理
|
||||
- 等等
|
||||
|
||||
1. 导入使用仓库中的WebFirst数据库
|
||||
2. 使用WebFirst添加实体、同步实体、修改模板生成路径并生成方案
|
||||
APP移动端系统(持续迭代)
|
||||
- 动态查询
|
||||
- 我的资料
|
||||
|
||||
没了,恭喜你已经成功完成了项目,并且已经具备大部分通用场景业务
|
||||
是不是一个字?爽!
|
||||
到此为止,你无需写任何一个代码!
|
||||
ERP进销存系统(持续迭代)
|
||||
- 供货商管理
|
||||
- 等等
|
||||
|
||||
**爽点**:
|
||||
SHOP电商系统(持续迭代)
|
||||
- SPU管理
|
||||
- SKU管理
|
||||
- 商品规格
|
||||
- 商品分类
|
||||
- 等等
|
||||
|
||||
新人,看这里,项目下载之后直接可以启动,无任何依赖,之后你可以查看`Test控制器`,迫不及待的快来爽一爽!
|
||||
|
||||
我们将使用说明转移至我们的官方论坛中,正在制作中,尽情期待!
|
||||
|
||||
****
|
||||
### 感谢:
|
||||
@@ -178,42 +260,30 @@ WebFirst开发:所有代码生成器已经配置完成,无需任何操作数
|
||||
|
||||
[朝夕教育]https://www.zhaoxiedu.net
|
||||
|
||||
[Sqlsugar]https://www.donet5.com/Home/Doc
|
||||
[Sqlsugar老杰哥]https://www.donet5.com/Home/Doc
|
||||
|
||||
[RuYiAdmin]https://gitee.com/pang-mingjun/RuYiAdmin
|
||||
[RuYiAdmin如意老兄]https://gitee.com/pang-mingjun/RuYiAdmin
|
||||
|
||||
[ZrAdminNetCore]https://gitee.com/izory/ZrAdminNetCore
|
||||
[ZrAdminNetCore字母老哥]https://gitee.com/izory/ZrAdminNetCore
|
||||
|
||||
[Admin.NET周哥]https://gitee.com/zuohuaijun/Admin.NET
|
||||
|
||||
[Furion百小僧]https://furion.baiqian.ltd/
|
||||
|
||||
****
|
||||
### 联系我们:
|
||||
|
||||
作者QQ:454313500
|
||||
作者QQ:`454313500`,2029年之前作者24小时在线,时刻保持活跃更新。
|
||||
|
||||
QQ交流群:官方一群(已满)、官方二群(已满)、官方三群:`786308927`(基本已满)、官方四群:`498310311`(新群)
|
||||
|
||||
联系作者,这里人人都是顾问
|
||||
|
||||
官方网址:正在建设
|
||||
官方网址留言区:[ccnetcore.com](https://ccnetcore.com)
|
||||
|
||||
****
|
||||
### FQA:
|
||||
|
||||
问1:为什么不采用EFcore?
|
||||
前往官网查看留言区
|
||||
|
||||
答1:别问,问就是Sqlsugar,和本框架一样爽!
|
||||
|
||||
问2:以后会持续更新下去吗?
|
||||
|
||||
答2:一定会的,我们的标题是 一个和Sqlsugar一样爽的.Net6开源框架 ,只要Sqlsugar在,我们将一直更新下去。
|
||||
|
||||
问3:这个框架的针对人群是哪些人?适合所有人吗?
|
||||
|
||||
答3:并不是适合所有人,应该算适合需要有一定基础的开发人员,当然,如果你是大神,你完全可以将这个框架二次开发!
|
||||
|
||||
问4:花如此多的精力制作这个框架,是为了什么?是为了赚钱吗?和目前主流的abp等框架比,又有什么意义呢?
|
||||
|
||||
答4:我们与Sqlsugar作者理念一致,我们是从用户角度出发,框架是为用户服务,与ABP复杂上手理念完全是相反的。
|
||||
|
||||
问5:为何不出版一个详细的说明书呢?
|
||||
|
||||
答5:暂时不会了,之后可能会,代码都是基于Asp.NetCore框架,适用于新手不用造轮子,整个框架较为简单,阅读源码后,基本能自定义改造使用了,过难也已经封装完毕,别忘了,其意义是为了开发更加简易!建议添加作者好友,这里人人都是顾问。
|
||||
|
||||
我大抵要厌倦了负重前行。
|
||||
[留言区](https://ccnetcore.com/discuss/1641030787056930818)
|
||||
17
Yi.App.Vue3/.env.development
Normal file
@@ -0,0 +1,17 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 意框架管理系统
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 若依管理系统/开发环境
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
|
||||
# ws/开发环境
|
||||
VITE_APP_BASE_WS = '/dev-ws'
|
||||
|
||||
|
||||
VITE_APP_BASE_URL='http://localhost:19001/api'
|
||||
|
||||
|
||||
|
||||
15
Yi.App.Vue3/.env.production
Normal file
@@ -0,0 +1,15 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 意框架管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
|
||||
# 意框架管理系统/生产环境
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
|
||||
# ws/开发环境
|
||||
VITE_APP_BASE_WS = '/prod-ws'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
|
||||
15
Yi.App.Vue3/.env.staging
Normal file
@@ -0,0 +1,15 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 意框架管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
# 若依管理系统/生产环境
|
||||
VITE_APP_BASE_API = '/stage-api'
|
||||
|
||||
# ws/开发环境
|
||||
VITE_APP_BASE_WS = '/stage-ws'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
|
||||
24
Yi.App.Vue3/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
3
Yi.App.Vue3/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
16
Yi.App.Vue3/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Vue 3 + TypeScript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
|
||||
|
||||
## Type Support For `.vue` Imports in TS
|
||||
|
||||
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
|
||||
|
||||
1. Run `Extensions: Show Built-in Extensions` from VS Code's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
|
||||
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).
|
||||
0
Yi.App.Vue3/components.d.ts
vendored
Normal file
13
Yi.App.Vue3/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>意框架</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
2543
Yi.App.Vue3/package-lock.json
generated
Normal file
29
Yi.App.Vue3/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "yi",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.1.2",
|
||||
"json-bigint": "^1.0.0",
|
||||
"pinia": "^2.0.23",
|
||||
"vant": "^3.6.3",
|
||||
"vue": "^3.2.37",
|
||||
"vue-router": "^4.1.5",
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/json-bigint": "^1.0.1",
|
||||
"@types/node": "^18.8.2",
|
||||
"@vitejs/plugin-vue": "^3.1.0",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-vue-components": "^0.22.7",
|
||||
"vite": "^3.1.0",
|
||||
"vue-tsc": "^0.40.4"
|
||||
}
|
||||
}
|
||||
BIN
Yi.App.Vue3/public/icon.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
1
Yi.App.Vue3/public/vite.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
16
Yi.App.Vue3/src/App.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<!-- <HelloWorld msg="123"></HelloWorld> -->
|
||||
<router-view></router-view>
|
||||
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
11
Yi.App.Vue3/src/api/agreeApi.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default {
|
||||
operate(data:any) {
|
||||
return myaxios({
|
||||
url: `/agree/operate`,
|
||||
method: 'get',
|
||||
params: {articleId:data}
|
||||
})
|
||||
},
|
||||
}
|
||||
18
Yi.App.Vue3/src/api/articleApi.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default {
|
||||
add(data:any) {
|
||||
return myaxios({
|
||||
url: `/Trends`,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
},
|
||||
pageList(data:any) {
|
||||
return myaxios({
|
||||
url: '/Trends',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
}
|
||||
17
Yi.App.Vue3/src/api/commentApi.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default {
|
||||
add(data:any) {
|
||||
return myaxios({
|
||||
url: `/comment/add`,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
},
|
||||
getListByArticleId(articleId:any) {
|
||||
return myaxios({
|
||||
url: `/comment/GetListByArticleId/${articleId}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
}
|
||||
12
Yi.App.Vue3/src/api/fileApi.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default{
|
||||
upload(data:any){
|
||||
return myaxios({
|
||||
url: `/file`,
|
||||
headers:{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"},
|
||||
method: 'post',
|
||||
data:data
|
||||
});
|
||||
}
|
||||
}
|
||||
59
Yi.App.Vue3/src/api/login.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
// 登录方法
|
||||
export function login(username:string, password:string, code:string, uuid:string) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid
|
||||
}
|
||||
return myaxios({
|
||||
url: '/account/login',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 注册方法
|
||||
export function register(data:any) {
|
||||
return myaxios({
|
||||
url: '/register',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return myaxios({
|
||||
url: '/account',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 退出方法
|
||||
export function logout() {
|
||||
return myaxios({
|
||||
url: '/account/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return myaxios({
|
||||
url: '/account/captchaImage',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
18
Yi.App.Vue3/src/api/skuApi.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default {
|
||||
add(data:any) {
|
||||
return myaxios({
|
||||
url: `/sku/add`,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
},
|
||||
pageList(data:any) {
|
||||
return myaxios({
|
||||
url: '/sku/pageList',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
}
|
||||
25
Yi.App.Vue3/src/api/spuApi.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import myaxios from '@/utils/myaxios'
|
||||
|
||||
export default {
|
||||
add(data: any) {
|
||||
return myaxios({
|
||||
url: `/spu/add`,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
},
|
||||
pageList(data: any) {
|
||||
return myaxios({
|
||||
url: '/spu/pageList',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
},
|
||||
getById(id: any) {
|
||||
return myaxios({
|
||||
url: `/spu/GetById/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
1
Yi.App.Vue3/src/assets/vue.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 496 B |
61
Yi.App.Vue3/src/components/AppCard.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
|
||||
<div class="out-div">
|
||||
<div class="card-div">
|
||||
|
||||
<van-image
|
||||
radius="1rem"
|
||||
width="100%"
|
||||
height="100%"
|
||||
src="https://unpkg.com/@vant/assets/cat.jpeg"
|
||||
/>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="bottom-div">
|
||||
<div v-for="i of 10" :key="i" class="card-div-inside">
|
||||
<van-image
|
||||
radius="1rem"
|
||||
width="4rem"
|
||||
height="4rem"
|
||||
src="https://unpkg.com/@vant/assets/cat.jpeg"
|
||||
/>
|
||||
<br>
|
||||
¥79.0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.out-div {
|
||||
width: 100%;
|
||||
min-height: 10rem;
|
||||
border-radius: 1rem;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.card-div {
|
||||
height: 6rem;
|
||||
width: 100%;
|
||||
}
|
||||
.bottom-div {
|
||||
display: flex;
|
||||
|
||||
/* justify-content: center; */
|
||||
width: 100%;
|
||||
height: 6rem;
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.card-div-inside {
|
||||
flex: none;
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
37
Yi.App.Vue3/src/components/AppCreateTime.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<span class="subtitle">{{ showTime }}</span>
|
||||
</template>
|
||||
<style scoped>
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
const props = defineProps<{ time: string }>();
|
||||
const showTime = computed(() => {
|
||||
var dataTime=new Date(Date.parse(props.time));
|
||||
const hour:number= getHour(dataTime,new Date())
|
||||
if(hour<=0)
|
||||
{
|
||||
return "刚刚"
|
||||
}
|
||||
if(hour<=6)
|
||||
{
|
||||
return hour+"小时前"
|
||||
}
|
||||
return props.time;
|
||||
|
||||
});
|
||||
const getHour=(s1:Date, s2:Date)=> {
|
||||
var ms = s2.getTime() - s1.getTime();
|
||||
if (ms < 0) return 0;
|
||||
return Math.floor(ms / 1000 / 60 / 60); //小时
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.subtitle{
|
||||
color: #CBCBCB;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
34
Yi.App.Vue3/src/components/AppGrid.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<van-row>
|
||||
<van-col span="24">
|
||||
<p > {{data.head}}</p>
|
||||
</van-col>
|
||||
<van-col class="col-body" span="6" v-for="item in data.body"><van-icon :name="item.icon" size="2rem" /> <br>{{item.title}}</van-col>
|
||||
</van-row>
|
||||
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import {AppGridData} from '@/type/class/AppGridData'
|
||||
defineProps<{ data: AppGridData }>()
|
||||
const count = ref(0)
|
||||
</script>
|
||||
<style scoped>
|
||||
.col-body
|
||||
{
|
||||
text-align: center;
|
||||
font-size: small;
|
||||
}
|
||||
.col-body .van-icon
|
||||
{
|
||||
|
||||
color: #FF689B;
|
||||
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
p{
|
||||
font-size: large;
|
||||
font-weight:bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
35
Yi.App.Vue3/src/components/AppUserIcon.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<van-image round :width="width" :height="height" :src="getUrl()" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
src: { type: String, default: "null", required: false },
|
||||
width: { type: String, default: "3rem", required: false },
|
||||
height: { type: String, default: "3rem", required: false },
|
||||
});
|
||||
|
||||
const url = `${import.meta.env.VITE_APP_BASE_API}/file/`;
|
||||
const getUrl = () => {
|
||||
const src = props.src;
|
||||
if (src === null || typeof src === "undefined" || src.trim() === "") {
|
||||
return "/icon.jpg";
|
||||
|
||||
// 字符串为 null、未定义或为空字符串
|
||||
} else {
|
||||
return url + "src";
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.col-body {
|
||||
text-align: center;
|
||||
}
|
||||
.col-body .van-icon {
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
p {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
19
Yi.App.Vue3/src/components/HelloWorld.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
defineProps<{ msg: string }>()
|
||||
|
||||
const count = ref(0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ msg }}</h1>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
76
Yi.App.Vue3/src/layout/bottom/index.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<van-tabbar v-model="active" active-color="#FF689B" inactive-color="#9C9C9C" @change="onChange" z-index="100">
|
||||
<van-tabbar-item v-for="item in tabbar.slice(0,2)" :to="item.to" :icon="item.icon">{{item.title}}</van-tabbar-item>
|
||||
<van-tabbar-item @click="show = true">
|
||||
<template #icon="props">
|
||||
<van-icon class="add" name="add-square" color="#FF689B" size="3rem" />
|
||||
<!-- <img :src="props.active ? icon.active : icon.inactive" /> -->
|
||||
</template>
|
||||
</van-tabbar-item>
|
||||
|
||||
<van-tabbar-item v-for="item in tabbar.slice(3)" :to="item.to" :icon="item.icon">{{item.title}}</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
|
||||
<van-action-sheet v-model:show="show" >
|
||||
|
||||
|
||||
<router-link to="/imageText"> <van-button class="btn1 btn " style="background-color: #5FBC76;" >发图文</van-button></router-link>
|
||||
<van-button class="btn" style="background-color: #FF689B;">(暂未开放)发视频</van-button>
|
||||
<van-button class="btn" style="background-color: #F7A63A;">(暂未开放)发文章</van-button>
|
||||
<van-button class="btn" style="background-color: #6AB5EE;">(暂未开放)发二手</van-button>
|
||||
|
||||
|
||||
|
||||
<van-icon class="icon" name="cross" size="1.5rem" @click="show=false"/>
|
||||
|
||||
|
||||
</van-action-sheet>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
const active = ref(0);
|
||||
const show = ref(false);
|
||||
|
||||
let tabbar=ref([
|
||||
{icon:"wap-home",to:"/",title:"主页"},
|
||||
{icon:"location-o",to:"",title:"发现"},
|
||||
{icon:"",to:"",title:""},
|
||||
{icon:"friends-o",to:"/shopIndex",title:"商城"},
|
||||
// {icon:"friends-o",to:"",title:"商城"},
|
||||
{icon:"setting-o",to:"/my",title:"我的"},
|
||||
])
|
||||
const onChange=(index:number)=>{
|
||||
tabbar.value=[
|
||||
{icon:"wap-home-o",to:"/",title:"主页"},
|
||||
{icon:"location-o",to:"",title:"发现"},
|
||||
{icon:"",to:"",title:""},
|
||||
{icon:"friends-o",to:"/shopIndex",title:"商城"},
|
||||
// {icon:"friends-o",to:"",title:"商城"},
|
||||
{icon:"setting-o",to:"/my",title:"我的"},
|
||||
];
|
||||
tabbar.value[index].icon=tabbar.value[index].icon.replace("-o","")
|
||||
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.btn1
|
||||
{
|
||||
margin-top: 3rem !important;
|
||||
}
|
||||
.btn{
|
||||
border-radius:0.5rem;
|
||||
height: 4rem;
|
||||
width:90%;
|
||||
margin: 0.5rem 1rem 0.5rem 1rem;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.content {
|
||||
padding: 16px 16px 160px;
|
||||
}
|
||||
.icon{
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.add{
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
</style>
|
||||
9
Yi.App.Vue3/src/layout/head/index.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<van-nav-bar
|
||||
title="标题"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
/>
|
||||
<br>
|
||||
<router-view />
|
||||
</template>
|
||||
13
Yi.App.Vue3/src/layout/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import AppBottom from './bottom/index.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
|
||||
<app-bottom/>
|
||||
|
||||
</template>
|
||||
|
||||
12
Yi.App.Vue3/src/layout/main/index.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<app-tab />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import AppTab from '@/layout/tab/index.vue'
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
45
Yi.App.Vue3/src/layout/tab/index.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template >
|
||||
<van-sticky :offset-top="0">
|
||||
<van-row class="row" >
|
||||
<van-col span="4" class="icon"><van-icon name="sign" size="1.6rem"/></van-col>
|
||||
<van-col span="16">
|
||||
<van-tabs v-model:active="active" class="tabs" sticky swipeable color="#FF689B">
|
||||
<van-tab v-for="item in tabs" :title="item.title" :to="item.to" class="tab" :style="{fontSize: 0 + 'px'}" ></van-tab>
|
||||
</van-tabs>
|
||||
</van-col>
|
||||
<van-col span="4" class="icon"><van-icon name="search" size="1.6rem" /></van-col>
|
||||
</van-row>
|
||||
</van-sticky>
|
||||
|
||||
|
||||
<router-view />
|
||||
<div style=""></div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
const active = ref(1);
|
||||
const tabs=ref([
|
||||
{title:"关注",to:"/follow"},
|
||||
{title:"推荐",to:"/recommend"},
|
||||
{title:"广场",to:"/square"},
|
||||
])
|
||||
</script>
|
||||
<style scoped>
|
||||
.row{
|
||||
background-color: #FFFFFF;
|
||||
min-width: 24rem;
|
||||
}
|
||||
.tab{
|
||||
|
||||
}
|
||||
.icon{
|
||||
padding-top: 0.6rem;
|
||||
}
|
||||
.tabs {
|
||||
width: 100%;
|
||||
}
|
||||
.icon .van-icon
|
||||
{
|
||||
color:#FF689B;
|
||||
}
|
||||
</style>
|
||||
17
Yi.App.Vue3/src/main.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import 'vant/es/image-preview/style';
|
||||
import 'vant/es/toast/style';
|
||||
import 'vant/es/dialog/style';
|
||||
import 'vant/es/notify/style';
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import './permission'
|
||||
import { Lazyload } from 'vant';
|
||||
import App from './App.vue'
|
||||
|
||||
const app=createApp(App)
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
app.use(Lazyload);
|
||||
app.mount('#app');
|
||||
52
Yi.App.Vue3/src/permission.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import router from './router'
|
||||
// import { ElMessage } from 'element-plus'
|
||||
// import NProgress from 'nprogress'
|
||||
// import 'nprogress/nprogress.css'
|
||||
import { getToken } from '@/utils/auth'
|
||||
// import { isHttp } from '@/utils/validate'
|
||||
import useUserStore from '@/store/modules/user.js'
|
||||
import { isRelogin } from '@/utils/myaxios'
|
||||
// import useSettingsStore from '@/store/modules/settings'
|
||||
// import usePermissionStore from '@/store/modules/permission'
|
||||
|
||||
// NProgress.configure({ showSpinner: false });
|
||||
|
||||
const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
// NProgress.start()
|
||||
if (getToken()) {
|
||||
// to.meta.title && useSettingsStore().setTitle(to.meta.title)
|
||||
/* has token*/
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
// NProgress.done()
|
||||
} else {
|
||||
if (useUserStore().roles.length === 0) {
|
||||
isRelogin.show = true
|
||||
useUserStore().getInfo().then((response: any) => {
|
||||
next()
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
next()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// 没有token
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
// 在免登录白名单,直接进入
|
||||
next()
|
||||
} else {
|
||||
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
|
||||
// NProgress.done()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
// NProgress.done()
|
||||
})
|
||||
92
Yi.App.Vue3/src/router/index.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { createWebHistory, createRouter } from 'vue-router';
|
||||
import Layout from '@/layout/index.vue';
|
||||
import HeadLayout from '@/layout/head/index.vue'
|
||||
|
||||
export const constantRoutes = [
|
||||
|
||||
{
|
||||
name:'Layout',
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect:"/recommend",
|
||||
children: [
|
||||
{
|
||||
path: '/shopIndex',
|
||||
component: () => import('@/view/shop/shopIndex.vue'),
|
||||
name: 'ShopIndex',
|
||||
},
|
||||
{
|
||||
path: '/my',
|
||||
component: () => import('@/view/my.vue'),
|
||||
name: 'My',
|
||||
},
|
||||
{
|
||||
path: '/main',
|
||||
component: () => import('@/layout/main/index.vue'),
|
||||
name: 'Main',
|
||||
children:[
|
||||
{
|
||||
path: '/recommend',
|
||||
component: () => import('@/view/main/recommend.vue'),
|
||||
name: 'Recommend',
|
||||
},
|
||||
{
|
||||
path: '/follow',
|
||||
component: () => import('@/view/main/follow.vue'),
|
||||
name: 'Follow',
|
||||
},
|
||||
{
|
||||
path: '/square',
|
||||
component: () => import('@/view/main/square.vue'),
|
||||
name: 'Square',
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/imageText',
|
||||
component: () => import('@/view/send/imageText.vue'),
|
||||
name: 'ImageText',
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/view/login.vue'),
|
||||
name: 'Login',
|
||||
},
|
||||
|
||||
{
|
||||
name:'Shop',
|
||||
path: '/shop',
|
||||
component: HeadLayout,
|
||||
redirect:"/shopIndex",
|
||||
children: [
|
||||
{
|
||||
path: '/shopDetails',
|
||||
component: () => import('@/view/shop/shopDetails.vue'),
|
||||
name: 'ShopDetails',
|
||||
},
|
||||
{
|
||||
path: '/shopSearch',
|
||||
component: () => import('@/view/shop/shopSearch.vue'),
|
||||
name: 'ShopSearch',
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: constantRoutes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
return { top: 0 }
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
4
Yi.App.Vue3/src/store/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { createPinia } from 'pinia'
|
||||
const store = createPinia()
|
||||
|
||||
export default store
|
||||
87
Yi.App.Vue3/src/store/modules/user.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { login, logout, getInfo } from '@/api/login'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
// import defAva from '@/assets/images/profile.jpg'
|
||||
import {defineStore} from 'pinia'
|
||||
const useUserStore = defineStore(
|
||||
'user',
|
||||
{
|
||||
state: () => ({
|
||||
token: getToken(),
|
||||
user:{username:"",nick:"",icon:""},
|
||||
roles: [],
|
||||
permissions: []
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
login(userInfo:any ) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
login(username, password, code, uuid).then(res => {
|
||||
if(!(res as any).succeeded)
|
||||
{
|
||||
reject(res)
|
||||
}
|
||||
setToken(res.data.token);
|
||||
this.token = res.data.token;
|
||||
|
||||
return resolve(res);
|
||||
}).catch(error => {
|
||||
return reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取用户信息
|
||||
getInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
getInfo().then(response => {
|
||||
const res=response.data;
|
||||
const user = res.user
|
||||
// const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
|
||||
|
||||
if (res.roleCodes && res.roleCodes.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
this.roles = res.roleCodes
|
||||
this.permissions = res.permissionCodes
|
||||
// this.roles = ["admin"];
|
||||
// this.permissions=["*:*:*"]
|
||||
|
||||
} else {
|
||||
this.roles = ["ROLE_DEFAULT"] as never[]
|
||||
}
|
||||
// this.roles = ["admin"];
|
||||
// this.permissions=["*:*:*"]
|
||||
this.user.username = user.userName;
|
||||
this.user.nick=user.nick
|
||||
this.user.icon = user.icon;
|
||||
resolve(res)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
// 退出系统
|
||||
logOut() {
|
||||
return new Promise((resolve, reject) => {
|
||||
//this.token
|
||||
logout().then((response) => {
|
||||
this.token = ''
|
||||
this.roles = []
|
||||
this.permissions = []
|
||||
removeToken()
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default useUserStore
|
||||
87
Yi.App.Vue3/src/style.css
Normal file
@@ -0,0 +1,87 @@
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0rem;
|
||||
text-align: center;
|
||||
}
|
||||
/* :root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
} */
|
||||
11
Yi.App.Vue3/src/type/class/AppGridData.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export class AppGridData{
|
||||
head!: string;
|
||||
body!: AppGridBody[];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AppGridBody{
|
||||
icon!: string;
|
||||
title!: string;
|
||||
}
|
||||
8
Yi.App.Vue3/src/type/interface/ArticleEntity.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface ArticleEntity{
|
||||
title: string;
|
||||
content: string;
|
||||
images:string[];
|
||||
isDeleted:boolean;
|
||||
creationTime:string;
|
||||
}
|
||||
// import { ArticleEntity } from '@/type/interface/ArticleEntity'
|
||||
13
Yi.App.Vue3/src/utils/auth.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
const TokenKey = 'Admin-Token'
|
||||
|
||||
export function getToken() {
|
||||
return localStorage.getItem(TokenKey)
|
||||
}
|
||||
|
||||
export function setToken(token:string) {
|
||||
return localStorage.setItem(TokenKey, token)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return localStorage.removeItem(TokenKey)
|
||||
}
|
||||
95
Yi.App.Vue3/src/utils/myaxios.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
import axios from 'axios'
|
||||
// import store from '../store/index'
|
||||
// import vm from '../main'
|
||||
import JsonBig from 'json-bigint'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { useRouter } from "vue-router";
|
||||
import useUserStore from '@/store/modules/user.js'
|
||||
import { Notify } from 'vant';
|
||||
// import VuetifyDialogPlugin from 'vuetify-dialog/nuxt/index';
|
||||
export let isRelogin = { show: false };
|
||||
const myaxios = axios.create({
|
||||
// baseURL:'/'//
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API, // /dev-apis
|
||||
timeout: 50000,
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + ""
|
||||
},
|
||||
//雪花id精度问题
|
||||
transformResponse: [data => {
|
||||
const json = JsonBig({
|
||||
storeAsString: true
|
||||
});
|
||||
try {
|
||||
return json.parse(data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return data;
|
||||
}
|
||||
}],
|
||||
})
|
||||
// 请求拦截器
|
||||
myaxios.interceptors.request.use(function (config:any) {
|
||||
const isToken = (config.headers || {}).isToken === false
|
||||
// 是否需要防止数据重复提交
|
||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
|
||||
if (getToken() && !isToken) {
|
||||
config.headers['Authorization'] = 'Bearer ' + getToken()
|
||||
}
|
||||
// store.dispatch("openLoad");
|
||||
return config;
|
||||
}, function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// 响应拦截器
|
||||
myaxios.interceptors.response.use(async function(response) {
|
||||
//成功
|
||||
const resp = response.data
|
||||
if(resp.code==401)
|
||||
{
|
||||
Notify({ type: 'warning', message: '登录过期' });
|
||||
//登出
|
||||
useUserStore().logOut().then(() => {
|
||||
location.href = '/';
|
||||
})
|
||||
isRelogin.show = false;
|
||||
}
|
||||
// store.dispatch("closeLoad");
|
||||
return resp;
|
||||
},
|
||||
async function(error) {
|
||||
const code=error.response.status;
|
||||
const message=error.message;
|
||||
//未授权、失败
|
||||
if(error.response==undefined)
|
||||
{
|
||||
Notify({ type: 'danger', message: `服务器异常:${error.message}` });
|
||||
|
||||
// useUserStore().logOut().then(() => {
|
||||
// location.href = '/';
|
||||
// })
|
||||
|
||||
return Promise.reject(error);;
|
||||
}
|
||||
|
||||
if (code == undefined &&message == undefined) {
|
||||
Notify({ type: 'danger', message: '未知错误' });
|
||||
} else if (code == 401) {
|
||||
// if (!isRelogin.show) {
|
||||
Notify({ type: 'warning', message: '登录过期' });
|
||||
//登出
|
||||
useUserStore().logOut().then(() => {
|
||||
location.href = '/';
|
||||
})
|
||||
isRelogin.show = false;
|
||||
// }
|
||||
} else if (code !== 200) {
|
||||
Notify({ type: 'danger', message: `错误代码:${code},原因:${message}` });
|
||||
}
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default myaxios
|
||||
140
Yi.App.Vue3/src/view/login.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div class="div-top">
|
||||
<span class="title">意框架</span>
|
||||
<br />
|
||||
<span class="subtitle">有幸相遇、不负未来</span>
|
||||
</div>
|
||||
<div class="div-bottom">
|
||||
<h5>密码登录</h5>
|
||||
<van-field
|
||||
class="van-field-username"
|
||||
v-model="loginForm.username"
|
||||
label="用户"
|
||||
placeholder="请输入用户名"
|
||||
/>
|
||||
<van-field
|
||||
class="van-field-password"
|
||||
v-model="loginForm.password"
|
||||
label="密码"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
<van-button type="primary" @click="login">进入意框架</van-button>
|
||||
<p>其他方式登录<van-icon name="arrow" /></p>
|
||||
|
||||
<van-row class="row-bottom" style="margin-top: 6rem">
|
||||
<van-col span="24"><p>第三方登录</p></van-col>
|
||||
<van-col span="2"></van-col>
|
||||
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
|
||||
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
|
||||
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
|
||||
<van-col span="5"><van-icon name="smile-o" size="2rem" /></van-col>
|
||||
<van-col span="2"></van-col>
|
||||
</van-row>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import useUserStore from "@/store/modules/user.js";
|
||||
import { Toast } from "vant";
|
||||
import { debug } from "console";
|
||||
|
||||
const router = useRouter();
|
||||
const redirect = ref(undefined);
|
||||
const loginForm = ref({
|
||||
username: "",
|
||||
password: "",
|
||||
rememberMe: false,
|
||||
code: "",
|
||||
uuid: "",
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
const login = () => {
|
||||
// 调用action的登录方法
|
||||
userStore
|
||||
.login(loginForm.value)
|
||||
.then((response: any) => {
|
||||
Toast({
|
||||
message: "登录成功",
|
||||
position: "bottom",
|
||||
});
|
||||
|
||||
router.push({ path: redirect.value || "/" });
|
||||
})
|
||||
.catch((response:any) => {
|
||||
loginForm.value.password="";
|
||||
Toast({
|
||||
message: response.errors,
|
||||
position: "bottom",
|
||||
});
|
||||
// loading.value = false;
|
||||
// // 重新获取验证码
|
||||
// if (captchaEnabled.value) {
|
||||
// getCode();
|
||||
// }
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.div-top {
|
||||
background-color: #FF689B;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 60%;
|
||||
}
|
||||
.div-bottom {
|
||||
background-color: #FFFFFF;
|
||||
position: absolute;
|
||||
top: 25%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: 3rem 3rem 0rem 0rem;
|
||||
padding: 1rem 2rem 2rem 2rem;
|
||||
|
||||
/* min-height: 70%; */
|
||||
}
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 1.8rem;
|
||||
font-weight: bolder;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.subtitle {
|
||||
transform: translateX(-50%);
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
font-weight: lighter;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.van-field-username {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.van-field-password {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
h5 {
|
||||
text-align: left;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bolder;
|
||||
}
|
||||
.div-bottom .van-button {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
border-radius: 0.4rem;
|
||||
background-color: #FF689B;
|
||||
border: 0;
|
||||
}
|
||||
.div-bottom p {
|
||||
text-align: center;
|
||||
color: #666666;
|
||||
}
|
||||
.row-bottom {
|
||||
color: #FF689B;
|
||||
}
|
||||
</style>
|
||||
16
Yi.App.Vue3/src/view/main/follow.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template >
|
||||
<van-row >
|
||||
<van-col span="24">
|
||||
<div class="test">这里是关注页面</div>
|
||||
</van-col>
|
||||
|
||||
</van-row>
|
||||
|
||||
|
||||
</template>
|
||||
<style scoped>
|
||||
.test
|
||||
{
|
||||
|
||||
}
|
||||
</style>
|
||||
301
Yi.App.Vue3/src/view/main/recommend.vue
Normal file
@@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
<van-list
|
||||
class="list"
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad"
|
||||
>
|
||||
<van-row v-for="(item, index) in articleList" :key="index" class="row">
|
||||
<van-col span="4" class="leftCol">
|
||||
<AppUserIcon
|
||||
width="3rem"
|
||||
height="3rem"
|
||||
:src="item.user == null ? null : item.user.icon"
|
||||
/>
|
||||
</van-col>
|
||||
|
||||
<van-col span="14" class="centerTitle">
|
||||
<span class="justtitle">{{
|
||||
item.user == null ? "-" : item.user.nick ?? item.user.username
|
||||
}}</span>
|
||||
<br />
|
||||
<app-createTime :time="item.creationTime" />
|
||||
</van-col>
|
||||
|
||||
<van-col span="6" class="down">
|
||||
<van-icon name="arrow-down" @click="show = true" />
|
||||
</van-col>
|
||||
|
||||
<van-col class="rowBody" span="24">{{ item.content }}</van-col>
|
||||
|
||||
<van-col
|
||||
span="8"
|
||||
v-for="(image, imageIndex) in item.images"
|
||||
:key="imageIndex"
|
||||
class="imageCol"
|
||||
@click="openImage(item.images, imageIndex)"
|
||||
>
|
||||
<van-image
|
||||
lazy-load
|
||||
fit="cover"
|
||||
width="100%"
|
||||
height="7rem"
|
||||
:src="url + image + '/true'"
|
||||
radius="5"
|
||||
/>
|
||||
<template v-slot:loading>
|
||||
<van-loading type="spinner" size="20" />
|
||||
</template>
|
||||
</van-col>
|
||||
|
||||
<van-col span="24" class="bottomRow">
|
||||
<van-grid direction="horizontal" :column-num="3">
|
||||
<van-grid-item icon="share-o" text="分享" />
|
||||
<van-grid-item
|
||||
icon="comment-o"
|
||||
text="评论"
|
||||
@click="openComment(item.id)"
|
||||
/>
|
||||
<!-- <van-grid-item
|
||||
icon="good-job-o"
|
||||
:text="`点赞:${item.agreeNum}`"
|
||||
@click="aggreeHand(item.id)"
|
||||
/> -->
|
||||
<van-grid-item
|
||||
icon="good-job-o"
|
||||
:text="`点赞:10`"
|
||||
@click="aggreeHand(item.id)"
|
||||
/>
|
||||
</van-grid>
|
||||
</van-col>
|
||||
</van-row>
|
||||
</van-list>
|
||||
</van-pull-refresh>
|
||||
<!-- 功能页面 -->
|
||||
<van-action-sheet
|
||||
v-model:show="show"
|
||||
:actions="actions"
|
||||
cancel-text="取消"
|
||||
close-on-click-action
|
||||
/>
|
||||
|
||||
<!-- 图片预览 -->
|
||||
<van-image-preview
|
||||
v-model:show="imageShow"
|
||||
:images="imagesPreview"
|
||||
:startPosition="startIndex"
|
||||
@change="onChange"
|
||||
:closeable="true"
|
||||
>
|
||||
<template v-slot:index>第{{ index + 1 }}页</template>
|
||||
</van-image-preview>
|
||||
|
||||
<!-- 评论面板 -->
|
||||
<van-action-sheet v-model:show="commentShow" title="共10条评论">
|
||||
<van-row v-for="i in commentList" :key="i" class="commentContent">
|
||||
<van-col span="4">头像</van-col>
|
||||
<van-col span="16">{{ i.content }}</van-col>
|
||||
<van-col span="4">点赞</van-col>
|
||||
</van-row>
|
||||
|
||||
<van-cell-group inset>
|
||||
<van-field v-model="commentData.content" placeholder="请输入评论" >
|
||||
<template #button>
|
||||
<van-button size="small" type="primary" @click="sendComment()">发布</van-button>
|
||||
</template>
|
||||
</van-field>
|
||||
</van-cell-group>
|
||||
</van-action-sheet>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive, toRefs } from "vue";
|
||||
import { ImagePreview, Toast } from "vant";
|
||||
import AppCreateTime from "@/components/AppCreateTime.vue";
|
||||
import AppUserIcon from "@/components/AppUserIcon.vue";
|
||||
import articleApi from "@/api/articleApi";
|
||||
import agreeApi from "@/api/agreeApi";
|
||||
import commentApi from "@/api/commentApi";
|
||||
const VanImagePreview = ImagePreview.Component;
|
||||
const url = `${import.meta.env.VITE_APP_BASE_API}/file/`;
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
// dictName: undefined,
|
||||
// dictType: undefined,
|
||||
isDeleted: false,
|
||||
},
|
||||
});
|
||||
|
||||
const commentData = reactive({
|
||||
content: "",
|
||||
articleId:0
|
||||
});
|
||||
const sendComment=()=>{
|
||||
commentData.articleId=openCommentId.value;
|
||||
commentApi.add(commentData).then(()=>{
|
||||
getCommentList(openCommentId.value);
|
||||
commentData.content="";
|
||||
})
|
||||
}
|
||||
|
||||
const { queryParams } = toRefs(data);
|
||||
const {content}=toRefs(commentData);
|
||||
const articleList = ref<any[]>([]);
|
||||
const commentList = ref<any[]>([]);
|
||||
const totol = ref<Number>(0);
|
||||
const imageShow = ref(false);
|
||||
const commentShow = ref<any>(false);
|
||||
const index = ref(0);
|
||||
let imagesPreview = ref<string[]>([]);
|
||||
const openCommentId=ref(0);
|
||||
const openComment = (id: any) => {
|
||||
commentShow.value = true;
|
||||
openCommentId.value=id;
|
||||
getCommentList(id);
|
||||
};
|
||||
|
||||
const onChange = (newIndex: any) => {
|
||||
index.value = newIndex;
|
||||
};
|
||||
|
||||
const list = ref<Number[]>([]);
|
||||
const loading = ref(false);
|
||||
const finished = ref(false);
|
||||
const refreshing = ref(false);
|
||||
const startIndex = ref(0);
|
||||
const show = ref(false);
|
||||
const actions = [{ name: "取消关注" }, { name: "将TA拉黑" }, { name: "举报" }];
|
||||
|
||||
const onLoad = async () => {
|
||||
if (refreshing.value) {
|
||||
articleList.value = [];
|
||||
refreshing.value = false;
|
||||
}
|
||||
// 异步更新数据
|
||||
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
|
||||
articleApi.pageList(queryParams.value).then((response: any) => {
|
||||
if (response.data.items.length == 0) {
|
||||
console.log("结束");
|
||||
finished.value = true;
|
||||
} else {
|
||||
console.log("执行");
|
||||
articleList.value.push(...response.data.items);
|
||||
totol.value = response.data.totol;
|
||||
queryParams.value.pageNum += 1;
|
||||
}
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
const onRefresh = () => {
|
||||
finished.value = false;
|
||||
|
||||
// 重新加载数据
|
||||
// 将 loading 设置为 true,表示处于加载状态
|
||||
loading.value = true;
|
||||
queryParams.value.pageNum = 1;
|
||||
onLoad();
|
||||
};
|
||||
const openImage = (imagesUrl: string[], imageIndex: any) => {
|
||||
imagesPreview.value = imagesUrl.map((i) => url + i);
|
||||
startIndex.value = imageIndex;
|
||||
imageShow.value = true;
|
||||
};
|
||||
onMounted(() => {
|
||||
articleList.value = [];
|
||||
// getList();
|
||||
});
|
||||
|
||||
const getCommentList = (id: any) => {
|
||||
commentApi.getListByArticleId(id).then((response: any) => {
|
||||
commentList.value = response.data;
|
||||
});
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
articleApi.pageList(queryParams.value).then((response: any) => {
|
||||
articleList.value.push(...response.data.data);
|
||||
totol.value = response.data.totol;
|
||||
});
|
||||
};
|
||||
const aggreeHand = (articleId: any) => {
|
||||
agreeApi.operate(articleId).then((response: any) => {
|
||||
//更改显示的值
|
||||
if (response.status) {
|
||||
articleList.value.filter((p) => p.id == articleId)[0].agreeNum += 1;
|
||||
} else {
|
||||
articleList.value.filter((p) => p.id == articleId)[0].agreeNum -= 1;
|
||||
}
|
||||
Toast({
|
||||
message: response.message,
|
||||
position: "bottom",
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.list {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.row {
|
||||
background-color: white;
|
||||
padding-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.rowBody {
|
||||
text-align: left;
|
||||
background-color: white;
|
||||
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding-top: 1rem;
|
||||
|
||||
min-height: 3rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.leftCol {
|
||||
align-content: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.centerTitle {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.imageCol {
|
||||
padding: 0.1rem 0.1rem 0.1rem 0.1rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #cbcbcb;
|
||||
}
|
||||
|
||||
.justtitle {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.bottomRow {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.down {
|
||||
text-align: right;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.commentContent {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
</style>
|
||||
1
Yi.App.Vue3/src/view/main/square.vue
Normal file
@@ -0,0 +1 @@
|
||||
<template>这里是广场</template>
|
||||
256
Yi.App.Vue3/src/view/my.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<van-row class="headRow">
|
||||
<van-col span="2"><van-icon name="scan" size="1.5rem" /></van-col>
|
||||
<van-col span="20"></van-col>
|
||||
<van-col span="2"
|
||||
><van-icon name="setting-o" size="1.5rem" @click="show = true"
|
||||
/></van-col>
|
||||
</van-row>
|
||||
|
||||
<van-row class="bodyRow">
|
||||
<van-col span="6" class="leftCol">
|
||||
<AppUserIcon width="4rem" height="4rem" :src="user.icon"></AppUserIcon>
|
||||
</van-col>
|
||||
<van-col span="12" class="title"><span>{{user.nick}}</span></van-col>
|
||||
<van-col span="6" class="subtitle"
|
||||
><span>个人主页<van-icon name="arrow" /></span
|
||||
></van-col>
|
||||
|
||||
<van-col span="6" class="bodyCol"
|
||||
><div><span>6</span><br />关注</div></van-col
|
||||
>
|
||||
<van-col span="6" class="bodyCol"
|
||||
><div><span>3</span><br />粉丝</div></van-col
|
||||
>
|
||||
<van-col span="6" class="bodyCol"
|
||||
><div><span>0</span><br />人气</div></van-col
|
||||
>
|
||||
<van-col span="6" class="bodyCol"
|
||||
><div><span>3</span><br />钱钱</div></van-col
|
||||
>
|
||||
|
||||
<van-col span="24">
|
||||
<van-row class="btnRow">
|
||||
<van-col span="12">
|
||||
<van-button class="btn">
|
||||
<van-icon name="bag" size="1.8rem" /> <span>我的购物</span><van-icon
|
||||
name="arrow"
|
||||
size="1.2rem" /></van-button
|
||||
></van-col>
|
||||
|
||||
<van-col span="12">
|
||||
<van-button class="btn"
|
||||
><van-icon name="send-gift" size="1.8rem" /> <span>我的签到</span><van-icon
|
||||
name="arrow"
|
||||
size="1.2rem" /></van-button
|
||||
></van-col>
|
||||
</van-row>
|
||||
</van-col>
|
||||
|
||||
<AppGrid class="grid" :data="data1"></AppGrid>
|
||||
<AppGrid class="grid" :data="data2"></AppGrid>
|
||||
<AppGrid class="grid" :data="data3"></AppGrid>
|
||||
</van-row>
|
||||
|
||||
<van-popup
|
||||
v-model:show="show"
|
||||
position="right"
|
||||
:style="{ height: '100%', width: '100%', backgroundColor: '#F8F8F8' }"
|
||||
>
|
||||
<van-nav-bar
|
||||
title="设置"
|
||||
left-text="返回"
|
||||
left-arrow
|
||||
@click-left="show = false"
|
||||
/>
|
||||
<van-cell-group>
|
||||
<van-cell title="账户与安全" is-link />
|
||||
<van-cell title="黑名单" is-link />
|
||||
<van-cell title="推送设置" is-link />
|
||||
<van-cell title="隐私管理" is-link />
|
||||
<van-cell title="通用设置" is-link />
|
||||
</van-cell-group>
|
||||
<van-cell-group class="group">
|
||||
<van-cell title="家庭入驻" is-link />
|
||||
<van-cell title="社区入驻" is-link />
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group class="group">
|
||||
<van-cell title="清理缓存" is-link />
|
||||
<van-cell title="检测更新" is-link />
|
||||
<van-cell title="关于我们" is-link />
|
||||
<van-cell title="给个好评" is-link />
|
||||
</van-cell-group>
|
||||
|
||||
<van-button type="danger" @click="outLog">退出登录</van-button>
|
||||
</van-popup>
|
||||
<!-- <van-popup v-model:show="show" position="right">
|
||||
<div class="body-div"> 内容</div>
|
||||
</van-popup> -->
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AppGrid from "@/components/AppGrid.vue";
|
||||
import { AppGridData } from "@/type/class/AppGridData";
|
||||
import { ref } from "vue";
|
||||
import { Dialog } from "vant";
|
||||
import useUserStore from "@/store/modules/user.js";
|
||||
import { storeToRefs } from 'pinia';
|
||||
import AppUserIcon from "@/components/AppUserIcon.vue";
|
||||
const show = ref<boolean>(false);
|
||||
let data1: AppGridData = {
|
||||
head: "个人中心",
|
||||
body: [
|
||||
{
|
||||
title: "我的消息",
|
||||
icon: "comment-o",
|
||||
},
|
||||
{
|
||||
title: "我的聊天",
|
||||
icon: "chat-o",
|
||||
},
|
||||
{
|
||||
title: "我的喜欢",
|
||||
icon: "like-o",
|
||||
},
|
||||
{
|
||||
title: "我的关注",
|
||||
icon: "user-o",
|
||||
},
|
||||
],
|
||||
};
|
||||
let data2: AppGridData = {
|
||||
head: "功能",
|
||||
body: [
|
||||
{
|
||||
title: "排行榜",
|
||||
icon: "medal-o",
|
||||
},
|
||||
{
|
||||
title: "活动报名",
|
||||
icon: "balance-list-o",
|
||||
},
|
||||
{
|
||||
title: "钱钱兑换",
|
||||
icon: "gem-o",
|
||||
},
|
||||
{
|
||||
title: "全网上新",
|
||||
icon: "gift-card-o",
|
||||
},
|
||||
],
|
||||
};
|
||||
let data3: AppGridData = {
|
||||
head: "服务",
|
||||
body: [
|
||||
{
|
||||
title: "客服",
|
||||
icon: "service-o",
|
||||
},
|
||||
{
|
||||
title: "小黑屋",
|
||||
icon: "wap-home-o",
|
||||
},
|
||||
{
|
||||
title: "邀请好友",
|
||||
icon: "friends-o",
|
||||
},
|
||||
],
|
||||
};
|
||||
const userStore=useUserStore();
|
||||
const {user}=storeToRefs(useUserStore());
|
||||
const outLog = () => {
|
||||
Dialog.confirm({
|
||||
title: "提示",
|
||||
message: "确定退出当前用户吗?",
|
||||
})
|
||||
.then(() => {
|
||||
userStore
|
||||
.logOut()
|
||||
.then((response: any) => {
|
||||
location.href = "/";
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
// on cancel
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.bodyCol
|
||||
{
|
||||
color: #9B9B9B;
|
||||
}
|
||||
.bodyCol span{
|
||||
color: black;
|
||||
font-size:larger;
|
||||
font-weight: 500;
|
||||
}
|
||||
.btn .van-icon{
|
||||
color: #FF689B;
|
||||
}
|
||||
.btn span{
|
||||
font-size:medium;
|
||||
font-weight:600;
|
||||
}
|
||||
.grid {
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.headRow {
|
||||
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
|
||||
}
|
||||
.bodyRow {
|
||||
text-align: left;
|
||||
margin-top: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.5rem;
|
||||
line-height: 4rem;
|
||||
}
|
||||
.subtitle {
|
||||
line-height: 4rem;
|
||||
color: #9B9B9B;
|
||||
}
|
||||
.bodyCol {
|
||||
text-align: center;
|
||||
font-size: 1.2rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.btn {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #ffffff;
|
||||
border: none;
|
||||
color: black;
|
||||
|
||||
}
|
||||
.btnRow {
|
||||
margin-top: 1.5rem;
|
||||
box-shadow: 0rem 0rem 0.2rem 0.2rem #f3f3f3;
|
||||
}
|
||||
.btnRow .van-button {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.van-icon-send-gift {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.btnRow .van-icon-arrow {
|
||||
margin-left: 0.45rem;
|
||||
}
|
||||
.van-cell {
|
||||
text-align: left;
|
||||
}
|
||||
.group {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.van-popup .van-button {
|
||||
width: 90%;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
</style>
|
||||
185
Yi.App.Vue3/src/view/send/imageText.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<transition name="van-slide-right">
|
||||
<div v-show="visible">
|
||||
<van-sticky>
|
||||
<van-row class="head-row">
|
||||
<van-col span="3">
|
||||
<router-link to="/recommend">
|
||||
<van-icon name="arrow-left" size="1.5rem" />
|
||||
</router-link>
|
||||
</van-col>
|
||||
<van-col span="18"><span>发图文</span></van-col>
|
||||
<van-col
|
||||
span="3"
|
||||
@click="send"
|
||||
:style="{ color: isSend ? '#FE70A0' : '#979797' }"
|
||||
>发布</van-col
|
||||
>
|
||||
</van-row>
|
||||
</van-sticky>
|
||||
|
||||
<van-cell-group>
|
||||
<van-field
|
||||
rows="5"
|
||||
autosize
|
||||
type="textarea"
|
||||
v-model="content"
|
||||
label-width="0"
|
||||
:show-word-limit="true"
|
||||
maxlength="500"
|
||||
placeholder="大于5字,每一天,都是为了下一天"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<van-row class="body-row">
|
||||
<van-col span="10">
|
||||
<van-icon name="share-o" size="1.5rem" /><span>发布到去其他</span>
|
||||
</van-col>
|
||||
<van-col span="4"></van-col>
|
||||
<van-col span="10"
|
||||
><span class="right-span">选择更多人看到</span>
|
||||
<van-icon name="arrow" size="1.2rem" />
|
||||
</van-col>
|
||||
</van-row>
|
||||
|
||||
<van-divider />
|
||||
<van-row>
|
||||
<van-col class="img-col" span="24">
|
||||
<van-uploader
|
||||
accept="image/*"
|
||||
:after-read="afterRead"
|
||||
v-model="fileList"
|
||||
multiple
|
||||
/>
|
||||
</van-col>
|
||||
</van-row>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, reactive, toRefs, watch } from "vue";
|
||||
import { ArticleEntity } from "@/type/interface/ArticleEntity";
|
||||
import fileApi from "@/api/fileApi";
|
||||
import articleApi from "@/api/articleApi";
|
||||
import { Toast } from "vant";
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
const form = reactive<any>({
|
||||
title: "",
|
||||
content: "",
|
||||
images: [],
|
||||
isDeleted: false,
|
||||
});
|
||||
|
||||
const isSend = ref(false);
|
||||
const { images, content } = toRefs(form);
|
||||
const fileList = ref([]);
|
||||
const visible = ref<boolean>(false);
|
||||
onMounted(() => {
|
||||
visible.value = true;
|
||||
});
|
||||
const afterRead = (file: any) => {
|
||||
file.status = "uploading";
|
||||
file.message = "上传中...";
|
||||
var formData = new FormData();
|
||||
//一个文件
|
||||
if (file.length == undefined) {
|
||||
formData.append("file", file.file);
|
||||
} else {
|
||||
//多个文件
|
||||
file.forEach((f: any) => {
|
||||
formData.append("file", f.file);
|
||||
f.status = "uploading";
|
||||
f.message = "上传中...";
|
||||
});
|
||||
Toast({
|
||||
message: "全部文件正在上传",
|
||||
position: "bottom",
|
||||
});
|
||||
}
|
||||
|
||||
fileApi.upload(formData).then((response: any) => {
|
||||
images.value.push(...response.data.map((x:any)=>x.id));
|
||||
|
||||
if (file.length == undefined) {
|
||||
file.status = "done";
|
||||
file.message = "成功";
|
||||
} else {
|
||||
//多个文件
|
||||
file.forEach((f: any) => {
|
||||
f.status = "done";
|
||||
f.message = "成功";
|
||||
});
|
||||
Toast({
|
||||
message: "全部文件上传成功",
|
||||
position: "bottom",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const send = () => {
|
||||
if (form.content.length < 5) {
|
||||
Toast({
|
||||
message: "请输入至少5个字符",
|
||||
position: "bottom",
|
||||
});
|
||||
} else {
|
||||
articleApi.add(form).then((response: any) => {
|
||||
router.push({ path: "/recommend" });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => form.content,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue.length < 5) {
|
||||
isSend.value = false;
|
||||
} else {
|
||||
isSend.value = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped>
|
||||
.head-row {
|
||||
background-color: #f8f8f8;
|
||||
|
||||
padding: 1.2rem 1rem 0.8rem 1rem;
|
||||
}
|
||||
|
||||
.head-row span {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.van-field-5-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.body-row {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.preview-cover {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 4px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.van-uploader {
|
||||
margin: 0 1.2rem 0 1.2rem;
|
||||
}
|
||||
|
||||
.img-col {
|
||||
text-align: left;
|
||||
}
|
||||
.right-span {
|
||||
color: #979797;
|
||||
}
|
||||
</style>
|
||||
44
Yi.App.Vue3/src/view/shop/shopDetails.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
这里是商品详情页,当所有规格组全部选择完后,就会匹配sku列表,匹配成功才显示价格,即绑定好的sku
|
||||
|
||||
<div >商品名称:{{spuItem.spuName}}</div>
|
||||
<div v-for="spec in spuItem.specsSpuAllInfo" :key="spec">规格组: {{spec.specsGroupName}}
|
||||
<div v-for="name in spec.specsNames" :key="name">规格值: {{name}}</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<div v-for="sku in spuItem.skus" :key="sku"> 价格:{{sku.price}}<br>Sku:{{sku}}
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
|
||||
<br>
|
||||
<router-link to="/shopIndex">返回商品首页</router-link>
|
||||
|
||||
<van-action-bar>
|
||||
<van-action-bar-icon icon="chat-o" text="客服" dot />
|
||||
<van-action-bar-icon icon="cart-o" text="购物车" badge="5" />
|
||||
<van-action-bar-icon icon="shop-o" text="店铺" badge="12" />
|
||||
<van-action-bar-button type="warning" text="加入购物车" />
|
||||
<van-action-bar-button type="danger" text="立即购买" />
|
||||
</van-action-bar>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import {ref,onMounted} from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import spuApi from "@/api/spuApi";
|
||||
const router = useRouter();
|
||||
|
||||
const spuItem=ref<any>({});
|
||||
|
||||
onMounted(() => {
|
||||
const spuId=router.currentRoute.value.query.spuId;
|
||||
// 打印
|
||||
spuApi.getById(spuId).then((response:any)=>{
|
||||
spuItem.value=response.data
|
||||
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
</script>>
|
||||
79
Yi.App.Vue3/src/view/shop/shopIndex.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template >
|
||||
<div class="back">
|
||||
|
||||
<van-row class="top-div"> <van-col span="3"><van-icon name="circle" size="2rem" /></van-col>
|
||||
<van-col span="18"> <router-link to="/shopSearch"><van-cell-group inset>
|
||||
<van-field label="搜索" placeholder="搜索" />
|
||||
</van-cell-group> </router-link></van-col>
|
||||
<van-col span="3"><van-icon name="circle" size="2rem" /></van-col></van-row>
|
||||
|
||||
<div class="head-div">
|
||||
<van-swipe
|
||||
height="100"
|
||||
class="my-swipe"
|
||||
:autoplay="3000"
|
||||
indicator-color="white"
|
||||
>
|
||||
<van-swipe-item>1</van-swipe-item>
|
||||
<van-swipe-item>2</van-swipe-item>
|
||||
<van-swipe-item>3</van-swipe-item>
|
||||
<van-swipe-item>4</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
|
||||
<van-row class="body-row">
|
||||
<van-col span="24">
|
||||
<van-grid :column-num="4">
|
||||
<van-grid-item
|
||||
v-for="value in 8"
|
||||
:key="value"
|
||||
icon="photo-o"
|
||||
text="文字"
|
||||
/>
|
||||
</van-grid>
|
||||
</van-col>
|
||||
<van-col span="24"> <AppCard /></van-col>
|
||||
<van-col span="24"> <AppCard /></van-col>
|
||||
<van-col span="24"> <AppCard /></van-col>
|
||||
</van-row>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AppCard from "@/components/AppCard.vue";
|
||||
</script>
|
||||
<style>
|
||||
|
||||
.my-swipe .van-swipe-item {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
line-height: 150px;
|
||||
text-align: center;
|
||||
background-color: #39a9ed;
|
||||
}
|
||||
.body-row {
|
||||
padding: 1rem;
|
||||
padding-top: 0.2rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.van-swipe {
|
||||
/* margin-top: 10rem;
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem; */
|
||||
}
|
||||
.head-div {
|
||||
padding: 1rem;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.body-row .van-col {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.top-div
|
||||
{
|
||||
padding: 1rem;
|
||||
padding-bottom: 0;
|
||||
|
||||
}
|
||||
.back{
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
</style>
|
||||
39
Yi.App.Vue3/src/view/shop/shopSearch.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
这里是商品搜索页
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<router-link to="/shopIndex">返回商品首页</router-link>
|
||||
这个是spu:
|
||||
|
||||
<div v-for="item in spuList" :key="item.id">商品名称:{{item.spuName}}
|
||||
<router-link :to="`/shopDetails?spuId=${item.id}`">点击进入该商品详情</router-link>
|
||||
<div v-for="spec in item.specsSpuAllInfo" :key="spec">规格组: {{spec.specsGroupName}}
|
||||
<div v-for="name in spec.specsNames" :key="name">规格值: {{name}}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref,reactive,toRefs} from 'vue'
|
||||
import spuApi from "@/api/spuApi";
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
// dictName: undefined,
|
||||
// dictType: undefined,
|
||||
isDeleted: false,
|
||||
},
|
||||
});
|
||||
const spuList = ref<any[]>([]);
|
||||
const { queryParams } = toRefs(data);
|
||||
spuApi.pageList(queryParams.value).then((response:any)=>{
|
||||
spuList.value=response.data.data;
|
||||
})
|
||||
</script>
|
||||
7
Yi.App.Vue3/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
24
Yi.App.Vue3/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
// "strictPropertyInitialization": false
|
||||
"paths": {
|
||||
"@": ["./src"],
|
||||
// "@/*": ["./src/*"] // 多加个这个,
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/store/modules/user.ts", "src/utils/myaxios.ts"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
9
Yi.App.Vue3/tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
53
Yi.App.Vue3/vite.config.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import path from 'path'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import { VantResolver } from 'unplugin-vue-components/resolvers';
|
||||
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
const env = loadEnv(mode, process.cwd())
|
||||
const { VITE_APP_ENV, VITE_APP_BASE_URL} = env
|
||||
return {
|
||||
plugins: [vue(), Components({
|
||||
resolvers: [VantResolver()],
|
||||
}),],
|
||||
resolve: {
|
||||
// https://cn.vitejs.dev/config/#resolve-alias
|
||||
alias: {
|
||||
// 设置路径
|
||||
'~': path.resolve(__dirname, './'),
|
||||
// 设置别名
|
||||
// '@': path.resolve(__dirname, './src'),
|
||||
"@": path.join(__dirname, "./src"),
|
||||
}
|
||||
},
|
||||
server: {
|
||||
port: 17000,
|
||||
host: true,
|
||||
open: true,
|
||||
|
||||
|
||||
proxy: {
|
||||
// https://cn.vitejs.dev/config/#server-proxy
|
||||
'/dev-api': {
|
||||
target: VITE_APP_BASE_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(/^\/dev-api/, ''),
|
||||
},
|
||||
|
||||
'/dev-ws': {
|
||||
target: VITE_APP_BASE_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(/^\/dev-ws/, ''),
|
||||
ws: true
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
0
Yi.BBS.Vue3/.env
Normal file
2
Yi.BBS.Vue3/.env.development
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_APP_BASEAPI="/api-dev"
|
||||
VITE_APP_URL="http://localhost:19001/api"
|
||||
1
Yi.BBS.Vue3/.env.production
Normal file
@@ -0,0 +1 @@
|
||||
VITE_APP_BASEAPI="/prod-api"
|
||||
28
Yi.BBS.Vue3/.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
3
Yi.BBS.Vue3/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
||||
29
Yi.BBS.Vue3/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# yi-bbs
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
14
Yi.BBS.Vue3/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>意社区</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
6840
Yi.BBS.Vue3/package-lock.json
generated
Normal file
34
Yi.BBS.Vue3/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "yi-bbs",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"axios": "^1.3.4",
|
||||
"echarts": "^5.4.2",
|
||||
"element-plus": "^2.2.32",
|
||||
"highlight": "^0.2.4",
|
||||
"i": "^0.3.7",
|
||||
"marked": "^4.2.12",
|
||||
"mavon-editor": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.32",
|
||||
"vue": "^3.2.47",
|
||||
"vue-cropper": "1.0.3",
|
||||
"vue-router": "^4.1.6",
|
||||
"yarm": "^0.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"sass": "1.52.1",
|
||||
"unplugin-auto-import": "^0.15.0",
|
||||
"unplugin-vue-components": "^0.24.0",
|
||||
"vite": "^4.1.3"
|
||||
}
|
||||
}
|
||||
BIN
Yi.BBS.Vue3/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 21 KiB |
28
Yi.BBS.Vue3/src/App.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<script setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-config-provider :locale="locale">
|
||||
<RouterView />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
<script setup>
|
||||
import useConfigStore from "@/stores/config";
|
||||
import { ElConfigProvider } from 'element-plus'
|
||||
import {onMounted } from "vue";
|
||||
|
||||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
const locale= zhCn;
|
||||
|
||||
const configStore = useConfigStore();
|
||||
|
||||
//加载全局信息
|
||||
onMounted(async()=>{
|
||||
|
||||
await configStore.getConfig();
|
||||
})
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
17
Yi.BBS.Vue3/src/apis/accessApi.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
// 触发访问
|
||||
export function access() {
|
||||
return request({
|
||||
url: '/access-log',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 获取本周数据
|
||||
export function getWeek() {
|
||||
return request({
|
||||
url: '/access-log/week',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
79
Yi.BBS.Vue3/src/apis/accountApi.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, code, uuid) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid
|
||||
}
|
||||
return request({
|
||||
url: '/account/login',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 注册方法
|
||||
export function register(userName,password,phone,code,uuid) {
|
||||
const data = {
|
||||
userName,
|
||||
password,
|
||||
phone,
|
||||
code,
|
||||
uuid
|
||||
}
|
||||
return request({
|
||||
url: '/account/register',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: '/account',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 退出方法
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/account/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
url: '/account/captcha-image',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
// 获取短信验证码
|
||||
export function getCodePhone(phone) {
|
||||
return request({
|
||||
url: '/account/captcha-phone',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
timeout: 20000,
|
||||
data:{phone}
|
||||
})
|
||||
}
|
||||
11
Yi.BBS.Vue3/src/apis/agreeApi.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function operate(discussId){
|
||||
if(discussId==undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return myaxios({
|
||||
url: `/agree/operate/${discussId}`,
|
||||
method: 'post'
|
||||
})
|
||||
};
|
||||
41
Yi.BBS.Vue3/src/apis/articleApi.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function getList(data){
|
||||
return myaxios({
|
||||
url: '/article',
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
export function get(id){
|
||||
return myaxios({
|
||||
url: `/article/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
};
|
||||
export function add(data){
|
||||
return myaxios({
|
||||
url: `/article`,
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
};
|
||||
export function update(id,data){
|
||||
return myaxios({
|
||||
url: `/article/${id}`,
|
||||
method: 'put',
|
||||
data:data
|
||||
})
|
||||
};
|
||||
export function del(ids){
|
||||
return myaxios({
|
||||
url: `/article/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
};
|
||||
export function all(discussId)
|
||||
{
|
||||
return myaxios({
|
||||
url: `/article/all/discuss-id/${discussId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
8
Yi.BBS.Vue3/src/apis/bannerApi.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function getList(data){
|
||||
return myaxios({
|
||||
url: '/banner',
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
22
Yi.BBS.Vue3/src/apis/commentApi.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function getListByDiscussId(discussId,data){
|
||||
return myaxios({
|
||||
url: `/comment/discuss-id/${discussId}`,
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
export function add(data){
|
||||
return myaxios({
|
||||
url: `/comment`,
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
};
|
||||
|
||||
export function del(ids){
|
||||
return myaxios({
|
||||
url: `/comment/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
};
|
||||
9
Yi.BBS.Vue3/src/apis/configApi.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import myaxios from '@/utils/request'
|
||||
|
||||
//获取配置
|
||||
export function getAll(){
|
||||
return myaxios({
|
||||
url: '/config',
|
||||
method: 'get'
|
||||
})
|
||||
};
|
||||
51
Yi.BBS.Vue3/src/apis/discussApi.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function getList(data){
|
||||
return myaxios({
|
||||
url: '/discuss',
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
export function getTopList(data){
|
||||
|
||||
if(data==undefined)
|
||||
{
|
||||
data={isTop:true}
|
||||
}
|
||||
else
|
||||
{
|
||||
data["isTop"]=true;
|
||||
}
|
||||
|
||||
return myaxios({
|
||||
url: '/discuss',
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
export function get(id){
|
||||
return myaxios({
|
||||
url: `/discuss/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
};
|
||||
export function add(data){
|
||||
return myaxios({
|
||||
url: `/discuss`,
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
};
|
||||
export function update(id,data){
|
||||
return myaxios({
|
||||
url: `/discuss/${id}`,
|
||||
method: 'put',
|
||||
data:data
|
||||
})
|
||||
};
|
||||
export function del(ids){
|
||||
return myaxios({
|
||||
url: `/discuss/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
};
|
||||
9
Yi.BBS.Vue3/src/apis/fileApi.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function upload(data){
|
||||
return myaxios({
|
||||
url: '/file',
|
||||
method: 'post',
|
||||
data:data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
};
|
||||
8
Yi.BBS.Vue3/src/apis/plateApi.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import myaxios from '@/utils/request'
|
||||
export function getList(data){
|
||||
return myaxios({
|
||||
url: '/plate',
|
||||
method: 'get',
|
||||
params:data
|
||||
})
|
||||
};
|
||||
139
Yi.BBS.Vue3/src/apis/userApi.js
Normal file
@@ -0,0 +1,139 @@
|
||||
import myaxios from '@/utils/request'
|
||||
|
||||
// 查询用户列表
|
||||
export function listUser(query) {
|
||||
return myaxios({
|
||||
url: '/user',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询用户详细
|
||||
export function getUser(userId) {
|
||||
return myaxios({
|
||||
url: '/user/' + parseStrEmpty(userId),
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增用户
|
||||
export function addUser(data) {
|
||||
return myaxios({
|
||||
url: '/user',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改用户
|
||||
export function updateUser(id, data) {
|
||||
return myaxios({
|
||||
url: `/user/${id}`,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
export function delUser(userId) {
|
||||
return myaxios({
|
||||
url: `/user/${userId}`,
|
||||
method: 'delete',
|
||||
})
|
||||
}
|
||||
|
||||
// 用户密码重置
|
||||
export function resetUserPwd(id, password) {
|
||||
const data = {
|
||||
password
|
||||
}
|
||||
|
||||
|
||||
return myaxios({
|
||||
url: `/account/rest-password/${id}`,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 用户状态修改
|
||||
export function changeUserStatus(userId, isDel) {
|
||||
return myaxios({
|
||||
url: `/user/${userId}/${isDel}`,
|
||||
method: 'put'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询用户个人信息
|
||||
export function getUserProfile() {
|
||||
return myaxios({
|
||||
url: '/account',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 修改用户个人信息
|
||||
export function updateUserProfile(data) {
|
||||
return myaxios({
|
||||
url: `/user/profile`,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 只修改用户头像
|
||||
export function updateUserIcon(data) {
|
||||
return myaxios({
|
||||
url: `/account/icon`,
|
||||
method: 'put',
|
||||
data:{icon:data}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 用户密码重置
|
||||
export function updateUserPwd(oldPassword, newPassword) {
|
||||
const data = {
|
||||
oldPassword,
|
||||
newPassword
|
||||
}
|
||||
return myaxios({
|
||||
url: '/account/password',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 用户头像上传
|
||||
export function uploadAvatar(data) {
|
||||
return request({
|
||||
url: '/system/user/profile/avatar',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询授权角色
|
||||
export function getAuthRole(userId) {
|
||||
return request({
|
||||
url: '/system/user/authRole/' + userId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存授权角色
|
||||
export function updateAuthRole(data) {
|
||||
return request({
|
||||
url: '/system/user/authRole',
|
||||
method: 'put',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// // 查询部门下拉树结构
|
||||
// export function deptTreeSelect() {
|
||||
// return request({
|
||||
// url: '/system/user/deptTree',
|
||||
// method: 'get'
|
||||
// })
|
||||
// }
|
||||
BIN
Yi.BBS.Vue3/src/assets/401_images/401.gif
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
Yi.BBS.Vue3/src/assets/404_images/404.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
Yi.BBS.Vue3/src/assets/404_images/404_cloud.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
0
Yi.BBS.Vue3/src/assets/base.css
Normal file
710
Yi.BBS.Vue3/src/assets/github-markdown.css
Normal file
@@ -0,0 +1,710 @@
|
||||
@font-face {
|
||||
font-family: octicons-link;
|
||||
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff');
|
||||
}
|
||||
|
||||
.markdown-body {
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
line-height: 1.5;
|
||||
color: #24292e;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.markdown-body .pl-c {
|
||||
color: #6a737d;
|
||||
}
|
||||
|
||||
.markdown-body .pl-c1,
|
||||
.markdown-body .pl-s .pl-v {
|
||||
color: #005cc5;
|
||||
}
|
||||
|
||||
.markdown-body .pl-e,
|
||||
.markdown-body .pl-en {
|
||||
color: #6f42c1;
|
||||
}
|
||||
|
||||
.markdown-body .pl-smi,
|
||||
.markdown-body .pl-s .pl-s1 {
|
||||
color: #24292e;
|
||||
}
|
||||
|
||||
.markdown-body .pl-ent {
|
||||
color: #22863a;
|
||||
}
|
||||
|
||||
.markdown-body .pl-k {
|
||||
color: #d73a49;
|
||||
}
|
||||
|
||||
.markdown-body .pl-s,
|
||||
.markdown-body .pl-pds,
|
||||
.markdown-body .pl-s .pl-pse .pl-s1,
|
||||
.markdown-body .pl-sr,
|
||||
.markdown-body .pl-sr .pl-cce,
|
||||
.markdown-body .pl-sr .pl-sre,
|
||||
.markdown-body .pl-sr .pl-sra {
|
||||
color: #032f62;
|
||||
}
|
||||
|
||||
.markdown-body .pl-v,
|
||||
.markdown-body .pl-smw {
|
||||
color: #e36209;
|
||||
}
|
||||
|
||||
.markdown-body .pl-bu {
|
||||
color: #b31d28;
|
||||
}
|
||||
|
||||
.markdown-body .pl-ii {
|
||||
color: #fafbfc;
|
||||
background-color: #b31d28;
|
||||
}
|
||||
|
||||
.markdown-body .pl-c2 {
|
||||
color: #fafbfc;
|
||||
background-color: #d73a49;
|
||||
}
|
||||
|
||||
.markdown-body .pl-c2::before {
|
||||
content: "^M";
|
||||
}
|
||||
|
||||
.markdown-body .pl-sr .pl-cce {
|
||||
font-weight: bold;
|
||||
color: #22863a;
|
||||
}
|
||||
|
||||
.markdown-body .pl-ml {
|
||||
color: #735c0f;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mh,
|
||||
.markdown-body .pl-mh .pl-en,
|
||||
.markdown-body .pl-ms {
|
||||
font-weight: bold;
|
||||
color: #005cc5;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mi {
|
||||
font-style: italic;
|
||||
color: #24292e;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mb {
|
||||
font-weight: bold;
|
||||
color: #24292e;
|
||||
}
|
||||
|
||||
.markdown-body .pl-md {
|
||||
color: #b31d28;
|
||||
background-color: #ffeef0;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mi1 {
|
||||
color: #22863a;
|
||||
background-color: #f0fff4;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mc {
|
||||
color: #e36209;
|
||||
background-color: #ffebda;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mi2 {
|
||||
color: #f6f8fa;
|
||||
background-color: #005cc5;
|
||||
}
|
||||
|
||||
.markdown-body .pl-mdr {
|
||||
font-weight: bold;
|
||||
color: #6f42c1;
|
||||
}
|
||||
|
||||
.markdown-body .pl-ba {
|
||||
color: #586069;
|
||||
}
|
||||
|
||||
.markdown-body .pl-sg {
|
||||
color: #959da5;
|
||||
}
|
||||
|
||||
.markdown-body .pl-corl {
|
||||
text-decoration: underline;
|
||||
color: #032f62;
|
||||
}
|
||||
|
||||
.markdown-body .octicon {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.markdown-body a {
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
|
||||
.markdown-body a:active,
|
||||
.markdown-body a:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
|
||||
.markdown-body strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.markdown-body strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
.markdown-body img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.markdown-body svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.markdown-body code,
|
||||
.markdown-body kbd,
|
||||
.markdown-body pre {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.markdown-body [type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.markdown-body input {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.markdown-body a {
|
||||
color: #0366d6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown-body a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.markdown-body strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
height: 0;
|
||||
margin: 15px 0;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #dfe2e5;
|
||||
}
|
||||
|
||||
.markdown-body hr::before {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body hr::after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.markdown-body td,
|
||||
.markdown-body th {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body h5 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.markdown-body blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown-body ul,
|
||||
.markdown-body ol {
|
||||
padding-left: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body ol ol,
|
||||
.markdown-body ul ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
.markdown-body ul ul ol,
|
||||
.markdown-body ul ol ol,
|
||||
.markdown-body ol ul ol,
|
||||
.markdown-body ol ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.markdown-body dd {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.markdown-body code {
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown-body .octicon {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.markdown-body .pl-0 {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-1 {
|
||||
padding-left: 4px !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-2 {
|
||||
padding-left: 8px !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-3 {
|
||||
padding-left: 16px !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-4 {
|
||||
padding-left: 24px !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-5 {
|
||||
padding-left: 32px !important;
|
||||
}
|
||||
|
||||
.markdown-body .pl-6 {
|
||||
padding-left: 40px !important;
|
||||
}
|
||||
|
||||
.markdown-body::before {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body::after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.markdown-body>*:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body>*:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body a:not([href]) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown-body .anchor {
|
||||
float: left;
|
||||
padding-right: 4px;
|
||||
margin-left: -20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.markdown-body .anchor:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.markdown-body p,
|
||||
.markdown-body blockquote,
|
||||
.markdown-body ul,
|
||||
.markdown-body ol,
|
||||
.markdown-body dl,
|
||||
.markdown-body table,
|
||||
.markdown-body pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
height: 0.25em;
|
||||
padding: 0;
|
||||
margin: 24px 0;
|
||||
background-color: #e1e4e8;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body blockquote {
|
||||
padding: 0 1em;
|
||||
color: #6a737d;
|
||||
border-left: 0.25em solid #dfe2e5;
|
||||
}
|
||||
|
||||
.markdown-body blockquote>:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown-body blockquote>:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
font-size: 11px;
|
||||
line-height: 10px;
|
||||
color: #444d56;
|
||||
vertical-align: middle;
|
||||
background-color: #fafbfc;
|
||||
border: solid 1px #c6cbd1;
|
||||
border-bottom-color: #959da5;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 -1px 0 #959da5;
|
||||
}
|
||||
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6 {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.markdown-body h1 .octicon-link,
|
||||
.markdown-body h2 .octicon-link,
|
||||
.markdown-body h3 .octicon-link,
|
||||
.markdown-body h4 .octicon-link,
|
||||
.markdown-body h5 .octicon-link,
|
||||
.markdown-body h6 .octicon-link {
|
||||
color: #1b1f23;
|
||||
vertical-align: middle;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .anchor,
|
||||
.markdown-body h2:hover .anchor,
|
||||
.markdown-body h3:hover .anchor,
|
||||
.markdown-body h4:hover .anchor,
|
||||
.markdown-body h5:hover .anchor,
|
||||
.markdown-body h6:hover .anchor {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown-body h1:hover .anchor .octicon-link,
|
||||
.markdown-body h2:hover .anchor .octicon-link,
|
||||
.markdown-body h3:hover .anchor .octicon-link,
|
||||
.markdown-body h4:hover .anchor .octicon-link,
|
||||
.markdown-body h5:hover .anchor .octicon-link,
|
||||
.markdown-body h6:hover .anchor .octicon-link {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.markdown-body h1 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 2em;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
.markdown-body h2 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 1.5em;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.markdown-body h5 {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.markdown-body h6 {
|
||||
font-size: 0.85em;
|
||||
color: #6a737d;
|
||||
}
|
||||
|
||||
.markdown-body ul,
|
||||
.markdown-body ol {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.markdown-body ul ul,
|
||||
.markdown-body ul ol,
|
||||
.markdown-body ol ol,
|
||||
.markdown-body ol ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.markdown-body li>p {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.markdown-body li+li {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
.markdown-body dl {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown-body dl dt {
|
||||
padding: 0;
|
||||
margin-top: 16px;
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body dl dd {
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.markdown-body table th {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown-body table th,
|
||||
.markdown-body table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #dfe2e5;
|
||||
}
|
||||
|
||||
.markdown-body table tr {
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #c6cbd1;
|
||||
}
|
||||
|
||||
.markdown-body table tr:nth-child(2n) {
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
|
||||
.markdown-body img {
|
||||
max-width: 100%;
|
||||
box-sizing: content-box;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.markdown-body img[align=right] {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.markdown-body img[align=left] {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.markdown-body code {
|
||||
padding: 0;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(27,31,35,0.05);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown-body code::before,
|
||||
.markdown-body code::after {
|
||||
letter-spacing: -0.2em;
|
||||
content: "\00a0";
|
||||
}
|
||||
|
||||
.markdown-body pre {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
.markdown-body pre>code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body .highlight {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.markdown-body .highlight pre {
|
||||
margin-bottom: 0;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.markdown-body .highlight pre,
|
||||
.markdown-body pre {
|
||||
padding: 16px;
|
||||
overflow: auto;
|
||||
font-size: 85%;
|
||||
line-height: 1.45;
|
||||
/* background-color: #f6f8fa; */
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown-body pre code {
|
||||
display: inline;
|
||||
max-width: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
line-height: inherit;
|
||||
word-wrap: normal;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.markdown-body pre code::before,
|
||||
.markdown-body pre code::after {
|
||||
content: normal;
|
||||
}
|
||||
|
||||
.markdown-body .full-commit .btn-outline:not(:disabled):hover {
|
||||
color: #005cc5;
|
||||
border-color: #005cc5;
|
||||
}
|
||||
|
||||
.markdown-body kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
line-height: 10px;
|
||||
color: #444d56;
|
||||
vertical-align: middle;
|
||||
background-color: #fafbfc;
|
||||
border: solid 1px #d1d5da;
|
||||
border-bottom-color: #c6cbd1;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 -1px 0 #c6cbd1;
|
||||
}
|
||||
|
||||
.markdown-body :checked+.radio-label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
border-color: #0366d6;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item+.task-list-item {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.markdown-body .task-list-item input {
|
||||
margin: 0 0.2em 0.25em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.markdown-body hr {
|
||||
border-bottom-color: #eee;
|
||||
}
|
||||
|
||||
BIN
Yi.BBS.Vue3/src/assets/login_images/QQ.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
Yi.BBS.Vue3/src/assets/login_images/WeChat.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
Yi.BBS.Vue3/src/assets/login_images/login_bg_phone.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
Yi.BBS.Vue3/src/assets/login_images/login_two.jpg
Normal file
|
After Width: | Height: | Size: 180 KiB |
BIN
Yi.BBS.Vue3/src/assets/logo.ico
Normal file
|
After Width: | Height: | Size: 21 KiB |
48
Yi.BBS.Vue3/src/assets/main.css
Normal file
@@ -0,0 +1,48 @@
|
||||
/* @import './base.css'; */
|
||||
/* #app {
|
||||
margin: 0 auto;
|
||||
font-weight: normal;
|
||||
} */
|
||||
|
||||
body
|
||||
{
|
||||
margin: 0 auto;
|
||||
font-weight: normal;
|
||||
}
|
||||
a{
|
||||
text-decoration: none;
|
||||
}
|
||||
/*
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
} */
|
||||
190
Yi.BBS.Vue3/src/assets/styles/index.scss
Normal file
@@ -0,0 +1,190 @@
|
||||
// @import './variables.module.scss';
|
||||
// @import './mixin.scss';
|
||||
// @import './transition.scss';
|
||||
// @import './element-ui.scss';
|
||||
// @import './sidebar.scss';
|
||||
// @import './btn.scss';
|
||||
// @import './ruoyi.scss';
|
||||
|
||||
// body {
|
||||
// height: 100%;
|
||||
// margin: 0;
|
||||
// -moz-osx-font-smoothing: grayscale;
|
||||
// -webkit-font-smoothing: antialiased;
|
||||
// text-rendering: optimizeLegibility;
|
||||
// font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||
// }
|
||||
|
||||
// label {
|
||||
// font-weight: 700;
|
||||
// }
|
||||
|
||||
// html {
|
||||
// height: 100%;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
|
||||
// #app {
|
||||
// height: 100%;
|
||||
// }
|
||||
|
||||
// *,
|
||||
// *:before,
|
||||
// *:after {
|
||||
// box-sizing: inherit;
|
||||
// }
|
||||
|
||||
// .no-padding {
|
||||
// padding: 0px !important;
|
||||
// }
|
||||
|
||||
// .padding-content {
|
||||
// padding: 4px 0;
|
||||
// }
|
||||
|
||||
// a:focus,
|
||||
// a:active {
|
||||
// outline: none;
|
||||
// }
|
||||
|
||||
// a,
|
||||
// a:focus,
|
||||
// a:hover {
|
||||
// cursor: pointer;
|
||||
// color: inherit;
|
||||
// text-decoration: none;
|
||||
// }
|
||||
|
||||
// div:focus {
|
||||
// outline: none;
|
||||
// }
|
||||
|
||||
// .fr {
|
||||
// float: right;
|
||||
// }
|
||||
|
||||
// .fl {
|
||||
// float: left;
|
||||
// }
|
||||
|
||||
// .pr-5 {
|
||||
// padding-right: 5px;
|
||||
// }
|
||||
|
||||
// .pl-5 {
|
||||
// padding-left: 5px;
|
||||
// }
|
||||
|
||||
// .block {
|
||||
// display: block;
|
||||
// }
|
||||
|
||||
// .pointer {
|
||||
// cursor: pointer;
|
||||
// }
|
||||
|
||||
// .inlineBlock {
|
||||
// display: block;
|
||||
// }
|
||||
|
||||
// .clearfix {
|
||||
// &:after {
|
||||
// visibility: hidden;
|
||||
// display: block;
|
||||
// font-size: 0;
|
||||
// content: " ";
|
||||
// clear: both;
|
||||
// height: 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// aside {
|
||||
// background: #eef1f6;
|
||||
// padding: 8px 24px;
|
||||
// margin-bottom: 20px;
|
||||
// border-radius: 2px;
|
||||
// display: block;
|
||||
// line-height: 32px;
|
||||
// font-size: 16px;
|
||||
// font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
// color: #2c3e50;
|
||||
// -webkit-font-smoothing: antialiased;
|
||||
// -moz-osx-font-smoothing: grayscale;
|
||||
|
||||
// a {
|
||||
// color: #337ab7;
|
||||
// cursor: pointer;
|
||||
|
||||
// &:hover {
|
||||
// color: rgb(32, 160, 255);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// .components-container {
|
||||
// margin: 30px 50px;
|
||||
// position: relative;
|
||||
// }
|
||||
|
||||
// .pagination-container {
|
||||
// margin-top: 30px;
|
||||
// }
|
||||
|
||||
.text-center {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
// .sub-navbar {
|
||||
// height: 50px;
|
||||
// line-height: 50px;
|
||||
// position: relative;
|
||||
// width: 100%;
|
||||
// text-align: right;
|
||||
// padding-right: 20px;
|
||||
// transition: 600ms ease position;
|
||||
// background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
||||
|
||||
// .subtitle {
|
||||
// font-size: 20px;
|
||||
// color: #fff;
|
||||
// }
|
||||
|
||||
// &.draft {
|
||||
// background: #d0d0d0;
|
||||
// }
|
||||
|
||||
// &.deleted {
|
||||
// background: #d0d0d0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .link-type,
|
||||
// .link-type:focus {
|
||||
// color: #337ab7;
|
||||
// cursor: pointer;
|
||||
|
||||
// &:hover {
|
||||
// color: rgb(32, 160, 255);
|
||||
// }
|
||||
// }
|
||||
|
||||
// .filter-container {
|
||||
// padding-bottom: 10px;
|
||||
|
||||
// .filter-item {
|
||||
// display: inline-block;
|
||||
// vertical-align: middle;
|
||||
// margin-bottom: 10px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //refine vue-multiselect plugin
|
||||
// .multiselect {
|
||||
// line-height: 16px;
|
||||
// }
|
||||
|
||||
// .multiselect--active {
|
||||
// z-index: 1000 !important;
|
||||
// }
|
||||
206
Yi.BBS.Vue3/src/assets/styles/login.scss
Normal file
@@ -0,0 +1,206 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
/*公共CSS*/
|
||||
.box {
|
||||
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgb(29, 67, 89);
|
||||
.content {
|
||||
box-shadow: 0px 1px 6px #3B4859;
|
||||
.login-wrapper {
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
.login-form {
|
||||
.form-item {
|
||||
margin: 20px 0;
|
||||
span {
|
||||
display: block;
|
||||
margin: 5px 20px;
|
||||
font-weight: 100;
|
||||
}
|
||||
.input-item {
|
||||
width: 100%;
|
||||
border-radius: 40px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
font-size: 20px;
|
||||
font-weight: 200;
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
border-radius: 40px;
|
||||
color: #fff;
|
||||
border: 0;
|
||||
font-weight: 100;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
width: 100%;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
span:nth-child(1) {
|
||||
flex: 1;
|
||||
}
|
||||
span:nth-child(3) {
|
||||
flex: 1;
|
||||
}
|
||||
.line {
|
||||
display: inline-block;
|
||||
max-width: 30%;
|
||||
width: 30%;
|
||||
}
|
||||
.divider-text {
|
||||
vertical-align: middle;
|
||||
margin: 0px 20px;
|
||||
line-height: 0px;
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
.other-login-wrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.other-login-item {
|
||||
border: 1px solid rgb(214, 222, 228);
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*一般大于手机的尺寸CSS*/
|
||||
@media (min-width: 767px) {
|
||||
.box {
|
||||
background-color: #F0F2F5;
|
||||
.content {
|
||||
width: 85vw;
|
||||
height: 90vh;
|
||||
background: url("@/assets/login_images/login_two.jpg") no-repeat;
|
||||
background-size: 90% 100%;
|
||||
position: absolute;
|
||||
right: 15%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 20px;
|
||||
background-color: #fff;
|
||||
.login-wrapper {
|
||||
width: 25vw;
|
||||
position: absolute;
|
||||
right: 15%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 45px;
|
||||
color: rgb(81, 100, 115);
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.login-form {
|
||||
margin: 10px 0;
|
||||
.form-item {
|
||||
span {
|
||||
color: rgb(81, 100, 115);
|
||||
}
|
||||
.input-item {
|
||||
height: 60px;
|
||||
border: 1px solid rgb(214, 222, 228);
|
||||
}
|
||||
}
|
||||
.login-btn {
|
||||
height: 50px;
|
||||
background-color: rgb(59, 72, 89);
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
.line {
|
||||
border-bottom: 1px solid rgb(214, 222, 228);
|
||||
}
|
||||
}
|
||||
.other-login-item {
|
||||
border-radius: 20px;
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*手机端CSS*/
|
||||
@media (max-width: 768px) {
|
||||
.box {
|
||||
.content {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: url("@/assets/login_images/login_bg_phone.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
.login-wrapper {
|
||||
width: 70%;
|
||||
height: 60%;
|
||||
padding-top: 15%;
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
.login-form {
|
||||
.form-item {
|
||||
margin: 10px 0;
|
||||
span {
|
||||
color: rgb(113, 129, 141);
|
||||
}
|
||||
.input-item {
|
||||
height: 30px;
|
||||
border: 1px solid rgb(113, 129, 141);
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.login-btn {
|
||||
height: 40px;
|
||||
background-color: rgb(235, 95, 93);
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
.line {
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
.divider-text {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.other-login-item {
|
||||
border-radius: 15px;
|
||||
img {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
271
Yi.BBS.Vue3/src/assets/styles/ruoyi.scss
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* 通用css样式布局处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
/** 基础通用 **/
|
||||
.pt5 {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.el-dialog:not(.is-fullscreen) {
|
||||
margin-top: 6vh !important;
|
||||
}
|
||||
|
||||
.el-dialog.scrollbar .el-dialog__body {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 10px 20px 0;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9 !important;
|
||||
color: #515a6e;
|
||||
height: 40px !important;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*="el-icon-"] + span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 表单布局 **/
|
||||
.form-header {
|
||||
font-size:15px;
|
||||
color:#6379bb;
|
||||
border-bottom:1px solid #ddd;
|
||||
margin:8px 10px 25px 10px;
|
||||
padding-bottom:5px
|
||||
}
|
||||
|
||||
/** 表格布局 **/
|
||||
.pagination-container {
|
||||
// position: relative;
|
||||
height: 25px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px !important;
|
||||
}
|
||||
|
||||
/* tree border */
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border-radius:4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media ( max-width : 768px) {
|
||||
.pagination-container .el-pagination > .el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table .fixed-width .el-button--small {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
/** 表格更多操作下拉样式 */
|
||||
.el-table .el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-tree-node__content > .el-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.list-group-striped > .list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
|
||||
// .el-card__header {
|
||||
// padding: 14px 15px 7px !important;
|
||||
// min-height: 40px;
|
||||
// }
|
||||
|
||||
// .el-card__body {
|
||||
// padding: 15px 20px 20px 20px !important;
|
||||
// }
|
||||
|
||||
.card-box {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1c84c6;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #23c6c8;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #f8ac59;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #ed5565;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
/* image */
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 拖拽列样式 */
|
||||
.sortable-ghost{
|
||||
opacity: .8;
|
||||
color: #fff!important;
|
||||
background: #42b983!important;
|
||||
}
|
||||
|
||||
/* 表格右侧工具栏样式 */
|
||||
.top-right-btn {
|
||||
margin-left: auto;
|
||||
}
|
||||
55
Yi.BBS.Vue3/src/components/AgreeInfo.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-button text @click="agree">
|
||||
<el-icon v-if="data.isAgree" color="#409EFF">
|
||||
<CircleCheckFilled />
|
||||
</el-icon>
|
||||
<el-icon v-else color="#1E1E1E">
|
||||
<Pointer />
|
||||
</el-icon> 点赞:{{ data.agreeNum ?? 0 }}</el-button>
|
||||
</template>
|
||||
<script setup>
|
||||
import {onMounted,reactive,watch} from 'vue'
|
||||
import { operate } from '@/apis/agreeApi'
|
||||
|
||||
|
||||
//'isAgree','agreeNum','id'
|
||||
const props = defineProps([ 'data'])
|
||||
|
||||
watch(()=>props,(n)=>{
|
||||
data.id=n.data.id;
|
||||
data.isAgree=n.data.isAgree;
|
||||
data.agreeNum=n.data.agreeNum;
|
||||
},{deep:true})
|
||||
|
||||
|
||||
const data=reactive({
|
||||
id:'',
|
||||
isAgree:false,
|
||||
agreeNum:0
|
||||
})
|
||||
// onMounted(()=>{
|
||||
|
||||
// })
|
||||
//点赞操作
|
||||
const agree = async () => {
|
||||
const response = await operate(data.id)
|
||||
const res = response.data;
|
||||
//提示框,颜色区分
|
||||
if (res.isAgree) {
|
||||
data.isAgree = true;
|
||||
data.agreeNum += 1;
|
||||
ElMessage({
|
||||
message: res.message,
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
else {
|
||||
data.isAgree = false;
|
||||
data.agreeNum-= 1;
|
||||
ElMessage({
|
||||
message: res.message,
|
||||
type: 'warning',
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
43
Yi.BBS.Vue3/src/components/ArticleContentInfo.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="markdown-body" v-html="outputHtml"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { marked } from 'marked';
|
||||
|
||||
import hljs from "highlight.js";
|
||||
//可以设置加载样式切换主题
|
||||
import 'highlight.js/styles/atom-one-dark.css'
|
||||
import '@/assets/github-markdown.css'
|
||||
import { ref,watch } from 'vue';
|
||||
|
||||
|
||||
|
||||
const outputHtml=ref("")
|
||||
const props = defineProps(['code'])
|
||||
watch(props,(n,o)=>{
|
||||
marked.setOptions({
|
||||
renderer: new marked.Renderer(),
|
||||
highlight: function(code) {
|
||||
return hljs.highlightAuto(code).value;
|
||||
},
|
||||
pedantic: false,
|
||||
gfm: true,//允许 Git Hub标准的markdown
|
||||
tables: true,//支持表格
|
||||
|
||||
breaks: true,
|
||||
sanitize: false,
|
||||
smartLists: true,
|
||||
smartypants: false,
|
||||
xhtml: false,
|
||||
smartLists: true,
|
||||
}
|
||||
);
|
||||
//需要注意代码块样式
|
||||
outputHtml.value = marked(n.code).replace(/<pre>/g, "<pre class='hljs'>")
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
131
Yi.BBS.Vue3/src/components/AvatarInfo.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template >
|
||||
<div class="avatar">
|
||||
<div class="avatar-left">
|
||||
<el-avatar :size="props.size" :src="iconUrl" />
|
||||
|
||||
<div v-if="props.isSelf">
|
||||
<div class="nick"> {{ userInfo.nick }}</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!props.isSelf">
|
||||
|
||||
<div class="nick" :class="{ mt_1: props.time != 'undefined' }"> {{ userInfo.nick }}</div>
|
||||
<div class="remarks" v-if="props.time"> {{ props.time }}</div>
|
||||
<div class="remarks">
|
||||
<slot name="bottom" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="info" v-if="!props.isSelf">
|
||||
<el-tag class="ml-2" type="warning">V8</el-tag>
|
||||
<el-tag class="ml-2" type="danger">会员</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<el-button v-if="props.showWatching" type="primary" size="default" icon="Plus">关注</el-button>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import useUserStore from '@/stores/user'
|
||||
import { reactive, watch, onMounted, computed, ref } from 'vue';
|
||||
//userInfo
|
||||
//{icon,name,role,id},根据判断userInfo是否等于未定义,来觉得是当前登录用户信息,还是其他人信息
|
||||
const props = defineProps(['size', 'showWatching', 'time', 'userInfo', 'isSelf'])
|
||||
const userStore = useUserStore();
|
||||
const userInfo = reactive({
|
||||
icon: "",
|
||||
nick: "",
|
||||
role: [],
|
||||
id: ""
|
||||
});
|
||||
const iconUrl=ref('/src/assets/logo.ico');
|
||||
const iconUrlHandler = () => {
|
||||
if (userInfo.icon == null || userInfo.icon == undefined || userInfo.icon == '') {
|
||||
|
||||
return '/src/assets/logo.ico';
|
||||
}
|
||||
return `${import.meta.env.VITE_APP_BASEAPI}/file/${userInfo.icon}`;
|
||||
}
|
||||
|
||||
watch(userStore, (n) => {
|
||||
if (props.userInfo == undefined) {
|
||||
userInfo.nick = n.name;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
watch(() => props, (n) => {
|
||||
Init();
|
||||
}, { deep: true })
|
||||
|
||||
onMounted(() => {
|
||||
Init();
|
||||
})
|
||||
|
||||
const Init = () => {
|
||||
//使用传入值
|
||||
if (props.userInfo != undefined) {
|
||||
userInfo.icon = props.userInfo.icon;
|
||||
userInfo.nick = props.userInfo.nick;
|
||||
userInfo.role = props.userInfo.role;
|
||||
userInfo.id = props.userInfo.id;
|
||||
iconUrl.value=iconUrlHandler(userInfo.icon)
|
||||
}
|
||||
|
||||
//使用当前登录用户
|
||||
else {
|
||||
|
||||
userInfo.icon = userStore.icon;
|
||||
userInfo.nick = userStore.name;
|
||||
userInfo.role = userStore.role;
|
||||
userInfo.id = userStore.id;
|
||||
iconUrl.value=userInfo.icon;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.mt_1 {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.nick {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-top: 0.6rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.info .el-tag {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
color: white;
|
||||
|
||||
}
|
||||
|
||||
.avatar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.avatar-left {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.el-avatar {
|
||||
margin-right: 1.2rem;
|
||||
}
|
||||
|
||||
.remarks {
|
||||
padding-top: 0.5rem;
|
||||
color: #8C8C8C;
|
||||
}
|
||||
</style>
|
||||
38
Yi.BBS.Vue3/src/components/BottomInfo.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="botton-div">
|
||||
<a><el-icon><UserFilled /></el-icon>站长:{{configStore.author}}</a>
|
||||
<a><el-icon><Search /></el-icon>{{configStore.bottom}}</a>
|
||||
<a><el-icon><View /></el-icon>关于本站</a>
|
||||
<a><el-icon><Message /></el-icon>建议反馈</a>
|
||||
<p></p>
|
||||
<a ><el-icon><Position /></el-icon>{{configStore.icp}}</a>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import useConfigStore from "@/stores/config";
|
||||
const configStore= useConfigStore();
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-icon
|
||||
{margin: 0 0.2rem;}
|
||||
a{
|
||||
margin-right: 2rem;
|
||||
line-height: 1.8rem;
|
||||
}
|
||||
a:hover {
|
||||
color: #40a9ff;
|
||||
cursor:pointer;
|
||||
}
|
||||
.botton-div
|
||||
{
|
||||
background: transparent;
|
||||
color: rgba(0,0,0,.45);
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
height: auto;
|
||||
width: auto;
|
||||
justify-content: center;
|
||||
margin: 0.5rem auto;
|
||||
}
|
||||
</style>
|
||||
204
Yi.BBS.Vue3/src/components/CommentInfo.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="评论" name="comment"></el-tab-pane>
|
||||
<el-tab-pane label="相关内容" name="interrelated"></el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<div class="total">
|
||||
<div style="align-self: center;"> 共{{total}}个评论</div>
|
||||
<div> <el-radio-group v-model="selectRadio">
|
||||
<el-radio-button label="new" name="new">最新</el-radio-button>
|
||||
<el-radio-button label="host" name="host">最热</el-radio-button>
|
||||
</el-radio-group></div>
|
||||
</div>
|
||||
|
||||
|
||||
<el-divider />
|
||||
<div v-hasPer="['bbs:comment:add']">
|
||||
<el-input v-model="topContent" placeholder="发表一个友善的评论吧~" :rows="5" type="textarea"></el-input>
|
||||
<el-button @click="addTopComment" type="primary" class="btn-top-comment" >发表评论</el-button>
|
||||
<el-button class="btn-top-comment">其他</el-button>
|
||||
|
||||
<el-divider />
|
||||
</div>
|
||||
|
||||
<!-- 开始评论主体 -->
|
||||
|
||||
<div v-for="item in commentList" :key="item.id" class="comment1">
|
||||
<AvatarInfo :userInfo="item.createUser" />
|
||||
<div class="content">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
<span class="time"> {{ item.creationTime }} </span>
|
||||
<span class="pointer"><el-icon>
|
||||
<Pointer />
|
||||
</el-icon> 0</span>
|
||||
<el-button type="primary" @click="replay(item.createUser.nick, item.id, item.id)" size="large" text v-hasPer="['bbs:comment:add']">回复</el-button>
|
||||
<el-button type="danger" @click="delComment(item.id)" size="large" text v-hasPer="['bbs:comment:remove']">删除</el-button>
|
||||
<div v-show="replayId == item.id" class="input-reply">
|
||||
<el-input v-model="form.content" :placeholder="placeholder" :rows="3" type="textarea"></el-input>
|
||||
<div class="btn-reply">
|
||||
<el-button @click="addComment" type="primary" v-hasPer="['bbs:comment:add']">回复</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 开始子评论主体 -->
|
||||
<div v-for="children in item.children" :key="children.id" class="comment2">
|
||||
|
||||
<div style="display: flex ;">
|
||||
<AvatarInfo :userInfo="children.createUser" />
|
||||
<span style="align-self: center;color:#606266;"> 回复@{{ children.commentedUser.nick }}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
{{ children.content }}
|
||||
</div>
|
||||
<span class="time">{{ children.creationTime }} </span>
|
||||
<span class="pointer"> <el-icon>
|
||||
<Pointer />
|
||||
</el-icon>0</span>
|
||||
<el-button type="primary" @click="replay(children.createUser.nick, children.id, item.id)" size="large" text v-hasPer="['bbs:comment:add']">回复</el-button>
|
||||
<el-button type="danger" @click="delComment(children.id)" size="large" text v-hasPer="['bbs:comment:remove']">删除</el-button>
|
||||
<div v-show="replayId == children.id" class="input-reply">
|
||||
<el-input v-model="form.content" :placeholder="placeholder" :rows="3" type="textarea"></el-input>
|
||||
<div class="btn-reply">
|
||||
<el-button @click="addComment" type="primary" v-hasPer="['bbs:comment:add']">回复</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<el-divider />
|
||||
|
||||
</div>
|
||||
<el-empty v-show="commentList.length<=0" description="评论空空如也,快来抢占沙发~" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { getListByDiscussId, add ,del} from "@/apis/commentApi.js";
|
||||
import AvatarInfo from './AvatarInfo.vue';
|
||||
//数据定义
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const commentList = ref([]);
|
||||
const query = reactive({});
|
||||
const topContent=ref('');
|
||||
//当前回复id
|
||||
const replayId = ref('');
|
||||
//回复文本框
|
||||
const placeholder = ref('')
|
||||
|
||||
//选择类型:评论
|
||||
const activeName = ref('comment');
|
||||
//选择 最新
|
||||
const selectRadio = ref('new');
|
||||
//评论总数
|
||||
const total=ref(0);
|
||||
const form = reactive({
|
||||
content: "",
|
||||
discussId: route.params.discussId,
|
||||
query,
|
||||
parentId: 0,
|
||||
rootId: 0,
|
||||
});
|
||||
onMounted(async () => {
|
||||
await loadComment();
|
||||
});
|
||||
const loadComment = async () => {
|
||||
topContent.value='';
|
||||
form.content = '';
|
||||
const response = await getListByDiscussId(route.params.discussId, query);
|
||||
commentList.value = response.data.items;
|
||||
total.value=response.data.total
|
||||
};
|
||||
const addTopComment = async () => {
|
||||
form.parentId = 0;
|
||||
form.rootId = 0;
|
||||
form.content=topContent.value;
|
||||
await addComment();
|
||||
}
|
||||
const addComment = async () => {
|
||||
if(form.content.length<=0)
|
||||
{
|
||||
ElMessage.error('输入评论不能为空!')
|
||||
return
|
||||
}
|
||||
await add(form);
|
||||
await loadComment();
|
||||
ElMessage({
|
||||
message: '评论发表成功!',
|
||||
type: 'success',
|
||||
})
|
||||
};
|
||||
const delComment=async(ids)=>{
|
||||
ElMessageBox.confirm(`确定是否删除编号[${ids}]的评论吗?`, "警告", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
|
||||
await del(ids);
|
||||
await loadComment();
|
||||
ElMessage({
|
||||
message: '评论已删除!',
|
||||
type: 'success',
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
const replay = async (parentUserName, parentId, rootId) => {
|
||||
replayId.value = parentId;
|
||||
form.parentId = parentId;
|
||||
form.rootId = rootId;
|
||||
placeholder.value = `回复@${parentUserName}`;
|
||||
}
|
||||
|
||||
//切换 评论、相关内容
|
||||
const handleClick = () => { }
|
||||
</script>
|
||||
<style scoped>
|
||||
.input-reply {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.btn-reply {
|
||||
margin: 1rem 0;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.comment1 .pointer {
|
||||
margin: 0 0 0 1rem;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #8C8C8C;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.total {
|
||||
display: flex;
|
||||
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
.comment2 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.btn-top-comment {
|
||||
margin-top: 0.5rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
</style>
|
||||