Compare commits
566 Commits
Author | SHA1 | Date |
---|---|---|
|
e4b2f70ae3 | |
|
41b0dce852 | |
|
188470bc1d | |
|
92e3aa4c35 | |
|
5e136d1815 | |
|
7506665052 | |
|
fc2f0e84b2 | |
|
6ba2ef3a96 | |
|
2674c6278d | |
|
6e881fbff4 | |
|
135f0615f5 | |
|
a53c0cd791 | |
|
71d5ff0a24 | |
|
acf4ed75dc | |
|
b6ddd637db | |
|
383bec6e20 | |
|
3f0839b12c | |
|
3c99d1e76a | |
|
195802e87f | |
|
063390e255 | |
|
a987e8eda3 | |
|
919f543cbd | |
|
617c72771d | |
|
82cc6befaa | |
|
4035c96c83 | |
|
7465b7f890 | |
|
5c7b29ee04 | |
|
a946424275 | |
|
8de82f119f | |
|
979361b20c | |
|
540694a4e1 | |
|
8b8d8d5111 | |
|
58c4d6d5b2 | |
|
889f03189d | |
|
7eb06c1df6 | |
|
a549d87acd | |
|
88268b450b | |
|
51ff64fb2a | |
|
25197d9cb3 | |
|
3280d00472 | |
|
5dc6bc066a | |
|
d09be53f2b | |
|
b25d6df9a7 | |
|
0df75c019f | |
|
2fb1e406d6 | |
|
1de338c6b7 | |
|
8c102946d7 | |
|
331f034d9b | |
|
10e5b1d26c | |
|
1a896cf994 | |
|
2107b70d94 | |
|
f4490c3395 | |
|
50bc67c5d8 | |
|
97836b447f | |
|
9d2c3dfdac | |
|
1ff9891331 | |
|
25fae681ae | |
|
e14b053c72 | |
|
24fe9e7d35 | |
|
ebf60eabf7 | |
|
b4aea5974c | |
|
65756b458c | |
|
8536fadf2c | |
|
f0a3c85f43 | |
|
3898d0c7d5 | |
|
434e7ab82b | |
|
0d609c41b0 | |
|
d7b7bef4c2 | |
|
49ca3503eb | |
|
41e94ca677 | |
|
7411047ea3 | |
|
71956f9a36 | |
|
43fe7cf209 | |
|
d6d5ec0ee8 | |
|
32bad4adcb | |
|
1bf2e4141c | |
|
e6d5cacefa | |
|
f68ec04269 | |
|
18ace08ea9 | |
|
658d616cfb | |
|
a602539ec5 | |
|
08b02e9579 | |
|
3e5de3e936 | |
|
f0e3e60514 | |
|
4182d86fd4 | |
|
36aa19dd6e | |
|
f18229d58c | |
|
d77d4786aa | |
|
503c1a4a2b | |
|
554614aa4a | |
|
84e4c68413 | |
|
3a0525f11f | |
|
cacea459c1 | |
|
267d0e68bd | |
|
05f0d1d344 | |
|
6840c1d851 | |
|
35ed1f654f | |
|
6657c29c79 | |
|
f12b2d254a | |
|
18cbde111b | |
|
e484961576 | |
|
df6098f1dc | |
|
7fd4a83b52 | |
|
2892a2780f | |
|
2a7c42071a | |
|
b04d45b624 | |
|
09146b9acf | |
|
f5bc782097 | |
|
23e43ff248 | |
|
95bec59886 | |
|
4d98083434 | |
|
9f3777209c | |
|
b8078fd505 | |
|
d0860e57a5 | |
|
22f5907bc4 | |
|
c19cd5ca85 | |
|
943c620c55 | |
|
b6cd8ddcdd | |
|
d60bdd3bc8 | |
|
b391d109cd | |
|
5aab0908c4 | |
|
aa11b1fa96 | |
|
53a8eb614f | |
|
0e64331bc3 | |
|
8ec06d9199 | |
|
e7b8a9ef51 | |
|
7e66b50b79 | |
|
61ac109d2e | |
|
eb67bbf26e | |
|
66f803c73b | |
|
a4599b835e | |
|
fb0d42b02e | |
|
5bdb883947 | |
|
cdeee4b3b2 | |
|
2a52d139a6 | |
|
74cf29ad13 | |
|
86640d3b64 | |
|
fcaa0244c2 | |
|
7b2b7490fa | |
|
16ed058850 | |
|
926cd75cf6 | |
|
7c2935bb1b | |
|
8b280cef15 | |
|
d683f392f2 | |
|
4695b8e17e | |
|
01c2857be6 | |
|
5bd40bd487 | |
|
0df8267cb2 | |
|
1317b2828f | |
|
663580b8ae | |
|
92f615c730 | |
|
e79b2d3007 | |
|
e148aa5c57 | |
|
57537d50d3 | |
|
e25fecb164 | |
|
5096910ba3 | |
|
eb3ce91948 | |
|
cf164c57c7 | |
|
81ce2b70e0 | |
|
bb6aa0723e | |
|
76fe5d7fcd | |
|
f712b0ab0e | |
|
b281d05c5d | |
|
bbf51ea3f4 | |
|
70e42a8268 | |
|
9720ae85ef | |
|
78078e6d6f | |
|
614d3d6b43 | |
|
19a2123cee | |
|
11984e20e7 | |
|
c00895a848 | |
|
fae54caea1 | |
|
b19a9cb955 | |
|
78ab4ad0d0 | |
|
4436a74b60 | |
|
5ee01d88be | |
|
57f78cc7f5 | |
|
d46602b4f7 | |
|
87438838b5 | |
|
97eeba961a | |
|
88fbd32ee8 | |
|
d381ef1e51 | |
|
b32e28ca2c | |
|
15007cd2fc | |
|
913f4db051 | |
|
06b3368a9f | |
|
bdae9766dc | |
|
0d0443fddb | |
|
e1a6e7379d | |
|
18bf30fe83 | |
|
c28ef26e8e | |
|
808dc444b1 | |
|
4cb59e5d03 | |
|
f9e4efd84e | |
|
4e3f7cfab1 | |
|
f8870109c3 | |
|
e0fd45f15a | |
|
f5f0a7b735 | |
|
a7fe25c67d | |
|
0323b5ca3b | |
|
ecff092ea4 | |
|
09de55a641 | |
|
7ce614554f | |
|
0e81c0e257 | |
|
3ebfe8cd56 | |
|
23dd2d05df | |
|
794d90731a | |
|
8e4066e6e2 | |
|
1ddef32a83 | |
|
cbb75e58d8 | |
|
d3f73e62b1 | |
|
56733878da | |
|
b062a01afb | |
|
b51782e796 | |
|
b18bc89175 | |
|
4b707e9bc4 | |
|
f87efc7c20 | |
|
9612e48bbb | |
|
383eaaf14e | |
|
c633dd4a81 | |
|
490c8f87eb | |
|
0bf9f2a4b5 | |
|
441cdfb336 | |
|
86522a81a4 | |
|
6bd7303d82 | |
|
ebbaba0f59 | |
|
93630f99b4 | |
|
c83725bfa1 | |
|
106d85acf4 | |
|
9e550a896c | |
|
eab30a9a6d | |
|
3c658dba46 | |
|
1a87ac25f5 | |
|
76a6628865 | |
|
580055c688 | |
|
5d44d2c5ca | |
|
fc1a0f113f | |
|
1e0203472e | |
|
e4cb1b4a9d | |
|
b417eb04c8 | |
|
e150e33bfe | |
|
d1d1811fd3 | |
|
17ae71c72e | |
|
57225c0937 | |
|
1086b7d6a1 | |
|
0e0f016cd9 | |
|
b72899b658 | |
|
ee28d845f2 | |
|
bafa4f1aa4 | |
|
ec02aeef82 | |
|
46641a8696 | |
|
310795568c | |
|
176ac6d4b1 | |
|
e1fcf586e5 | |
|
bd58a29fca | |
|
bc6ec6be12 | |
|
541a2714b7 | |
|
3c7ce9cf24 | |
|
2e11fce1fd | |
|
ed8dcc9296 | |
|
bbe2631541 | |
|
39aa8bfd1d | |
|
eea8838963 | |
|
7e7b9d0ec0 | |
|
0a6317ec5c | |
|
a5866b13b1 | |
|
25af048f77 | |
|
c7b385cd67 | |
|
08b194c33d | |
|
3ef333f6ec | |
|
5a61625f6f | |
|
edf691a506 | |
|
6703d510b2 | |
|
97503e4a81 | |
|
7768c9ea49 | |
|
915e2371b1 | |
|
083bd15d91 | |
|
d517d57163 | |
|
ce74be1f6d | |
|
ec83350830 | |
|
184b0e2a14 | |
|
374392afb3 | |
|
d716b340e6 | |
|
55f673cacc | |
|
2eced5eadd | |
|
35339d7ebf | |
|
99b6da65af | |
|
1e95e722f9 | |
|
0cdcb0eec9 | |
|
db8da6b3ed | |
|
927a9bfd90 | |
|
874b45b29b | |
|
edf50b0a7a | |
|
9946294160 | |
|
d542c4675e | |
|
c15de686c0 | |
|
dfb5fffcef | |
|
b0a3a35396 | |
|
578bfc6710 | |
|
9912d73e70 | |
|
5eaca5d5dc | |
|
90e06fedc2 | |
|
eadf199649 | |
|
289ed3f4a3 | |
|
7fdef045ca | |
|
a395512a24 | |
|
ae746cd352 | |
|
4b6b1e2d6e | |
|
9ed1fd8f20 | |
|
fa3c2e4557 | |
|
e903eac47b | |
|
7ca930a12c | |
|
2d9dc116d6 | |
|
e4dea27c12 | |
|
ee8387f620 | |
|
dee2e909a4 | |
|
fe36e7d888 | |
|
5eddf6ad24 | |
|
4a3582748b | |
|
fa6c0e302f | |
|
ae88de413a | |
|
da261c6405 | |
|
719c9ace72 | |
|
e385ad798b | |
|
0b828ff38c | |
|
77f1f2e0d9 | |
|
570775ad1b | |
|
f2095cac40 | |
|
6029e86072 | |
|
30614bd223 | |
|
69e8428b2e | |
|
c9396cc163 | |
|
d3eb00b93d | |
|
4b3a61ed39 | |
|
fcee12335e | |
|
accc58a6b0 | |
|
840a78db95 | |
|
f581e761e8 | |
|
ab8508a0cb | |
|
fa3374a492 | |
|
fa3d6ba274 | |
|
7b0902435c | |
|
7369db6778 | |
|
85537a1dec | |
|
d106b8eeb4 | |
|
e63226e755 | |
|
5037b16123 | |
|
05cfdeefb3 | |
|
8b3ac481e9 | |
|
359a01e7ea | |
|
972c9da4cf | |
|
0109e5fbb9 | |
|
92bc630e4f | |
|
8ae21413f4 | |
|
2c20e23ba3 | |
|
892049c2cb | |
|
1d94e53866 | |
|
0df111ee42 | |
|
61827b87eb | |
|
f21df83abc | |
|
fd2fca1d90 | |
|
ede1f1fead | |
|
99477b8ede | |
|
ac2df1436d | |
|
eaf36fec5e | |
|
31c9c4de7b | |
|
08d5e498a0 | |
|
54431a131d | |
|
32cc5c184a | |
|
2232cd2eb9 | |
|
b8f2851dab | |
|
0b682fd3d7 | |
|
206368282d | |
|
9ed6fc4541 | |
|
5b8ca016c2 | |
|
3de89cd94e | |
|
500f0f148e | |
|
33054356d0 | |
|
0b1a110b22 | |
|
c0c417ca29 | |
|
647cc252d4 | |
|
affbfe1d88 | |
|
b14d9d5752 | |
|
fea8e572fd | |
|
4e8a7b2cdd | |
|
bf4fedc544 | |
|
b0651c755e | |
|
513dce940f | |
|
334a1efbd9 | |
|
bee6c5b895 | |
|
5bc293dd50 | |
|
4260dd6888 | |
|
17fac05da1 | |
|
ee5558d817 | |
|
1ccd30b337 | |
|
8ed5a6981f | |
|
27e25c9907 | |
|
ead25a3390 | |
|
801ea3a957 | |
|
67942d615b | |
|
311195f86d | |
|
1085708123 | |
|
5845c87e69 | |
|
3deea2b478 | |
|
63680b0b6f | |
|
6cc1ccaa5a | |
|
80c7f9aa8c | |
|
f4ba67baf9 | |
|
16d3d52005 | |
|
33ed7abc0d | |
|
816019e202 | |
|
d9da2119a6 | |
|
0675e5de8c | |
|
4e4a6a61e0 | |
|
5c3be3a19f | |
|
03ceefcd11 | |
|
edac104fbc | |
|
42d56b9dbc | |
|
24baec9cea | |
|
4204cf2e19 | |
|
2308252fd9 | |
|
1b1481e86a | |
|
a755e68ee6 | |
|
0028688ffb | |
|
500d564cd6 | |
|
c0fb0a7beb | |
|
d79ad95f6f | |
|
f78a64ee4e | |
|
cad6b19f02 | |
|
c4da4cc9dc | |
|
e1b1c3cbb1 | |
|
4a2e077dce | |
|
64033be9f2 | |
|
ac7ce48a8c | |
|
5524b909a9 | |
|
ddaeee11c7 | |
|
a3e6697500 | |
|
429c9ed6f1 | |
|
0a1302dbc6 | |
|
198c016099 | |
|
6dfcc4b90c | |
|
2c1334a4a9 | |
|
4d15c8ffa4 | |
|
0442af36ab | |
|
a7c1789eb2 | |
|
b12d75f2cd | |
|
0157c571ad | |
|
2819af41e2 | |
|
3ba8bd4ba8 | |
|
45a70fe238 | |
|
5daeab89dd | |
|
1f2865807a | |
|
d31b056292 | |
|
d9a80affcf | |
|
b6f0e08257 | |
|
361037cdbd | |
|
4b39a2da63 | |
|
d95e066b7d | |
|
bb55697dda | |
|
ed072c229d | |
|
80f5c1be1f | |
|
6a3b006cc1 | |
|
6fe9de3ac9 | |
|
d97e0c5ba5 | |
|
59852d3bd3 | |
|
9a288c91de | |
|
6270102c99 | |
|
2ab14c25d1 | |
|
6d814a2e2d | |
|
1b59098fa4 | |
|
d83a96ed63 | |
|
88607e9419 | |
|
a04d2213c4 | |
|
cc3af1218c | |
|
32071fe0ad | |
|
14d3413f1e | |
|
534a3a80f0 | |
|
23c9db651c | |
|
2f2bb8f440 | |
|
49b33137e6 | |
|
531cafc11c | |
|
7762b36e37 | |
|
30fd07591e | |
|
dcfe691fd3 | |
|
549cd8ff48 | |
|
76b7043bdf | |
|
b513d19b60 | |
|
e800937321 | |
|
1c0e5f05d5 | |
|
2e13e2c5b7 | |
|
582b5a0aee | |
|
bab4abe978 | |
|
988e71402c | |
|
5728ee8983 | |
|
763061caf8 | |
|
2da0738339 | |
|
986c6c7ab4 | |
|
cebb4e7beb | |
|
829bbcd588 | |
|
f608d88c9d | |
|
cea0a9744f | |
|
7150e86473 | |
|
3f49c7fecd | |
|
188709e4a5 | |
|
23015c318a | |
|
ec87210310 | |
|
94ffea202f | |
|
4814786ab3 | |
|
9e963aba7b | |
|
c911fd99b2 | |
|
0a94117088 | |
|
e9dc4404ca | |
|
db5b324eec | |
|
c5ccfef7d0 | |
|
fde8231177 | |
|
045b5861e7 | |
|
004e591076 | |
|
842827ad22 | |
|
4131b5e51d | |
|
78c82af2dc | |
|
612331e5e9 | |
|
e20e51a3b1 | |
|
09a3f34f12 | |
|
393e3ee1d6 | |
|
144151fc0c | |
|
7b6dac9bd5 | |
|
e0563c17c8 | |
|
b6324ba2b9 | |
|
62e3d6b54a | |
|
23c20628d9 | |
|
861dbee3b0 | |
|
f9937cd32c | |
|
d3e93c7c7b | |
|
be7a2f80bd | |
|
33641b85d8 | |
|
2422950925 | |
|
a0b25da459 | |
|
a242a2b395 | |
|
fb40cfff10 | |
|
e50cda5478 | |
|
d003d2aaac | |
|
a3c07e0392 | |
|
1cae5ea56d | |
|
b268c4a9e1 | |
|
d5fbb09d77 | |
|
d10e2ec4fa | |
|
c0b601130b | |
|
159fa782c0 | |
|
8c076f95bd | |
|
db9acc1cde | |
|
635e3cdcb7 | |
|
bf1459a778 | |
|
efb02ff3bb | |
|
bcf426bfda | |
|
e83c02e161 | |
|
9ae9d5ccf4 | |
|
d42bfba824 | |
|
a320208253 | |
|
03cc7d445c | |
|
a9ae7ed140 | |
|
2e08a6b26b | |
|
19206c564a | |
|
be1c6919be | |
|
f163b1becf | |
|
368401f35a | |
|
f27843d493 |
|
@ -16,7 +16,7 @@ indent_size = 4
|
|||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8-bom
|
||||
[*.{json,yml,xml}]
|
||||
[*.{json,yml,xml,csproj,props}]
|
||||
indent_size = 2
|
||||
###############################
|
||||
# .NET Coding Conventions #
|
||||
|
@ -123,9 +123,13 @@ csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
|||
# Wrapping preferences
|
||||
csharp_preserve_single_line_statements = true
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_style_namespace_declarations=file_scoped:silent
|
||||
###############################
|
||||
# VB Coding Conventions #
|
||||
###############################
|
||||
[*.vb]
|
||||
# Modifier preferences
|
||||
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
|
||||
[*.cs]
|
||||
# Add file header
|
||||
file_header_template = Copyright (c) Argo Zhang (argo@163.com). All rights reserved.\nLicensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.\nWebsite: https://admin.blazor.zone
|
|
@ -14,6 +14,6 @@ jobs:
|
|||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.1.100
|
||||
dotnet-version: 5.0.103
|
||||
- name: Build with dotnet
|
||||
run: dotnet build src/admin/Bootstrap.Admin/ --configuration Release
|
|
@ -12,4 +12,4 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build the Docker image
|
||||
run: docker build . --file src/admin/Bootstrap.Admin/Linux.Dockerfile --tag ba:$(date +%s)
|
||||
run: docker build . --file src/admin/Bootstrap.Admin/Dockerfile --tag ba:$(date +%s)
|
||||
|
|
|
@ -85,7 +85,6 @@ StyleCopReport.xml
|
|||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
|
@ -348,10 +347,10 @@ ASALocalRun/
|
|||
|
||||
# Net Core Keys
|
||||
**/[Kk]eys/*.xml
|
||||
Bootstrap.*.xml
|
||||
Bootstrap*.xml
|
||||
|
||||
###### -- Custom Ignore Section, Make sure all files you add to the git repo are below this line -- ######
|
||||
|
||||
# Coverage
|
||||
coverage*.xml
|
||||
tools/
|
||||
tools/
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"solution": {
|
||||
"path": "BootstrapAdmin.sln",
|
||||
"projects": [
|
||||
"src\\blazor\\admin\\BootstrapAdmin.Caching\\BootstrapAdmin.Caching.csproj",
|
||||
"src\\blazor\\admin\\BootstrapAdmin.DataAccess.Models\\BootstrapAdmin.DataAccess.Models.csproj",
|
||||
"src\\blazor\\admin\\BootstrapAdmin.DataAccess.PetaPoco\\BootstrapAdmin.DataAccess.PetaPoco.csproj",
|
||||
"src\\blazor\\admin\\BootstrapAdmin.Web.Core\\BootstrapAdmin.Web.Core.csproj",
|
||||
"src\\blazor\\admin\\BootstrapAdmin.Web\\BootstrapAdmin.Web.csproj",
|
||||
"src\\blazor\\client\\BootstrapClient.DataAccess\\BootstrapClient.DataAccess.PetaPoco.csproj",
|
||||
"src\\blazor\\client\\BootstrapClient.Shared\\BootstrapClient.Web.Shared.csproj",
|
||||
"src\\blazor\\client\\BootstrapClient.Web.Core\\BootstrapClient.Web.Core.csproj",
|
||||
"src\\blazor\\client\\BootstrapClient.Web.Models\\BootstrapClient.DataAccess.Models.csproj",
|
||||
"src\\blazor\\client\\BootstrapClient.Web\\BootstrapClient.Web.csproj",
|
||||
"src\\mvc\\admin\\Bootstrap.Admin\\Bootstrap.Admin.csproj",
|
||||
"src\\mvc\\admin\\Bootstrap.DataAccess\\Bootstrap.DataAccess.csproj",
|
||||
"test\\UnitTest\\UnitTest.csproj"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29215.179
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{87319AF5-7C40-4362-B67C-35F9DD737DB4}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -10,15 +10,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLServer", "SQLServer", "{
|
|||
db\SqlServer\Install.sql = db\SqlServer\Install.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Admin", "src\mvc\admin\Bootstrap.Admin\Bootstrap.Admin.csproj", "{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "db", "db", "{586410F2-C1F0-47CD-AB28-2CF506DED2C8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client", "src\mvc\client\Bootstrap.Client\Bootstrap.Client.csproj", "{C82A6E45-AB90-43D1-8429-5CBE953D8151}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess", "src\mvc\admin\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj", "{8D62BE79-BE13-43C8-969B-C9B00B3C84B7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515EC-2AD7-4282-9AF4-9D20371183B0}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -26,7 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SQLite", "SQLite", "{523515
|
|||
db\SQLite\Install.sql = db\SQLite\Install.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.DataAccess.MongoDB", "src\mvc\admin\Bootstrap.DataAccess.MongoDB\Bootstrap.DataAccess.MongoDB.csproj", "{8336F096-4B4A-4710-A1FA-0F5E44CD8D26}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MongoDB", "MongoDB", "{A06A0AD8-A246-4329-B024-7174AE4A3EDE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -57,9 +57,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Postgresql", "Postgresql",
|
|||
db\Postgresql\install.sql = db\Postgresql\install.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess", "src\mvc\client\Bootstrap.Client.DataAccess\Bootstrap.Client.DataAccess.csproj", "{843811A2-FE49-410F-BF9F-9F1FB14A1DEE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bootstrap.Client.DataAccess.MongoDB", "src\mvc\client\Bootstrap.Client.DataAccess.MongoDB\Bootstrap.Client.DataAccess.MongoDB.csproj", "{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6AD32A76-F3AA-423E-96EA-E5CC679934D1}"
|
||||
EndProject
|
||||
|
@ -74,10 +74,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E057452E-0
|
|||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{85574E7C-7D58-4135-AB4B-76678552D271}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\admin\Bootstrap.Admin\Dockerfile = src\admin\Bootstrap.Admin\Dockerfile
|
||||
src\admin\Bootstrap.Admin\Linux.Dockerfile = src\admin\Bootstrap.Admin\Linux.Dockerfile
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "srcipts", "srcipts", "{72C103DB-E1D3-449F-97C2-DF12CA111FD4}"
|
||||
EndProject
|
||||
|
@ -121,6 +117,54 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Oracle", "Oracle", "{41E078
|
|||
db\Oracle\Install.sql = db\Oracle\Install.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "git", "git", "{64EACBD1-23DD-4168-BEED-55D47DB1A8BB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
scripts\git\commit_msg_template.txt = scripts\git\commit_msg_template.txt
|
||||
scripts\git\readme.md = scripts\git\readme.md
|
||||
scripts\git\run.cmd = scripts\git\run.cmd
|
||||
scripts\git\run.sh = scripts\git\run.sh
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "blazor", "blazor", "{DAE3826B-AAAB-468A-9A06-2F56EF5C0767}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{C07631B9-5E5E-417A-9A16-3C88956D574E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\build.yml = .github\workflows\build.yml
|
||||
.github\workflows\docker.yml = .github\workflows\docker.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mvc", "mvc", "{C996F427-DA93-49D6-9804-4E665D195FC2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{45ADEF9B-C8BD-4224-9E12-F6716E85A22C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{55A2459A-6BDE-4493-B2C0-5BE1673E99EE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Web", "src\blazor\admin\BootstrapAdmin.Web\BootstrapAdmin.Web.csproj", "{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.EFCore", "src\blazor\admin\BootstrapAdmin.DataAccess.EFCore\BootstrapAdmin.DataAccess.EFCore.csproj", "{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.Models", "src\blazor\admin\BootstrapAdmin.DataAccess.Models\BootstrapAdmin.DataAccess.Models.csproj", "{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.DataAccess.PetaPoco", "src\blazor\admin\BootstrapAdmin.DataAccess.PetaPoco\BootstrapAdmin.DataAccess.PetaPoco.csproj", "{20D03C52-0F8B-47B6-BCA8-CF0812F82722}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Web.Core", "src\blazor\admin\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj", "{DA143654-C258-410D-B5DC-FE446ED99CE4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.DataAccess.PetaPoco", "src\blazor\client\BootstrapClient.DataAccess\BootstrapClient.DataAccess.PetaPoco.csproj", "{640F598B-6586-4AD6-B544-78CFF2602DFB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web.Shared", "src\blazor\client\BootstrapClient.Shared\BootstrapClient.Web.Shared.csproj", "{93770088-3463-427B-9CD8-88B8D7945C83}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web", "src\blazor\client\BootstrapClient.Web\BootstrapClient.Web.csproj", "{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootStarpAdmin.DataAccess.FreeSql", "src\blazor\admin\BootStarpAdmin.DataAccess.FreeSql\BootStarpAdmin.DataAccess.FreeSql.csproj", "{11122D97-B349-4A3E-B7DD-73B8B363C47C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootStarpAdmin.DataAccess.SqlSugar", "src\blazor\admin\BootStarpAdmin.DataAccess.SqlSugar\BootStarpAdmin.DataAccess.SqlSugar.csproj", "{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.Web.Core", "src\blazor\client\BootstrapClient.Web.Core\BootstrapClient.Web.Core.csproj", "{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapClient.DataAccess.Models", "src\blazor\client\BootstrapClient.Web.Models\BootstrapClient.DataAccess.Models.csproj", "{CC3DF23A-2880-438F-BDEB-DB093E919ABA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapAdmin.Caching", "src\blazor\admin\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj", "{ADD20515-1C1C-418B-84F6-8B05A7AA315B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -155,6 +199,58 @@ Global
|
|||
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{20D03C52-0F8B-47B6-BCA8-CF0812F82722}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA143654-C258-410D-B5DC-FE446ED99CE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{640F598B-6586-4AD6-B544-78CFF2602DFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{93770088-3463-427B-9CD8-88B8D7945C83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{93770088-3463-427B-9CD8-88B8D7945C83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{93770088-3463-427B-9CD8-88B8D7945C83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{93770088-3463-427B-9CD8-88B8D7945C83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{11122D97-B349-4A3E-B7DD-73B8B363C47C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CC3DF23A-2880-438F-BDEB-DB093E919ABA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADD20515-1C1C-418B-84F6-8B05A7AA315B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -163,7 +259,7 @@ Global
|
|||
{87319AF5-7C40-4362-B67C-35F9DD737DB4} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
|
||||
{7B2B7043-3CB2-4C5A-BDF2-8C47F1A5471A} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
|
||||
{C82A6E45-AB90-43D1-8429-5CBE953D8151} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
|
||||
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
|
||||
{C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0} = {C996F427-DA93-49D6-9804-4E665D195FC2}
|
||||
{8D62BE79-BE13-43C8-969B-C9B00B3C84B7} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
|
||||
{523515EC-2AD7-4282-9AF4-9D20371183B0} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
|
||||
{8336F096-4B4A-4710-A1FA-0F5E44CD8D26} = {E03B7391-B52F-4449-B400-5CD9DE01F085}
|
||||
|
@ -173,12 +269,30 @@ Global
|
|||
{6F61C2AC-84D4-48A9-8A48-680657CC8175} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
|
||||
{843811A2-FE49-410F-BF9F-9F1FB14A1DEE} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
|
||||
{BC1C6D63-ADA9-4C3B-89F0-CEB191A86BF5} = {C7F51A14-2D89-4D1F-AD78-C42B79AB0BF0}
|
||||
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
|
||||
{E03B7391-B52F-4449-B400-5CD9DE01F085} = {C996F427-DA93-49D6-9804-4E665D195FC2}
|
||||
{C6F2DCA0-7941-4C28-9328-2D495F5DCB00} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
|
||||
{FDCFC3E3-14CF-40B2-9FE5-5BC239AAC110} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
|
||||
{5F732D4E-133B-4DA6-811B-C369CDC3FB89} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
|
||||
{68F7C160-3FB2-4129-8F89-96F78B2DA0A9} = {FDCFC3E3-14CF-40B2-9FE5-5BC239AAC110}
|
||||
{41E078CA-F005-4B66-B440-FD7EB731AD61} = {586410F2-C1F0-47CD-AB28-2CF506DED2C8}
|
||||
{64EACBD1-23DD-4168-BEED-55D47DB1A8BB} = {72C103DB-E1D3-449F-97C2-DF12CA111FD4}
|
||||
{DAE3826B-AAAB-468A-9A06-2F56EF5C0767} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
|
||||
{C996F427-DA93-49D6-9804-4E665D195FC2} = {41B6D37A-5E5E-42B3-85E4-D81A81E3D757}
|
||||
{45ADEF9B-C8BD-4224-9E12-F6716E85A22C} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
|
||||
{55A2459A-6BDE-4493-B2C0-5BE1673E99EE} = {DAE3826B-AAAB-468A-9A06-2F56EF5C0767}
|
||||
{EF5EF5A4-616A-4BA7-9E1E-1407E8EC0395} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{D8ED2DF7-F7E1-4DE7-B097-D0BEE51D58E9} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{7E3861AB-F797-4A9F-B7CE-0E35751FFCD9} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{20D03C52-0F8B-47B6-BCA8-CF0812F82722} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{DA143654-C258-410D-B5DC-FE446ED99CE4} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{640F598B-6586-4AD6-B544-78CFF2602DFB} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
|
||||
{93770088-3463-427B-9CD8-88B8D7945C83} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
|
||||
{6CD7A35B-93A8-4DB2-B078-EE5A81F40032} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
|
||||
{11122D97-B349-4A3E-B7DD-73B8B363C47C} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{1D20E6CF-9825-4CDE-B732-AE586BD1AABA} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
{FFDF9FF9-0B29-47D3-AD42-53A476B570EC} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
|
||||
{CC3DF23A-2880-438F-BDEB-DB093E919ABA} = {55A2459A-6BDE-4493-B2C0-5BE1673E99EE}
|
||||
{ADD20515-1C1C-418B-84F6-8B05A7AA315B} = {45ADEF9B-C8BD-4224-9E12-F6716E85A22C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {221EAE38-5F75-4391-9A48-E462A9F3B8FC}
|
||||
|
|
|
@ -11,17 +11,17 @@
|
|||
|
||||
<Target Condition=" $(IsWebProject) == true Or $(IsTestProject) == true" Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Message Text="Copy lic file -> $(TargetDir)" Importance="high" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(TargetDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
<Target Condition=" $(IsWebProject) == true " Name="PostPublish" AfterTargets="Publish">
|
||||
<Message Text="Publish lic file -> $(PublishDir)" Importance="high" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\keys\Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/keys/Longbow.lic" SkipUnchangedFiles="true" />
|
||||
<Message Text="Publish db file -> $(PublishDir)" Importance="high" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'Windows_NT'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src\mvc\admin\Bootstrap.Admin\BootstrapAdmin.db" SkipUnchangedFiles="true" />
|
||||
<Copy Condition="'$(OS)' == 'UNIX'" DestinationFolder="$(PublishDir)" SourceFiles="$(MSBuildThisFileDirectory)src/mvc/admin/Bootstrap.Admin/BootstrapAdmin.db" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
16
README.md
16
README.md
|
@ -5,19 +5,19 @@
|
|||
---
|
||||
|
||||
##### Version & Coverage
|
||||
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://ba.sdgxgz.com/api/Gitee/Releases)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
|
||||
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://admin.blazor.zone/api/Gitee/Releases?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
|
||||
[![Coveralls](https://img.shields.io/coveralls/github/ArgoZhang/BootstrapAdmin/master.svg?logo=ReverbNation&logoColor=green&label=coveralls)](https://coveralls.io/github/ArgoZhang/BootstrapAdmin)
|
||||
[![Codecov](https://img.shields.io/codecov/c/gh/argozhang/bootstrapadmin/master.svg?logo=codecov&label=codecov)](https://codecov.io/gh/argozhang/bootstrapadmin/branch/master)
|
||||
|
||||
##### Gitee
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
|
||||
[![Build Status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master)
|
||||
[![Test](https://img.shields.io/appveyor/tests/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master/tests)
|
||||
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://ba.sdgxgz.com/api/Gitee/Issues)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
|
||||
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://ba.sdgxgz.com/api/Gitee/Pulls)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
|
||||
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://admin.blazor.zone/api/Gitee/Issues?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
|
||||
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://admin.blazor.zone/api/Gitee/Pulls?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
|
||||
|
||||
##### GitHub
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
|
||||
[![master status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master)
|
||||
[![Test](https://img.shields.io/appveyor/tests/argozhang/bootstrapadmin/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master/tests)
|
||||
[![Github build](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Auto%20Build%20CI/master?label=master&logoColor=green&logo=github)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
|
||||
|
@ -60,7 +60,7 @@ Departments Authorize Users
|
|||
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D)
|
||||
|
||||
### Database
|
||||
**MSSQL/Oracle/SQLite/MySql/MariaDB/Postgresql/Firebird/MongoDB**
|
||||
**MSSQL/Oracle/SQLite/MySql/MariaDB/Firebird/MongoDB**
|
||||
|
||||
For more information, please click [wiki](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/数据库连接配置?sort_id=1333482)
|
||||
|
||||
|
@ -122,7 +122,7 @@ For more information, please click [wiki](https://gitee.com/LongbowEnterprise/Bo
|
|||
|
||||
## Online Demonstration
|
||||
[![website1](https://img.shields.io/badge/linux-http://ba.zylweb.cn-success.svg?logo=buzzfeed&logoColor=green)](http://ba.zylweb.cn)
|
||||
[![website2](https://img.shields.io/badge/linux-http://ba.sdgxgz.com-success.svg?logo=buzzfeed&logoColor=green)](http://ba.sdgxgz.com)
|
||||
[![website2](https://img.shields.io/badge/linux-http://admin.blazor.zone-success.svg?logo=buzzfeed&logoColor=green)](http://admin.blazor.zone)
|
||||
|
||||
### Login
|
||||
Administrator: Admin/123789
|
||||
|
@ -154,7 +154,7 @@ Please click [wikis](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E
|
|||
[![Gitee license](https://img.shields.io/github/license/argozhang/bootstrapadmin.svg?logo=git&logoColor=red)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/blob/master/LICENSE)
|
||||
|
||||
## GVP award
|
||||
[View](https://images.gitee.com/uploads/images/2019/0516/124055_96cc9f8d_554725.png "GiteeGVP.png")
|
||||
[View](https://images.gitee.com/uploads/images/2021/0112/112021_9d570be1_554725.png "GiteeGVP.png")
|
||||
|
||||
## Screenshots
|
||||
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
---
|
||||
|
||||
##### Version & Coverage
|
||||
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://ba.sdgxgz.com/api/Gitee/Releases)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
|
||||
[![Release](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=red&color=green&label=release&url=https://admin.blazor.zone/api/Gitee/Releases?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/releases)
|
||||
[![Coveralls](https://img.shields.io/coveralls/github/ArgoZhang/BootstrapAdmin/master.svg?logo=ReverbNation&logoColor=green&label=coveralls)](https://coveralls.io/github/ArgoZhang/BootstrapAdmin?branch=master)
|
||||
[![Codecov](https://img.shields.io/codecov/c/gh/argozhang/bootstrapadmin/master.svg?logo=codecov&label=codecov)](https://codecov.io/gh/argozhang/bootstrapadmin/branch/master)
|
||||
|
||||
##### Gitee
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin-9m1jm)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm)
|
||||
[![Build Status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master)
|
||||
[![Test](https://img.shields.io/appveyor/tests/ArgoZhang/bootstrapadmin-9m1jm/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin-9m1jm/branch/master/tests)
|
||||
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://ba.sdgxgz.com/api/Gitee/Issues)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
|
||||
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://ba.sdgxgz.com/api/Gitee/Pulls)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
|
||||
[![Issue Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=critical&label=issues&url=https://admin.blazor.zone/api/Gitee/Issues?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/issues)
|
||||
[![Pull Status](https://img.shields.io/endpoint.svg?logo=Groupon&logoColor=green&color=success&label=pulls&url=https://admin.blazor.zone/api/Gitee/Pulls?userName=LongbowEnterprise)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/pulls)
|
||||
|
||||
##### GitHub
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://ba.sdgxgz.com/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
|
||||
[![Appveyor build](https://img.shields.io/endpoint.svg?logo=appveyor&label=build&color=blueviolet&url=https://admin.blazor.zone/api/Gitee/Builds?projName=bootstrapadmin)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin)
|
||||
[![master status](https://img.shields.io/appveyor/ci/ArgoZhang/bootstrapadmin/master.svg?logo=appveyor&label=master)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master)
|
||||
[![Test](https://img.shields.io/appveyor/tests/argozhang/bootstrapadmin/master.svg?logo=appveyor&)](https://ci.appveyor.com/project/ArgoZhang/bootstrapadmin/branch/master/tests)
|
||||
[![Github build](https://img.shields.io/github/workflow/status/ArgoZhang/BootstrapAdmin/Auto%20Build%20CI/master?label=master&logoColor=green&logo=github)](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
|
||||
|
@ -29,6 +29,15 @@
|
|||
|
||||
使用 NET Core + Bootstrap + PetaPoco + HTML 5 + jQuery 构建的后台管理平台
|
||||
|
||||
**BootstrapAdmin** 与 **开源驰骋 ccflow** 达成如下协议.
|
||||
|
||||
1. 驰骋工作流引擎、表单引擎、快速开发平台系统采用 `GPL` 协议.
|
||||
2. 驰骋 `.net` 版本成为 `ccflow`, `java` 版本成为 `jflow` 两个版本代码 100% 开源.
|
||||
3. 与 BootstrapAdmin 签订服务合同的并且付费的 BootstrapAdmin 客户使用ccflow不开源系统代码受到法律保护.
|
||||
4. 驰骋 BPM 代码下载地址: [传送门](http://ccflow.org/down.htm?from=argo)
|
||||
|
||||
<a href='http://ccflow.org/?from=argo' target=_blank ><img src='https://images.gitee.com/uploads/images/2021/0718/172630_7ebb560a_554725.png' /></a>
|
||||
|
||||
### 特别说明
|
||||
**BootstrapAdmin** 无需二次开发,要做的仅仅是与前台系统集成,前台系统模板工程为 **Bootstrap.Client**
|
||||
项目原始出发点是把权限系统从业务系统中剥离出来,项目开发专注于功能,详细配置说明请点击 [查看文档](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E7%B3%BB%E7%BB%9F%E9%9B%86%E6%88%90)
|
||||
|
@ -66,6 +75,10 @@
|
|||
数据库支持列表如下:
|
||||
**MSSQL/Oracle/SQLite/MySql/MariaDB/Postgresql/Firebird/MongoDB**
|
||||
|
||||
### 工作流
|
||||
|
||||
与 **驰骋工作流** 进行深度集成,欢迎访问其主页 [传送门](http://ccflow.org/?from=argo)
|
||||
|
||||
### 浏览器支持
|
||||
|
||||
![chrome](https://img.shields.io/badge/chrome->%3D4.5-success.svg?logo=google%20chrome&logoColor=red)
|
||||
|
@ -116,7 +129,7 @@
|
|||
|
||||
## 开发环境搭建
|
||||
1. 安装 .net core sdk [官方网址](http://www.microsoft.com/net/download)
|
||||
2. 安装 Visual Studio 2019 以上 [官方网址](https://visualstudio.microsoft.com/vs/getting-started/)
|
||||
2. 安装 Visual Studio 2019 最新版 [官方网址](https://visualstudio.microsoft.com/vs/getting-started/)
|
||||
3. 获取本项目代码 [BootstrapAdmin](https://gitee.com/LongbowEnterprise/BootstrapAdmin)
|
||||
|
||||
环境搭建教程 [详细说明](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B?sort_id=1333477)
|
||||
|
@ -128,8 +141,7 @@
|
|||
2. SqlServer
|
||||
3. MySql
|
||||
4. Oracle
|
||||
5. PostgresSql
|
||||
6. MongoDB
|
||||
5. MongoDB
|
||||
|
||||
数据库配置 [详细说明](https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/数据库连接配置?sort_id=1333482)
|
||||
|
||||
|
@ -138,7 +150,7 @@
|
|||
|
||||
## 演示地址
|
||||
[![website1](https://img.shields.io/badge/linux-http://ba.zylweb.cn-success.svg?logo=buzzfeed&logoColor=green)](http://ba.zylweb.cn)
|
||||
[![website2](https://img.shields.io/badge/linux-http://ba.sdgxgz.com-success.svg?logo=buzzfeed&logoColor=green)](http://ba.sdgxgz.com)
|
||||
[![website2](https://img.shields.io/badge/linux-http://admin.blazor.zone-success.svg?logo=buzzfeed&logoColor=green)](http://admin.blazor.zone)
|
||||
|
||||
### 登录用户名与密码
|
||||
管理账号:Admin/123789
|
||||
|
@ -170,7 +182,7 @@ docker pull reg.qiniu.com/argozhang/ba
|
|||
[![Gitee license](https://img.shields.io/github/license/argozhang/bootstrapadmin.svg?logo=git&logoColor=red)](https://gitee.com/LongbowEnterprise/BootstrapAdmin/blob/master/LICENSE)
|
||||
|
||||
## GVP 奖杯
|
||||
[查看照片](https://images.gitee.com/uploads/images/2019/0516/124055_96cc9f8d_554725.png "GiteeGVP.png")
|
||||
![项目奖杯](https://images.gitee.com/uploads/images/2021/0112/112021_9d570be1_554725.png "GVP.png")
|
||||
|
||||
## 项目截图
|
||||
|
||||
|
@ -203,4 +215,4 @@ docker pull reg.qiniu.com/argozhang/ba
|
|||
|
||||
如果这个项目对您有所帮助,请扫下方二维码打赏一杯咖啡。
|
||||
|
||||
![WeChat](https://gitee.com/LongbowEnterprise/Pictures/raw/master/WeChat/WeChat.png "微信扫码")
|
||||
<img src="https://gitee.com/LongbowEnterprise/Pictures/raw/master/WeChat/BarCode@2x.png" width="382px;" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version: 3.1.{build}
|
||||
version: 5.0.{build}
|
||||
branches:
|
||||
only:
|
||||
- release
|
||||
|
@ -33,7 +33,7 @@ test_script:
|
|||
- ps: >-
|
||||
.\scripts\appveyor\appveyor.test.ps1
|
||||
artifacts:
|
||||
- path: src\admin\Bootstrap.Admin\bin\release\netcoreapp3.1\publish\
|
||||
- path: src\admin\Bootstrap.Admin\bin\release\net5.0\publish\
|
||||
name: BootstrapAdmin
|
||||
type: WebDeployPackage
|
||||
deploy:
|
||||
|
|
|
@ -359,5 +359,41 @@
|
|||
"Name": "网站图标",
|
||||
"Code": "/favicon.png",
|
||||
"Define": NumberInt(1)
|
||||
},
|
||||
{
|
||||
"Category": "系统首页",
|
||||
"Name": "高仿码云",
|
||||
"Code": "Login-Gitee",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"Category": "系统首页",
|
||||
"Name": "蓝色清新",
|
||||
"Code": "Login-Blue",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"Category": "系统首页",
|
||||
"Name": "系统默认",
|
||||
"Code": "Login",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"Category": "系统首页",
|
||||
"Name": "科技动感",
|
||||
"Code": "Login-Tec",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"Category": "系统首页",
|
||||
"Name": "Admin-LTE",
|
||||
"Code": "Login-LTE",
|
||||
"Define": NumberInt(0)
|
||||
},
|
||||
{
|
||||
"Category": "网站设置",
|
||||
"Name": "登录界面",
|
||||
"Code": "Login",
|
||||
"Define": NumberInt(0)
|
||||
}
|
||||
];
|
|
@ -77,6 +77,15 @@ INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '默认
|
|||
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '后台地址', 'http://localhost:50852', 0);
|
||||
|
||||
-- 系统登录首页设置
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '高仿码云', 'Login-Gitee', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '蓝色清新', 'Login-Blue', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '系统默认', 'Login', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '科技动感', 'Login-Tec', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', 'Admin-LTE', 'Login-LTE', 0);
|
||||
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('网站设置', '登录界面', 'Login', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
INSERT INTO Navigations (ParentId, Name, `Order`, Icon, Url, Category) VALUES (0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');
|
||||
|
|
|
@ -178,10 +178,10 @@ CREATE TABLE Traces(
|
|||
UserName VARCHAR (50) NOT NULL,
|
||||
LogTime DATETIME NOT NULL,
|
||||
IP VARCHAR (15) NOT NULL,
|
||||
Browser VARCHAR (50),
|
||||
OS VARCHAR (50),
|
||||
Browser VARCHAR (2000),
|
||||
OS VARCHAR (2000),
|
||||
City VARCHAR (50),
|
||||
RequestUrl VARCHAR (500) NOT NULL,
|
||||
RequestUrl VARCHAR (2000) NOT NULL,
|
||||
UserAgent VARCHAR (2000) NULL,
|
||||
Referer VARCHAR (2000)
|
||||
);
|
||||
|
@ -189,6 +189,6 @@ CREATE TABLE Traces(
|
|||
CREATE TABLE DBLogs (
|
||||
ID INTEGER PRIMARY KEY Auto_increment,
|
||||
UserName VARCHAR (50) NULL,
|
||||
`SQL` VARCHAR (2000) NOT NULL,
|
||||
`SQL` Text NOT NULL,
|
||||
LogTime DATETIME NOT NULL
|
||||
);
|
||||
|
|
|
@ -76,6 +76,15 @@ INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVA
|
|||
INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVAL, '网站设置', '默认应用程序', '0', 0);
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) Values (SEQ_DICTS_ID.NEXTVAL, '网站设置', '后台地址', 'http://localhost:50852', 0);
|
||||
|
||||
-- 系统登录首页设置
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '高仿码云', 'Login-Gitee', 0);
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '蓝色清新', 'Login-Blue', 0);
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '系统默认', 'Login', 0);
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', '科技动感', 'Login-Tec', 0);
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '系统首页', 'Admin-LTE', 'Login-LTE', 0);
|
||||
|
||||
INSERT INTO Dicts (Id, Category, Name, Code, Define) VALUES (SEQ_DICTS_ID.NEXTVAL, '网站设置', '登录界面', 'Login', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO Navigations (Id, ParentId, Name, "ORDER", Icon, Url, Category) Values (SEQ_NAVIGATIONS_ID.NEXTVAL, 0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
INSERT INTO Navigations (Id, ParentId, Name, "ORDER", Icon, Url, Category) Values (SEQ_NAVIGATIONS_ID.NEXTVAL, 0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');
|
||||
|
|
|
@ -178,10 +178,10 @@ CREATE TABLE Traces(
|
|||
UserName NVARCHAR2 (50) NOT NULL,
|
||||
LogTime DATE NOT NULL,
|
||||
IP NVARCHAR2 (15) NOT NULL,
|
||||
Browser NVARCHAR2 (50),
|
||||
OS NVARCHAR2 (50),
|
||||
Browser NVARCHAR2 (2000),
|
||||
OS NVARCHAR2 (2000),
|
||||
City NVARCHAR2 (50),
|
||||
RequestUrl NVARCHAR2 (500) NOT NULL,
|
||||
RequestUrl NVARCHAR2 (2000) NOT NULL,
|
||||
UserAgent NVARCHAR2 (2000),
|
||||
Referer NVARCHAR2 (2000)
|
||||
);
|
||||
|
|
|
@ -178,10 +178,10 @@ CREATE TABLE Traces(
|
|||
UserName VARCHAR (50) NOT NULL,
|
||||
LogTime DATE NOT NULL,
|
||||
IP VARCHAR (15) NOT NULL,
|
||||
Browser VARCHAR (50),
|
||||
OS VARCHAR (50),
|
||||
Browser VARCHAR (2000),
|
||||
OS VARCHAR (2000),
|
||||
City VARCHAR (50),
|
||||
RequestUrl VARCHAR (500) NOT NULL,
|
||||
RequestUrl VARCHAR (2000) NOT NULL,
|
||||
UserAgent VARCHAR (2000) NULL,
|
||||
Referer VARCHAR (2000)
|
||||
);
|
||||
|
|
|
@ -5,8 +5,6 @@ INSERT INTO Users (UserName, Password, PassSalt, DisplayName, RegisterTime, Appr
|
|||
INSERT INTO Users (UserName, Password, PassSalt, DisplayName, RegisterTime, ApprovedTime, ApprovedBy, [Description], [App]) values ('User', 'tXG/yNffpnm6cThrCH7wf6jN1ic3VHvLoY4OrzKtrZ4=', 'c5cIrRMn8XjB84M/D/X7Lg9uUqQFmYNEdxb/4HWH8OLa4pNZ', '测试账号', datetime(CURRENT_TIMESTAMP, 'localtime'), datetime(CURRENT_TIMESTAMP, 'localtime'), 'system', '系统默认创建', 'Demo');
|
||||
|
||||
DELETE From Dicts Where Define = 0;
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('菜单', '系统菜单', '0', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('菜单', '外部菜单', '1', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('应用程序', '后台管理', 'BA', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '网站标题', '后台管理系统', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '网站页脚', '2016 © 通用后台管理系统', 0);
|
||||
|
@ -81,6 +79,15 @@ INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置
|
|||
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '后台地址', 'http://localhost:50852', 0);
|
||||
|
||||
-- 系统登录首页设置
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '2-高仿码云', 'Login-Gitee', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '3-蓝色清新', 'Login-Blue', 0);
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('系统首页', '1-系统默认', 'Login', 1);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', '科技动感', '4-Login-Tec', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES ('系统首页', 'Admin-LTE', '5-Login-LTE', 0);
|
||||
|
||||
INSERT INTO [Dicts] ([Category], [Name], [Code], [Define]) VALUES ('网站设置', '登录界面', 'Login', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = '0';
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '后台管理', 10, 'fa fa-gear', '~/Admin/Index', '0');
|
||||
INSERT INTO [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, '个人中心', 20, 'fa fa-suitcase', '~/Admin/Profiles', '0');
|
||||
|
|
|
@ -178,10 +178,10 @@ CREATE TABLE Traces(
|
|||
UserName VARCHAR (50) NOT NULL COLLATE NOCASE,
|
||||
LogTime DATETIME NOT NULL,
|
||||
IP VARCHAR (15) NOT NULL,
|
||||
Browser VARCHAR (50),
|
||||
OS VARCHAR (50),
|
||||
Browser VARCHAR (2000),
|
||||
OS VARCHAR (2000),
|
||||
City VARCHAR (50),
|
||||
RequestUrl VARCHAR (500) NOT NULL,
|
||||
RequestUrl VARCHAR (2000) NOT NULL,
|
||||
UserAgent VARCHAR (2000),
|
||||
Referer VARCHAR (2000)
|
||||
);
|
||||
|
|
|
@ -81,6 +81,15 @@ INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'网站设
|
|||
|
||||
INSERT [dbo].[Dicts] ([Category], [Name], [Code], [Define]) VALUES (N'网站设置', N'后台地址', 'http://localhost:50852', 0)
|
||||
|
||||
-- 系统登录首页设置
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'高仿码云', N'Login-Gitee', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'蓝色清新', N'Login-Blue', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'系统默认', N'Login', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'科技动感', N'Login-Tec', 0);
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'系统首页', N'Admin-LTE', N'Login-LTE', 0);
|
||||
|
||||
INSERT INTO Dicts (Category, Name, Code, Define) VALUES (N'网站设置', N'登录界面', N'Login', 0);
|
||||
|
||||
DELETE FROM Navigations Where Category = N'0'
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'后台管理', 10, N'fa fa-gear', N'~/Admin/Index', N'0')
|
||||
INSERT [Navigations] ([ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (0, N'个人中心', 20, N'fa fa-suitcase', N'~/Admin/Profiles', N'0')
|
||||
|
|
|
@ -564,10 +564,10 @@ CREATE TABLE [dbo].[Traces](
|
|||
[UserName] [varchar](50) NOT NULL,
|
||||
[LogTime] [datetime] NOT NULL,
|
||||
[Ip] [varchar](15) NOT NULL,
|
||||
[Browser] [varchar](50) NULL,
|
||||
[OS] [varchar](50) NULL,
|
||||
[Browser] [varchar](2000) NULL,
|
||||
[OS] [varchar](2000) NULL,
|
||||
[City] [nvarchar](50) NULL,
|
||||
[RequestUrl] [nvarchar](500) NOT NULL,
|
||||
[RequestUrl] [nvarchar](2000) NOT NULL,
|
||||
[UserAgent] [varchar](2000) NULL,
|
||||
[Referer] [nvarchar](2000) NULL,
|
||||
CONSTRAINT [PK_Traces] PRIMARY KEY CLUSTERED
|
||||
|
|
|
@ -70,12 +70,9 @@ function reportCodecov() {
|
|||
}
|
||||
}
|
||||
|
||||
$branch = $($env:APPVEYOR_REPO_BRANCH)
|
||||
if ($branch -ne "dev") {
|
||||
installDB
|
||||
installCoveralls
|
||||
installCodecov
|
||||
runUnitTest
|
||||
reportCoveralls
|
||||
reportCodecov
|
||||
}
|
||||
installDB
|
||||
installCoveralls
|
||||
installCodecov
|
||||
runUnitTest
|
||||
reportCoveralls
|
||||
reportCodecov
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
fix(#BUGID): 简要描述
|
||||
|
||||
#Comment
|
||||
comment #BUGID
|
||||
|
||||
#Issue
|
||||
close link fix https://gitee.com/LongbowEnterprise/dashboard/issues?id=BUGID
|
||||
|
||||
# 样式 : feat(location): 接入登录API
|
||||
#
|
||||
# 登录功能与服务器对接
|
||||
#
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
|
||||
#其中 type 的值可以有
|
||||
# feat: 新功能
|
||||
# fix: 修复bug
|
||||
# doc: 文档改变
|
||||
# style: 代码格式改变
|
||||
# refactor: 某个已有功能重构
|
||||
# perf: 性能优化
|
||||
# test: 增加测试
|
||||
# build: 改变了build工具 如 更新 props 文件
|
||||
# revert: 撤销上一次的 commit
|
||||
# db: 数据库文件或者脚本更改
|
||||
# script: 辅助脚本改变
|
||||
#
|
||||
#scope: 用来说明此次修改的影响范围
|
||||
# all: 表示影响面大 ,如修改了网络框架 会对真个程序产生影响
|
||||
# location: 表示影响小,某个小小的功能
|
||||
# module: 表示会影响某个模块 如登录模块、首页模块 、用户管理模块等等
|
||||
#
|
||||
#subject: 用来简要描述本次改动,概述就好了
|
||||
#
|
||||
#body: 具体的修改信息 应该尽量详细
|
||||
#
|
||||
#footer: 放置写备注啥的,如果是 bug ,可以把bug id放入
|
||||
#
|
|
@ -0,0 +1,32 @@
|
|||
## 提交模板配置
|
||||
|
||||
### Windows Fork
|
||||
|
||||
Windows 版本的 Fork 提供了提交模板 (commit message template)功能,配置步骤如下
|
||||
|
||||
#### git 配置文件
|
||||
|
||||
1. 拷贝仓库 `scripts\git\commit_msg_template.txt` 文件到当前用户根目录下 `C:\Users\[用户名]\.commit_msg_template.txt`
|
||||
2. 配置 git 全局配置文件 `C:\Users\[用户名]\.gitconfig` (此文件为隐藏文件)
|
||||
3. 更新 commit 配置项
|
||||
|
||||
```log
|
||||
[commit]
|
||||
template = /Users/argo/.commit_msg_template.txt
|
||||
```
|
||||
|
||||
注意原始文件不是 . 开头拷贝到跟目录下为 . 开头文件名(点号开头文件默认为隐藏文件)
|
||||
|
||||
#### Fork 配置步骤
|
||||
|
||||
1. 打开要配置的仓库
|
||||
2. 点击菜单栏第二个 **仓库** 菜单(Repository)
|
||||
3. 下拉菜单中选中最后一个菜单项 **仓库设置** 子菜单(Settings for this repository)
|
||||
|
||||
如下图所示
|
||||
![输入图片说明](https://images.gitee.com/uploads/images/2020/0327/123310_1b9b4af3_554725.png "Screen Shot 2020-03-27 at 12.30.38.png")
|
||||
|
||||
4. 切换到 **提交模板** 面板(Commit Template)
|
||||
5. 勾选使用 **全局配置文件** (Use global git configuration file)
|
||||
|
||||
下面的文本框内即出现提交模板内容
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
|
||||
copy commit_msg_template.txt "%USERPROFILE%\.commit_msg_template.txt" /y
|
|
@ -0,0 +1,3 @@
|
|||
#! /bin/bash
|
||||
|
||||
cp commit_msg_template.txt "../../.git/commit_msg_template1.txt"
|
|
@ -4,10 +4,10 @@ cd ~/BootstrapAdmin
|
|||
git pull
|
||||
dotnet publish src/admin/Bootstrap.Admin -c Release
|
||||
|
||||
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/appsettings*.json
|
||||
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/BootstrapAdmin.db
|
||||
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/appsettings*.json
|
||||
rm -f ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/BootstrapAdmin.db
|
||||
|
||||
systemctl stop ba.admin
|
||||
\cp -fr ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/netcoreapp3.1/publish/* /usr/local/ba/admin/
|
||||
\cp -fr ~/BootstrapAdmin/src/admin/Bootstrap.Admin/bin/Release/net5.0/publish/* /usr/local/ba/admin/
|
||||
systemctl start ba.admin
|
||||
systemctl status ba.admin -l
|
||||
|
|
|
@ -4,8 +4,8 @@ cd ~/BootstrapAdmin
|
|||
git pull
|
||||
dotnet publish src/client/Bootstrap.Client -c Release
|
||||
|
||||
rm -f ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/netcoreapp3.1/publish/appsettings*.json
|
||||
rm -f ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/net5.0/publish/appsettings*.json
|
||||
systemctl stop ba.client
|
||||
\cp -fr ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/netcoreapp3.1/publish/* /usr/local/ba/client/
|
||||
\cp -fr ~/BootstrapAdmin/src/client/Bootstrap.Client/bin/Release/net5.0/publish/* /usr/local/ba/client/
|
||||
systemctl start ba.client
|
||||
systemctl status ba.client -l
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageProjectUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin</PackageProjectUrl>
|
||||
<RepositoryUrl>https://gitee.com/LongbowEnterprise/BootstrapAdmin.git</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bootstrap.Admin.Controllers.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Gitee 网站信息接口类
|
||||
/// </summary>
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
[AllowAnonymous]
|
||||
public class GiteeController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取 Gitee 网站 Issues 信息
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="repoName"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Issues([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
|
||||
{
|
||||
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/issues", url => client.HttpClient.GetStringAsync(url), content =>
|
||||
{
|
||||
var regex = Regex.Matches(content, "<div class='ui mini circular label'>([\\d]+)</div>", RegexOptions.IgnoreCase);
|
||||
var labels = new string[] { "open", "progressing", "closed", "rejected" };
|
||||
var result = string.IsNullOrEmpty(content) ? new string[] { "unknown" } : regex.Select((m, i) => $"{labels[i]} {m.Groups[1].Value}");
|
||||
return string.Join(" ", result);
|
||||
});
|
||||
color = ret.StartsWith("open 0 progressing 0", StringComparison.OrdinalIgnoreCase) ? "success" : color;
|
||||
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Gitee 网站 Pulls 信息
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="repoName"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Pulls([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
|
||||
{
|
||||
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/pulls", url => client.HttpClient.GetStringAsync(url), content =>
|
||||
{
|
||||
var regex = Regex.Matches(content, "<div class='ui mini circular label'>([\\d]+)</div>", RegexOptions.IgnoreCase);
|
||||
var labels = new string[] { "open", "merged", "closed" };
|
||||
var result = string.IsNullOrEmpty(content) ? new string[] { "unknown" } : regex.Select((m, i) => $"{labels[i]} {m.Groups[1].Value}");
|
||||
return string.Join(" ", result);
|
||||
});
|
||||
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Gitee 网站 Releases 信息
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="repoName"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Releases([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "LongbowEnterprise", [FromQuery]string? repoName = "BootstrapAdmin", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
|
||||
{
|
||||
var ret = await GetJsonAsync($"https://gitee.com/{userName}/{repoName}/releases", url => client.HttpClient.GetStringAsync(url), content =>
|
||||
{
|
||||
var regex = Regex.Match(content, $"<a href=\"/{userName}/{repoName}/releases/([^\\s]+)\" target=\"_blank\">", RegexOptions.IgnoreCase);
|
||||
return string.IsNullOrEmpty(content) ? "unknown" : regex.Groups[1].Value;
|
||||
});
|
||||
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Gitee 网站 Builds 信息
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="projName"></param>
|
||||
/// <param name="branchName"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Builds([FromServices]GiteeHttpClient client, [FromQuery]string? userName = "ArgoZhang", [FromQuery]string? projName = "bootstrapadmin", [FromQuery]string? branchName = "master", [FromQuery]string? label = "custom badge", [FromQuery]string? color = "orange")
|
||||
{
|
||||
var ret = await GetJsonAsync($"https://ci.appveyor.com/api/projects/{userName}/{projName}/branch/{branchName}", url => client.HttpClient.GetAsJsonAsync<AppveyorBuildResult>(url, null, new CancellationTokenSource(10000).Token), content =>
|
||||
{
|
||||
return content == null ? "unknown" : content.Build.Version;
|
||||
});
|
||||
return new JsonResult(new { schemaVersion = 1, label, message = ret, color });
|
||||
}
|
||||
|
||||
private async static Task<string> GetJsonAsync<T>(string url, Func<string, Task<T>> requestUrl, Func<T, string> callback)
|
||||
{
|
||||
var ret = "unresponsive";
|
||||
try
|
||||
{
|
||||
var resq = await requestUrl(url);
|
||||
ret = callback(resq);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Log(new NameValueCollection()
|
||||
{
|
||||
["Url"] = url
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class AppveyorBuildResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Appveyor 编译版本实例
|
||||
/// </summary>
|
||||
public Build Build { get; set; } = new Build();
|
||||
}
|
||||
|
||||
private class Build
|
||||
{
|
||||
/// <summary>
|
||||
/// Build 版本信息
|
||||
/// </summary>
|
||||
public string Version { get; set; } = "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
|
||||
#For more information, please see https://aka.ms/containercompat
|
||||
|
||||
FROM microsoft/dotnet:3.1-aspnetcore-runtime-nanoserver-1903 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
|
||||
FROM microsoft/dotnet:3.1-sdk-nanoserver-1903 AS build
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
WORKDIR "src/admin/Bootstrap.Admin"
|
||||
FROM build AS publish
|
||||
RUN dotnet publish -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "Bootstrap.Admin.dll"]
|
|
@ -1,12 +0,0 @@
|
|||
using Bootstrap.Admin.Pages.Shared;
|
||||
|
||||
namespace Bootstrap.Admin.Pages.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// LgbInputText 组件
|
||||
/// </summary>
|
||||
public class LgbInputText : LgbInput<string>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using Bootstrap.Admin.Pages.Components;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class FieldIdentifierExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fieldIdentifier"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDisplayName(this FieldIdentifier fieldIdentifier)
|
||||
{
|
||||
var cacheKey = (Type: fieldIdentifier.Model.GetType(), FieldName: fieldIdentifier.FieldName);
|
||||
if (!DisplayNamesExtensions.TryGetValue(cacheKey, out var dn))
|
||||
{
|
||||
if (BootstrapAdminEditContextDataAnnotationsExtensions.TryGetValidatableProperty(fieldIdentifier, out var propertyInfo))
|
||||
{
|
||||
var displayNameAttribute = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
|
||||
if (displayNameAttribute.Length > 0)
|
||||
{
|
||||
dn = ((DisplayNameAttribute)displayNameAttribute[0]).DisplayName;
|
||||
|
||||
// add display name into cache
|
||||
DisplayNamesExtensions.GetOrAdd((fieldIdentifier.Model.GetType(), fieldIdentifier.FieldName), key => dn);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dn ?? cacheKey.FieldName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using Longbow.Web.SignalR;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR
|
||||
{
|
||||
/// <summary>
|
||||
/// 后台任务消息Hub
|
||||
/// </summary>
|
||||
public class TaskLogHub : SignalRHub
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bootstrap.Security" Version="3.1.0" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.10.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Bootstrap.DataAccess\Bootstrap.DataAccess.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,28 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="3.1.1" />
|
||||
<PackageReference Include="Bootstrap.Security.Mvc" Version="3.1.2-beta01" />
|
||||
<PackageReference Include="Longbow" Version="3.1.0" />
|
||||
<PackageReference Include="Longbow.AlipayAuth" Version="3.1.0" />
|
||||
<PackageReference Include="Longbow.Cache" Version="3.1.2-beta-02" />
|
||||
<PackageReference Include="Longbow.Data" Version="3.1.0" />
|
||||
<PackageReference Include="Longbow.GiteeAuth" Version="3.1.0" />
|
||||
<PackageReference Include="Longbow.GitHubAuth" Version="3.1.0" />
|
||||
<PackageReference Include="Longbow.OAuth" Version="3.1.1" />
|
||||
<PackageReference Include="Longbow.PetaPoco" Version="1.0.2" />
|
||||
<PackageReference Include="Longbow.Security.Cryptography" Version="1.3.0" />
|
||||
<PackageReference Include="Longbow.Tasks" Version="3.1.1" />
|
||||
<PackageReference Include="Longbow.TencentAuth" Version="3.1.1" />
|
||||
<PackageReference Include="Longbow.Web" Version="3.1.1" />
|
||||
<PackageReference Include="Longbow.WeChatAuth" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="3.1.2" />
|
||||
<PackageReference Include="PetaPoco.Extensions" Version="3.1.0" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1 +0,0 @@
|
|||
<lgb><token>d9DQpRTdULRQDYkciXU+R2LrcHSPdJY+9eip5weQTVQfgX6m0sETBCqW5ymQ/A7lrEXkKHXmJpO9rs9xy3rpDX5FJ+wF1o66HROA28Arh26APC55IcL23n+ImKyZPEUHupHvPGZ0rrGPy18A6GTn65IrsfqFS2vyr5yrmnjssgA=</token></lgb>
|
|
@ -0,0 +1,15 @@
|
|||
<Project>
|
||||
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Diagnostics.CodeAnalysis" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
|
||||
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
|
||||
<PackageReference Include="FreeSql.Provider.Sqlite" Version="3.0.100" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using FreeSql;
|
||||
using FreeSql.Internal.Model;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
static class FilterExtensions
|
||||
{
|
||||
public static ISelect<TModel> PageIf<TModel>(this ISelect<TModel> source, int pageIndex, int pageItems, bool isPage) => isPage
|
||||
? source.Page(pageIndex, pageItems)
|
||||
: source;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="filters"></param>
|
||||
/// <returns></returns>
|
||||
public static DynamicFilterInfo ToDynamicFilter(this IEnumerable<IFilterAction> filters)
|
||||
{
|
||||
var ret = new DynamicFilterInfo() { Filters = new List<DynamicFilterInfo>() };
|
||||
|
||||
// 处理 过滤 高级搜索 自定义搜索
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
var item = new DynamicFilterInfo() { Filters = new List<DynamicFilterInfo>() };
|
||||
var actions = filter.GetFilterConditions();
|
||||
foreach (var f in actions)
|
||||
{
|
||||
item.Logic = f.FilterLogic.ToDynamicFilterLogic();
|
||||
item.Filters.Add(new DynamicFilterInfo()
|
||||
{
|
||||
Field = f.FieldKey,
|
||||
Value = f.FieldValue,
|
||||
Operator = f.FilterAction.ToDynamicFilterOperator()
|
||||
});
|
||||
}
|
||||
ret.Filters.Add(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static DynamicFilterLogic ToDynamicFilterLogic(this FilterLogic logic) => logic switch
|
||||
{
|
||||
FilterLogic.And => DynamicFilterLogic.And,
|
||||
_ => DynamicFilterLogic.Or
|
||||
};
|
||||
|
||||
private static DynamicFilterOperator ToDynamicFilterOperator(this FilterAction action) => action switch
|
||||
{
|
||||
FilterAction.Equal => DynamicFilterOperator.Equal,
|
||||
FilterAction.NotEqual => DynamicFilterOperator.NotEqual,
|
||||
FilterAction.Contains => DynamicFilterOperator.Contains,
|
||||
FilterAction.NotContains => DynamicFilterOperator.NotContains,
|
||||
FilterAction.GreaterThan => DynamicFilterOperator.GreaterThan,
|
||||
FilterAction.GreaterThanOrEqual => DynamicFilterOperator.GreaterThanOrEqual,
|
||||
FilterAction.LessThan => DynamicFilterOperator.LessThan,
|
||||
FilterAction.LessThanOrEqual => DynamicFilterOperator.LessThanOrEqual,
|
||||
_ => throw new System.NotSupportedException()
|
||||
};
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Extensions;
|
||||
|
||||
static class FreeSqlExtensions
|
||||
{
|
||||
public static void Mapper(this IFreeSql freeSql)
|
||||
{
|
||||
freeSql.CodeFirst.ConfigEntity<Navigation>(i =>
|
||||
{
|
||||
i.Name("Navigations");
|
||||
i.Property(n => n.HasChildren).IsIgnore(true);
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<User>(i =>
|
||||
{
|
||||
i.Name("Users");
|
||||
i.Property(n => n.NewPassword).IsIgnore(true);
|
||||
i.Property(n => n.ConfirmPassword).IsIgnore(true);
|
||||
i.Property(n => n.Period).IsIgnore(true);
|
||||
i.Property(n => n.IsReset).IsIgnore(true);
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<Group>(i =>
|
||||
{
|
||||
i.Name("Groups");
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<Role>(i =>
|
||||
{
|
||||
i.Name("Roles");
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<Error>(i =>
|
||||
{
|
||||
i.Name("Exceptions");
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<UserRole>(i =>
|
||||
{
|
||||
i.Name("UserRole");
|
||||
i.Property(s => s.ID).IsIgnore(true);
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<NavigationRole>(i =>
|
||||
{
|
||||
i.Name("NavigationRole");
|
||||
i.Property(s => s.ID).IsIgnore(true);
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<UserGroup>(i =>
|
||||
{
|
||||
i.Name("UserGroup");
|
||||
i.Property(s => s.ID).IsIgnore(true);
|
||||
});
|
||||
freeSql.CodeFirst.ConfigEntity<RoleGroup>(i =>
|
||||
{
|
||||
i.Name("RoleGroup");
|
||||
i.Property(s => s.ID).IsIgnore(true);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Extensions;
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using BootstrapBlazor.Components;
|
||||
using FreeSql;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// FreeSql ORM 注入服务扩展类
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注入 FreeSql 数据服务类
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="freeSqlBuilder"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddFreeSql(this IServiceCollection services, Action<IServiceProvider, FreeSqlBuilder> freeSqlBuilder)
|
||||
{
|
||||
services.TryAddSingleton<IFreeSql>(provider =>
|
||||
{
|
||||
var builder = new FreeSqlBuilder();
|
||||
freeSqlBuilder(provider, builder);
|
||||
var instance = builder.Build();
|
||||
instance.Mapper();
|
||||
return instance;
|
||||
});
|
||||
|
||||
// 增加数据服务
|
||||
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
|
||||
|
||||
// 增加业务服务
|
||||
services.AddSingleton<IApp, AppService>();
|
||||
services.AddSingleton<IDict, DictService>();
|
||||
services.AddSingleton<IException, ExceptionService>();
|
||||
services.AddSingleton<IGroup, GroupService>();
|
||||
services.AddSingleton<ILogin, LoginService>();
|
||||
services.AddSingleton<INavigation, NavigationService>();
|
||||
services.AddSingleton<IRole, RoleService>();
|
||||
services.AddSingleton<IUser, UserService>();
|
||||
return services;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
|
||||
class NavigationRole
|
||||
{
|
||||
public string? ID { get; set; }
|
||||
|
||||
public string? NavigationID { get; set; }
|
||||
|
||||
public string? RoleID { get; set; }
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
|
||||
class RoleApp
|
||||
{
|
||||
public string? RoleID { get; set; }
|
||||
|
||||
public string? AppID { get; set; }
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
|
||||
class RoleGroup
|
||||
{
|
||||
public string? ID { get; set; }
|
||||
|
||||
public string? RoleID { get; set; }
|
||||
|
||||
public string? GroupID { get; set; }
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
|
||||
class UserGroup
|
||||
{
|
||||
public string? ID { get; set; }
|
||||
|
||||
public string? UserID { get; set; }
|
||||
|
||||
public string? GroupID { get; set; }
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
|
||||
class UserRole
|
||||
{
|
||||
public string? ID { get; set; }
|
||||
|
||||
public string? UserID { get; set; }
|
||||
|
||||
public string? RoleID { get; set; }
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class AppService : IApp
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public AppService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public List<string> GetAppsByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select AppID from RoleApp where RoleID = @roleId", new { roleId });
|
||||
|
||||
public bool SaveAppsByRoleId(string? roleId, IEnumerable<string> appIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from RoleApp where RoleID = @roleId", new { roleId });
|
||||
FreeSql.Insert(appIds.Select(g => new RoleApp { AppID = g, RoleID = roleId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Extensions;
|
||||
using BootstrapBlazor.Components;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public DefaultDataService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
/// <summary>
|
||||
/// 删除方法
|
||||
/// </summary>
|
||||
/// <param name="models"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
|
||||
{
|
||||
await FreeSql.Delete<TModel>(models).ExecuteAffrowsAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存方法
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="changedType"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
|
||||
{
|
||||
if (changedType == ItemChangedType.Add)
|
||||
{
|
||||
await FreeSql.Insert<TModel>(model).ExecuteAffrowsAsync();
|
||||
}
|
||||
else if (changedType == ItemChangedType.Update)
|
||||
{
|
||||
await FreeSql.Update<TModel>(model).ExecuteAffrowsAsync();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
|
||||
{
|
||||
var ret = new QueryData<TModel>()
|
||||
{
|
||||
IsSorted = true,
|
||||
IsFiltered = true,
|
||||
IsSearch = true,
|
||||
IsAdvanceSearch = option.AdvanceSearchs.Any() || option.CustomerSearchs.Any()
|
||||
};
|
||||
ret.Items = FreeSql.Select<TModel>()
|
||||
.WhereDynamicFilter(option.Searchs.ToDynamicFilter())
|
||||
.WhereDynamicFilter(option.Filters
|
||||
.Concat(option.AdvanceSearchs)
|
||||
.Concat(option.CustomerSearchs)
|
||||
.ToDynamicFilter())
|
||||
.OrderByPropertyNameIf(option.SortOrder != SortOrder.Unset, option.SortName, option.SortOrder == SortOrder.Asc)
|
||||
.Count(out var count)
|
||||
.PageIf(option.PageIndex, option.PageItems, option.IsPage)
|
||||
.ToList();
|
||||
ret.TotalCount = Convert.ToInt32(count);
|
||||
return Task.FromResult(ret);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Longbow.Security.Cryptography;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class DictService : IDict
|
||||
{
|
||||
private const string DictServiceCacheKey = "DictService-GetAll";
|
||||
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
private string? AppId { get; set; }
|
||||
|
||||
public DictService(IFreeSql freeSql, IConfiguration configuration)
|
||||
{
|
||||
FreeSql = freeSql;
|
||||
AppId = configuration.GetValue("AppId", "BA");
|
||||
}
|
||||
|
||||
public bool AuthenticateDemo(string code)
|
||||
{
|
||||
var ret = false;
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var salt = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "授权盐值" && d.Define == EnumDictDefine.System)?.Code;
|
||||
var authCode = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "哈希结果" && d.Define == EnumDictDefine.System)?.Code;
|
||||
if (!string.IsNullOrEmpty(salt))
|
||||
{
|
||||
ret = LgbCryptography.ComputeHash(code, salt) == authCode;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<Dict> GetAll() => CacheManager.GetOrAdd<List<Dict>>(DictServiceCacheKey, entry => FreeSql.Select<Dict>().ToList());
|
||||
|
||||
public Dictionary<string, string> GetApps()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
|
||||
return dicts.Where(d => d.Category == "应用程序").Select(s => new KeyValuePair<string, string>(s.Code, s.Name)).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public int GetCookieExpiresPeriod()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "Cookie保留时长" && d.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(code, out var ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public string GetCurrentLogin()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "登录界面" && d.Define == EnumDictDefine.System)?.Code ?? "Login";
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetLogins()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "系统首页").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(i => i.Value).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public string? GetNotificationUrl(string appId) => GetUrlByName(appId, "系统通知地址");
|
||||
|
||||
public string? GetProfileUrl(string appId) => GetUrlByName(appId, "个人中心地址");
|
||||
|
||||
public string? GetSettingsUrl(string appId) => GetUrlByName(appId, "系统设置地址");
|
||||
|
||||
public Dictionary<string, string> GetThemes()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "网站样式").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public string GetWebFooter()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var title = "网站页脚";
|
||||
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站页脚") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站页脚");
|
||||
title = dict?.Code ?? "网站标题";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public string GetWebTitle()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var title = "网站标题";
|
||||
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站标题") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站标题");
|
||||
title = dict?.Code ?? "网站标题";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public bool IsDemo()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "演示系统" && d.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
return code == "1";
|
||||
}
|
||||
|
||||
public string RetrieveIconFolderPath()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "images/uploder/";
|
||||
}
|
||||
|
||||
private bool SaveDict(Dict dict)
|
||||
{
|
||||
var ret = FreeSql.Update<Dict>().Where(s => s.Category == dict.Category && s.Name == dict.Name).Set(s => s.Code, dict.Code).ExecuteAffrows() > 0;
|
||||
if (ret)
|
||||
{
|
||||
// 更新缓存
|
||||
CacheManager.Clear(DictServiceCacheKey);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveCookieExpiresPeriod(int expiresPeriod) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = expiresPeriod.ToString() });
|
||||
|
||||
public bool SaveDemo(bool isDemo) => SaveDict(new Dict { Category = "网站设置", Name = "演示系统", Define = EnumDictDefine.System, Code = isDemo ? "1" : "0" });
|
||||
|
||||
public bool SaveHealthCheck(bool enable = true) => SaveDict(new Dict { Category = "网站设置", Name = "演示系统", Define = EnumDictDefine.System, Code = enable ? "1" : "0" });
|
||||
|
||||
public bool SaveLogin(string login) => SaveDict(new Dict { Category = "网站设置", Name = "登录界面", Code = login });
|
||||
|
||||
public bool SaveTheme(string theme) => SaveDict(new Dict { Category = "网站设置", Name = "使用样式", Code = theme });
|
||||
|
||||
public bool SaveWebFooter(string footer) => SaveDict(new Dict { Category = "网站设置", Name = "网站页脚", Code = footer });
|
||||
|
||||
public bool SaveWebTitle(string title) => SaveDict(new Dict { Category = "网站设置", Name = "网站标题", Code = title });
|
||||
|
||||
private string? GetUrlByName(string appId, string dictName)
|
||||
{
|
||||
string? url = null;
|
||||
var dicts = GetAll();
|
||||
var appName = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == appId && d.Define == EnumDictDefine.System)?.Name;
|
||||
if (!string.IsNullOrEmpty(appName))
|
||||
{
|
||||
url = dicts.FirstOrDefault(d => d.Category == appName && d.Name == dictName && d.Define == EnumDictDefine.Customer)?.Code;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过指定 appId 获得配置首页地址
|
||||
/// </summary>
|
||||
/// <param name="appId"></param>
|
||||
/// <returns></returns>
|
||||
public string? GetHomeUrlByAppId(string appId)
|
||||
{
|
||||
string? url = null;
|
||||
var dicts = GetAll();
|
||||
// appId 为空时读取前台列表取第一个应用作为默认应用
|
||||
url = dicts.FirstOrDefault(d => d.Category == "应用首页" && d.Name.Equals(appId, StringComparison.OrdinalIgnoreCase) && d.Define == EnumDictDefine.System)?.Code;
|
||||
return url;
|
||||
}
|
||||
|
||||
public bool SavDefaultApp(bool enabled)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetEnableDefaultApp()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetIconFolderPath()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetDefaultIcon()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class ExceptionService : IException
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public ExceptionService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public (IEnumerable<Error> Items, int ItemsCount) GetAll(string? searchText, ExceptionFilter filter, int pageIndex, int pageItems, List<string> sortList)
|
||||
{
|
||||
var items = FreeSql.Select<Error>();
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
items.Where($"ErrorPage Like %@searchText% or Message Like %@searchText% or StackTrace Like %@searchText%", new { searchText });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.Category))
|
||||
{
|
||||
items.Where("Category = @Category", new { filter.Category });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.UserId))
|
||||
{
|
||||
items.Where("UserId Like %@UserId%", new { filter.UserId });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.ErrorPage))
|
||||
{
|
||||
items.Where("ErrorPage Like %{ErrorPage}%", new { filter.ErrorPage });
|
||||
}
|
||||
|
||||
items.Where("LogTime >= @Star and LogTime <= @End", new { filter.Star, filter.End });
|
||||
|
||||
if (sortList.Any())
|
||||
{
|
||||
items.OrderBy(string.Join(", ", sortList));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.OrderBy("UserId, ErrorPage, Logtime desc");
|
||||
}
|
||||
var errors = items.Count(out var count).Page(pageIndex, pageItems).ToList();
|
||||
|
||||
return (errors, Convert.ToInt32(count));
|
||||
}
|
||||
|
||||
public bool Log(Error exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
FreeSql.Insert(exception).ExecuteAffrows();
|
||||
}
|
||||
catch { }
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class GroupService : IGroup
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public GroupService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public List<Group> GetAll() => FreeSql.Select<Group>().ToList();
|
||||
|
||||
public List<string> GetGroupsByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select GroupID from RoleGroup where RoleID = @roleId", new { roleId });
|
||||
|
||||
public List<string> GetGroupsByUserId(string? userId) => FreeSql.Ado.Query<string>("select GroupID from UserGroup where UserID = @userId", new { userId });
|
||||
|
||||
public bool SaveGroupsByRoleId(string? roleId, IEnumerable<string> groupIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from RoleGroup where RoleID = @roleId", new { roleId });
|
||||
FreeSql.Insert(groupIds.Select(g => new RoleGroup { GroupID = g, RoleID = roleId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveGroupsByUserId(string? userId, IEnumerable<string> groupIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from UserGroup where UserID = @userId", new { userId });
|
||||
FreeSql.Insert(groupIds.Select(g => new UserGroup { GroupID = g, UserID = userId }));
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class LoginService : ILogin
|
||||
{
|
||||
public Task<bool> Log(string userName, bool result)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class NavigationService : INavigation
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public NavigationService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public List<Navigation> GetAllMenus(string userName)
|
||||
{
|
||||
return FreeSql.Ado.Query<Navigation>($"select n.ID, n.ParentId, n.Name, n.[order], n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application, ln.Name as ParentName from Navigations n inner join Dicts d on n.Category = d.Code and d.Category = @Category and d.Define = @Define left join Navigations ln on n.ParentId = ln.ID inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = @UserName union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = @UserName union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = @UserName and r.RoleName = @RoleName)) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.[order]", new { UserName = userName, Category = "菜单", RoleName = "Administrators", Define = EnumDictDefine.System });
|
||||
}
|
||||
|
||||
public List<string> GetMenusByRoleId(string? roleId) => FreeSql.Ado.Query<string>("select NavigationID from NavigationRole where RoleID = @roleId", new { roleId });
|
||||
|
||||
public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from NavigationRole where RoleID = @roleId", new { roleId });
|
||||
FreeSql.Insert(menuIds.Select(g => new NavigationRole { NavigationID = g, RoleID = roleId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class RoleService : IRole
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public RoleService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public List<Role> GetAll()
|
||||
{
|
||||
return FreeSql.Select<Role>().ToList();
|
||||
}
|
||||
|
||||
public List<string> GetRolesByGroupId(string? groupId) => FreeSql.Ado.Query<string>("select RoleID from RoleGroup where GroupID = @groupId", new { groupId });
|
||||
|
||||
public List<string> GetRolesByMenuId(string? menuId) => FreeSql.Ado.Query<string>("select RoleID from NavigationRole where NavigationID = @menuId", new { menuId });
|
||||
|
||||
public List<string> GetRolesByUserId(string? userId) => FreeSql.Ado.Query<string>("select RoleID from UserRole where UserID = @userId", new { userId });
|
||||
|
||||
public bool SaveRolesByGroupId(string? groupId, IEnumerable<string> roleIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from RoleGroup where GroupID = @groupId", new { groupId });
|
||||
FreeSql.Insert(roleIds.Select(g => new RoleGroup { RoleID = g, GroupID = groupId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveRolesByMenuId(string? menuId, IEnumerable<string> roleIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from NavigationRole where NavigationID = @menuId", new { menuId });
|
||||
FreeSql.Insert(roleIds.Select(g => new NavigationRole { RoleID = g, NavigationID = menuId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveRolesByUserId(string? userId, IEnumerable<string> roleIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from UserRole where UserID = @userId", new { userId });
|
||||
FreeSql.Insert(roleIds.Select(g => new UserRole { RoleID = g, UserID = userId })).ExecuteAffrows();
|
||||
});
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.FreeSql.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Longbow.Security.Cryptography;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.FreeSql.Service;
|
||||
|
||||
class UserService : IUser
|
||||
{
|
||||
private IFreeSql FreeSql { get; }
|
||||
|
||||
public UserService(IFreeSql freeSql) => FreeSql = freeSql;
|
||||
|
||||
public bool Authenticate(string userName, string password)
|
||||
{
|
||||
var user = FreeSql.Select<User>().Where(s => s.ApprovedTime != null && s.UserName == userName).ToOne(s => new User
|
||||
{
|
||||
DisplayName = s.DisplayName,
|
||||
PassSalt = s.PassSalt,
|
||||
Password = s.Password
|
||||
});
|
||||
|
||||
var isAuth = false;
|
||||
if (user != null && !string.IsNullOrEmpty(user.PassSalt))
|
||||
{
|
||||
isAuth = user.Password == LgbCryptography.ComputeHash(password, user.PassSalt);
|
||||
}
|
||||
return isAuth;
|
||||
}
|
||||
|
||||
public List<User> GetAll()
|
||||
{
|
||||
return FreeSql.Select<User>().ToList();
|
||||
}
|
||||
|
||||
public List<string> GetApps(string userName)
|
||||
{
|
||||
return FreeSql.Ado.Query<string>($"select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @UserName union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @UserName) r on ra.RoleId = r.ID union select Code from Dicts where Category = @Category and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = @UserName and r.RoleName = @RoleName union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = @UserName and r.RoleName = @RoleName)", new { UserName = userName, Category = "应用程序", RoleName = "Administrators" }).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过用户名获得指定的前台 AppId
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public string? GetAppIdByUserName(string userName) => FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne(s => s.App);
|
||||
|
||||
public string? GetDisplayName(string? userName)
|
||||
{
|
||||
return FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne(s => s.DisplayName);
|
||||
}
|
||||
|
||||
public List<string> GetRoles(string userName)
|
||||
{
|
||||
return FreeSql.Ado.Query<string>($"select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = @userName union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join Groups g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = @userName", new { userName }).ToList();
|
||||
}
|
||||
|
||||
public User? GetUserByUserName(string? userName) => string.IsNullOrEmpty(userName) ? null : FreeSql.Select<User>().Where(i => i.UserName == userName).ToOne();
|
||||
|
||||
public List<string> GetUsersByGroupId(string? groupId)
|
||||
{
|
||||
return FreeSql.Ado.Query<string>("select UserID from UserGroup where GroupID = @groupId", new { groupId }).ToList();
|
||||
}
|
||||
|
||||
public List<string> GetUsersByRoleId(string? roleId)
|
||||
{
|
||||
return FreeSql.Ado.Query<string>("select UserID from UserRole where RoleID = @roleId", new { roleId }).ToList();
|
||||
}
|
||||
|
||||
public bool SaveUser(string userName, string displayName, string password)
|
||||
{
|
||||
var salt = LgbCryptography.GenerateSalt();
|
||||
var pwd = LgbCryptography.ComputeHash(password, salt);
|
||||
var user = FreeSql.Select<User>().Where(s => s.UserName == userName).ToOne();
|
||||
bool ret = default;
|
||||
if (user == null)
|
||||
{
|
||||
// 开始事务
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
user = new User()
|
||||
{
|
||||
Id = "0",
|
||||
ApprovedBy = "System",
|
||||
ApprovedTime = DateTime.Now,
|
||||
DisplayName = "手机用户",
|
||||
UserName = userName,
|
||||
Icon = "default.jpg",
|
||||
Description = "系统默认创建",
|
||||
PassSalt = salt,
|
||||
Password = pwd
|
||||
};
|
||||
FreeSql.Insert(user).ExecuteAffrows();
|
||||
// 授权 Default 角色
|
||||
FreeSql.Ado.ExecuteNonQuery("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = @userName", new { userName });
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
user.DisplayName = displayName;
|
||||
user.PassSalt = salt;
|
||||
user.Password = pwd;
|
||||
FreeSql.Update<User>(user);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveUsersByGroupId(string? groupId, IEnumerable<string> userIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from UserGroup where GroupId = @groupId", new { groupId });
|
||||
FreeSql.Insert(userIds.Select(g => new UserGroup { UserID = g, GroupID = groupId })).ExecuteAffrows();
|
||||
});
|
||||
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveUsersByRoleId(string? roleId, IEnumerable<string> userIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
FreeSql.Ado.ExecuteNonQuery("delete from UserRole where RoleID = @roleId", new { roleId });
|
||||
FreeSql.Insert(userIds.Select(g => new UserRole { UserID = g, RoleID = roleId })).ExecuteAffrows();
|
||||
ret = true;
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="phone"></param>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="appId"></param>
|
||||
/// <param name="roles"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
var salt = LgbCryptography.GenerateSalt();
|
||||
var pwd = LgbCryptography.ComputeHash(code, salt);
|
||||
var user = FreeSql.Select<User>().Where(s => s.UserName == phone).ToOne();
|
||||
if (user == null)
|
||||
{
|
||||
FreeSql.Transaction(() =>
|
||||
{
|
||||
user = new User()
|
||||
{
|
||||
ApprovedBy = "Mobile",
|
||||
ApprovedTime = DateTime.Now,
|
||||
DisplayName = "手机用户",
|
||||
UserName = phone,
|
||||
Icon = "default.jpg",
|
||||
Description = "手机用户",
|
||||
PassSalt = salt,
|
||||
Password = LgbCryptography.ComputeHash(code, salt),
|
||||
App = appId
|
||||
};
|
||||
FreeSql.Insert(user).ExecuteAffrows();
|
||||
// Authorization
|
||||
var roleIds = FreeSql.Ado.Query<string>("select ID from Roles where RoleName in (@roles)", new { roles });
|
||||
FreeSql.Insert(roleIds.Select(g => new UserRole { RoleID = g, UserID = user.Id }));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
user.PassSalt = salt;
|
||||
user.Password = pwd;
|
||||
FreeSql.Update<User>(user).ExecuteAffrows();
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveApp(string userName, string app)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ChangePassword(string userName, string password, string newPassword)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SaveDisplayName(string userName, string displayName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SaveTheme(string userName, string theme)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SaveLogo(string userName, string? logo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.0.5.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootStarpAdmin.DataAccess.SqlSugar.Service;
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// FreeSql ORM 注入服务扩展类
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注入 FreeSql 数据服务类
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="sqlSugarBuilder"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddSqlSugar(this IServiceCollection services, Action<IServiceProvider, ConnectionConfig> sqlSugarBuilder)
|
||||
{
|
||||
services.TryAddSingleton<ISqlSugarClient>(provider =>
|
||||
{
|
||||
var builder = new ConnectionConfig();
|
||||
builder.IsAutoCloseConnection = true;
|
||||
sqlSugarBuilder(provider, builder);
|
||||
return new SqlSugarClient(builder);
|
||||
});
|
||||
|
||||
// 增加数据服务
|
||||
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
|
||||
|
||||
// 增加业务服务
|
||||
//services.AddSingleton<IApp, AppService>();
|
||||
//services.AddSingleton<IDict, DictService>();
|
||||
//services.AddSingleton<IException, ExceptionService>();
|
||||
//services.AddSingleton<IGroup, GroupService>();
|
||||
//services.AddSingleton<ILogin, LoginService>();
|
||||
//services.AddSingleton<INavigation, NavigationService>();
|
||||
//services.AddSingleton<IRole, RoleService>();
|
||||
//services.AddSingleton<IUser, UserService>();
|
||||
return services;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.SqlSugar.Extensions;
|
||||
|
||||
static class SqlSugarExtensions
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using SqlSugar;
|
||||
|
||||
namespace BootStarpAdmin.DataAccess.SqlSugar.Service;
|
||||
|
||||
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
|
||||
{
|
||||
private ISqlSugarClient Client { get; }
|
||||
|
||||
public DefaultDataService(ISqlSugarClient client) => Client = client;
|
||||
|
||||
/// <summary>
|
||||
/// 删除方法
|
||||
/// </summary>
|
||||
/// <param name="models"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
|
||||
{
|
||||
await Client.Deleteable<TModel>(models).ExecuteCommandAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存方法
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="changedType"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
|
||||
{
|
||||
if (changedType == ItemChangedType.Add)
|
||||
{
|
||||
await Client.Insertable<TModel>(model).ExecuteCommandAsync();
|
||||
}
|
||||
else if (changedType == ItemChangedType.Update)
|
||||
{
|
||||
await Client.Updateable<TModel>(model).ExecuteCommandAsync();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
|
||||
{
|
||||
var ret = new QueryData<TModel>()
|
||||
{
|
||||
IsSorted = true,
|
||||
IsFiltered = true,
|
||||
IsSearch = true,
|
||||
IsAdvanceSearch = option.AdvanceSearchs.Any() || option.CustomerSearchs.Any()
|
||||
};
|
||||
if (option.IsPage)
|
||||
{
|
||||
var count = 0;
|
||||
ret.Items = Client.Queryable<TModel>()
|
||||
.ToPageList(option.PageIndex, option.PageItems, ref count);
|
||||
ret.TotalCount = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.Items = Client.Queryable<TModel>()
|
||||
.ToList();
|
||||
}
|
||||
return Task.FromResult(ret);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching.Services;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace BootstrapAdmin.Caching;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存管理类
|
||||
/// </summary>
|
||||
public static class CacheManager
|
||||
{
|
||||
[NotNull]
|
||||
private static ICacheManager? Cache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 由服务调用
|
||||
/// </summary>
|
||||
/// <param name="cache"></param>
|
||||
internal static void Init(ICacheManager cache) => Cache = cache;
|
||||
|
||||
/// <summary>
|
||||
/// 获得或者新建数据
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="valueFactory"></param>
|
||||
/// <returns></returns>
|
||||
public static TItem GetOrAdd<TItem>(string key, Func<ICacheEntry, TItem> valueFactory) => Cache.GetOrAdd(key, valueFactory);
|
||||
|
||||
/// <summary>
|
||||
/// 清除指定键值缓存项
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public static void Clear(string? key = null) => Cache.Clear(key);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.Caching.Services;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注入 ICacheManager 服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddCacheManager(this IServiceCollection services)
|
||||
{
|
||||
services.AddMemoryCache();
|
||||
services.TryAddSingleton<ICacheManager>(provider =>
|
||||
{
|
||||
var cache = provider.GetRequiredService<IMemoryCache>();
|
||||
var cacheManager = new DefaultCacheManager(cache);
|
||||
CacheManager.Init(cacheManager);
|
||||
return cacheManager;
|
||||
});
|
||||
return services;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace BootstrapAdmin.Caching;
|
||||
|
||||
/// <summary>
|
||||
/// CacheManager 接口类
|
||||
/// </summary>
|
||||
public interface ICacheManager
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
T GetOrAdd<T>(string key, Func<ICacheEntry, T> factory);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> factory);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
void Clear(string? key = null);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace BootstrapAdmin.Caching.Services;
|
||||
|
||||
class DefaultCacheManager : ICacheManager
|
||||
{
|
||||
[NotNull]
|
||||
private IMemoryCache? Cache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DefaultCacheManager(IMemoryCache cache) => Cache = cache;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
public T GetOrAdd<T>(string key, Func<ICacheEntry, T> factory) => Cache.GetOrCreate(key, entry =>
|
||||
{
|
||||
HandlerEntry(key, entry);
|
||||
return factory(entry);
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
public Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> factory) => Cache.GetOrCreate(key, entry =>
|
||||
{
|
||||
HandlerEntry(key, entry);
|
||||
return factory(entry);
|
||||
});
|
||||
|
||||
private static void HandlerEntry(string key, ICacheEntry entry, IChangeToken? token = null)
|
||||
{
|
||||
if (token != null)
|
||||
{
|
||||
entry.AddExpirationToken(token);
|
||||
}
|
||||
|
||||
// 内置缓存策略 缓存相对时间 10 分钟
|
||||
if (entry.AbsoluteExpiration == null && entry.SlidingExpiration == null && !entry.ExpirationTokens.Any())
|
||||
{
|
||||
#if DEBUG
|
||||
entry.SlidingExpiration = TimeSpan.FromMilliseconds(100);
|
||||
#else
|
||||
entry.SlidingExpiration = TimeSpan.FromMinutes(10);
|
||||
#endif
|
||||
}
|
||||
entry.RegisterPostEvictionCallback((key, value, reason, state) =>
|
||||
{
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void Clear(string? key)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
Cache.Remove(key);
|
||||
}
|
||||
else if (Cache is MemoryCache c)
|
||||
{
|
||||
c.Compact(100);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
|
||||
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BootstrapAdminContext : DbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public BootstrapAdminContext(DbContextOptions<BootstrapAdminContext> options) : base(options)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<Dict>? Dicts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<User>? Users { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<Role>? Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<UserRole>? UserRole { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<Navigation>? Navigations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<NavigationRole>? NavigationRole { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<Group>? Groups { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<UserGroup>? UserGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<RoleGroup>? RoleGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public DbSet<RoleApp>? RoleApp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="modelBuilder"></param>
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
EntityConfiguration.Configure(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Microsoft.EntityFrameworkCore.ValueGeneration;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class EntityConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
public static void Configure(this ModelBuilder builder)
|
||||
{
|
||||
var converter = new ValueConverter<string?, int>(
|
||||
v => Convert.ToInt32(v),
|
||||
v => v.ToString(),
|
||||
new ConverterMappingHints(valueGeneratorFactory: (p, t) => new GuidStringGenerator()));
|
||||
|
||||
builder.Entity<User>().ToTable("Users");
|
||||
builder.Entity<User>().Ignore(u => u.Period);
|
||||
builder.Entity<User>().Ignore(u => u.NewPassword);
|
||||
builder.Entity<User>().Ignore(u => u.ConfirmPassword);
|
||||
builder.Entity<User>().Ignore(u => u.IsReset);
|
||||
builder.Entity<User>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
|
||||
|
||||
builder.Entity<Role>().ToTable("Roles");
|
||||
builder.Entity<Role>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
|
||||
|
||||
builder.Entity<Navigation>().ToTable("Navigations");
|
||||
builder.Entity<Navigation>().Property(s => s.Id).HasConversion(converter!).ValueGeneratedOnAdd();
|
||||
builder.Entity<Navigation>().Ignore(s => s.HasChildren);
|
||||
|
||||
builder.Entity<Dict>().ToTable("Dicts");
|
||||
builder.Entity<Dict>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
|
||||
|
||||
builder.Entity<Group>().ToTable("Groups");
|
||||
builder.Entity<Group>().Property(s => s.Id).HasConversion(converter).ValueGeneratedOnAdd();
|
||||
|
||||
builder.Entity<Error>().ToTable("Exceptions");
|
||||
builder.Entity<LoginLog>().ToTable("LoginLogs");
|
||||
builder.Entity<Trace>().ToTable("Traces");
|
||||
}
|
||||
}
|
||||
|
||||
internal class GuidStringGenerator : ValueGenerator
|
||||
{
|
||||
|
||||
public override bool GeneratesTemporaryValues => false;
|
||||
|
||||
protected override object? NextValue(EntityEntry entry) => "0";
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.EFCore;
|
||||
using BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ServicesExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="optionConfigure"></param>
|
||||
/// <param name="lifetime"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddEFCoreDataAccessServices(this IServiceCollection services, Action<IServiceProvider, DbContextOptionsBuilder> optionConfigure, ServiceLifetime lifetime = ServiceLifetime.Singleton)
|
||||
{
|
||||
services.AddDbContextFactory<BootstrapAdminContext>(optionConfigure, lifetime);
|
||||
|
||||
services.AddServices();
|
||||
return services;
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="optionConfigure"></param>
|
||||
/// <param name="lifetime"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddEFCoreDataAccessServices(this IServiceCollection services, Action<DbContextOptionsBuilder> optionConfigure, ServiceLifetime lifetime = ServiceLifetime.Singleton)
|
||||
{
|
||||
services.AddDbContextFactory<BootstrapAdminContext>(optionConfigure, lifetime);
|
||||
|
||||
services.AddServices();
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddServices(this IServiceCollection services)
|
||||
{
|
||||
// 增加数据服务
|
||||
services.AddSingleton(typeof(IDataService<>), typeof(DefaultDataService<>));
|
||||
// 增加缓存服务
|
||||
services.AddCacheManager();
|
||||
services.AddSingleton<INavigation, NavigationService>();
|
||||
services.AddSingleton<IDict, DictService>();
|
||||
services.AddSingleton<IUser, UserService>();
|
||||
services.AddSingleton<IRole, RoleService>();
|
||||
services.AddSingleton<IGroup, GroupService>();
|
||||
services.AddSingleton<ILogin, LoginService>();
|
||||
return services;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class NavigationRole
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? NavigationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? RoleId { get; set; }
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RoleApp
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? AppID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? RoleID { get; set; }
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RoleGroup
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? RoleId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? GroupId { get; set; }
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UserGroup
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? GroupId { get; set; }
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UserRole
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? RoleId { get; set; }
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AppService : IApp
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dbFactory"></param>
|
||||
public AppService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public List<string> GetAppsByRoleId(string? roleId)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return dbcontext.RoleApp.Where(s => s.RoleID == roleId).Select(s => s.AppID!).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <param name="appIds"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveAppsByRoleId(string? roleId, IEnumerable<string> appIds)
|
||||
{
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from RoleApp where RoleID = {0}", roleId!);
|
||||
dbcontext.AddRange(appIds.Select(g => new RoleApp { AppID = g, RoleID = roleId }));
|
||||
ret = dbcontext.SaveChanges() > 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
/// EFCore ORM 的 IDataService 接口实现
|
||||
/// </summary>
|
||||
class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class, new()
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public DefaultDataService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
|
||||
|
||||
/// <summary>
|
||||
/// 删除方法
|
||||
/// </summary>
|
||||
/// <param name="models"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAsync(IEnumerable<TModel> models)
|
||||
{
|
||||
// 通过模型获取主键列数据
|
||||
// 支持批量删除
|
||||
var context = DbFactory.CreateDbContext();
|
||||
context.RemoveRange(models);
|
||||
return await context.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存方法
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <param name="changedType"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
|
||||
{
|
||||
var context = DbFactory.CreateDbContext();
|
||||
if (changedType == ItemChangedType.Add)
|
||||
{
|
||||
context.Entry(model).State = EntityState.Added;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Entry(model).State = EntityState.Modified;
|
||||
}
|
||||
return await context.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询方法
|
||||
/// </summary>
|
||||
/// <param name="option"></param>
|
||||
/// <returns></returns>
|
||||
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions option)
|
||||
{
|
||||
var context = DbFactory.CreateDbContext();
|
||||
var ret = new QueryData<TModel>()
|
||||
{
|
||||
IsSorted = true,
|
||||
IsFiltered = true,
|
||||
IsSearch = true
|
||||
};
|
||||
|
||||
var filters = option.Filters.Concat(option.Searchs).Concat(option.CustomerSearchs);
|
||||
if (option.IsPage)
|
||||
{
|
||||
var items = context.Set<TModel>()
|
||||
.Where(filters.GetFilterLambda<TModel>(), filters.Any())
|
||||
.Sort(option.SortName!, option.SortOrder, !string.IsNullOrEmpty(option.SortName))
|
||||
.Count(out var count)
|
||||
.Page((option.PageIndex - 1) * option.PageItems, option.PageItems);
|
||||
|
||||
ret.TotalCount = count;
|
||||
ret.Items = items;
|
||||
}
|
||||
else
|
||||
{
|
||||
var items = context.Set<TModel>()
|
||||
.Where(filters.GetFilterLambda<TModel>(), filters.Any())
|
||||
.Sort(option.SortName!, option.SortOrder, !string.IsNullOrEmpty(option.SortName))
|
||||
.Count(out var count);
|
||||
ret.TotalCount = count;
|
||||
ret.Items = items;
|
||||
}
|
||||
return Task.FromResult(ret);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,465 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using BootstrapBlazor.Components;
|
||||
using Longbow.Security.Cryptography;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
class DictService : IDict
|
||||
{
|
||||
private const string DictServiceCacheKey = "DictService-GetAll";
|
||||
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
private string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="configuration"></param>
|
||||
public DictService(IDbContextFactory<BootstrapAdminContext> factory, IConfiguration configuration)
|
||||
{
|
||||
DbFactory = factory;
|
||||
AppId = configuration.GetValue("AppId", "BA");
|
||||
}
|
||||
|
||||
public List<Dict> GetAll()
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return CacheManager.GetOrAdd(DictServiceCacheKey, entry => context.Dicts.AsNoTracking().ToList());
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetApps()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "应用程序").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetLogins()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "系统首页").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetThemes()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "网站样式").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public string GetWebFooter()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var title = "网站页脚";
|
||||
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站页脚") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站页脚");
|
||||
title = dict?.Code ?? "网站标题";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public string GetWebTitle()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var title = "网站标题";
|
||||
var name = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == AppId)?.Name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
var dict = dicts.FirstOrDefault(d => d.Category == name && d.Name == "网站标题") ?? dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "网站标题");
|
||||
title = dict?.Code ?? "网站标题";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public bool IsDemo()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "演示系统" && d.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
return code == "1";
|
||||
}
|
||||
|
||||
public bool SaveDemo(bool isDemo) => SaveDict(new Dict
|
||||
{
|
||||
Category = "网站设置",
|
||||
Name = "演示系统",
|
||||
Code = isDemo ? "1" : "0",
|
||||
Define = EnumDictDefine.System
|
||||
});
|
||||
|
||||
public bool AuthenticateDemo(string code)
|
||||
{
|
||||
var ret = false;
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var salt = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "授权盐值" && d.Define == EnumDictDefine.System)?.Code;
|
||||
var authCode = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "哈希结果" && d.Define == EnumDictDefine.System)?.Code;
|
||||
if (!string.IsNullOrEmpty(salt))
|
||||
{
|
||||
ret = LgbCryptography.ComputeHash(code, salt) == authCode;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveHealthCheck(bool enable = true) => SaveDict(new Dict
|
||||
{
|
||||
Category = "网站设置",
|
||||
Name = "健康检查",
|
||||
Code = enable ? "1" : "0",
|
||||
Define = EnumDictDefine.System
|
||||
});
|
||||
|
||||
public int GetCookieExpiresPeriod()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "Cookie保留时长" && d.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(code, out var ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public string GetCurrentLogin()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "登录界面" && d.Define == EnumDictDefine.System)?.Code ?? "Login";
|
||||
}
|
||||
|
||||
public bool SaveLogin(string login) => SaveDict(new Dict { Category = "网站设置", Name = "登录界面", Code = login });
|
||||
|
||||
public bool SaveTheme(string theme) => SaveDict(new Dict { Category = "网站设置", Name = "使用样式", Code = theme });
|
||||
|
||||
public bool SaveWebTitle(string title) => SaveDict(new Dict { Category = "网站设置", Name = "网站标题", Code = title });
|
||||
|
||||
public bool SaveWebFooter(string footer) => SaveDict(new Dict { Category = "网站设置", Name = "网站页脚", Code = footer });
|
||||
|
||||
public bool SaveCookieExpiresPeriod(int expiresPeriod) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = expiresPeriod.ToString() });
|
||||
|
||||
public string? GetProfileUrl(string appId) => GetUrlByName(appId, "个人中心地址");
|
||||
|
||||
public string? GetSettingsUrl(string appId) => GetUrlByName(appId, "系统设置地址");
|
||||
|
||||
public string? GetNotificationUrl(string appId) => GetUrlByName(appId, "系统通知地址");
|
||||
|
||||
public string? GetIpLocatorName()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP地理位置接口" && s.Define == EnumDictDefine.System)?.Code;
|
||||
}
|
||||
|
||||
public string? GetIpLocatorUrl(string? name)
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return string.IsNullOrWhiteSpace(name) ? null : dicts.FirstOrDefault(s => s.Category == "地理位置" && s.Name == name && s.Define == EnumDictDefine.System)?.Code;
|
||||
}
|
||||
|
||||
public bool SavDefaultApp(bool enabled) => SaveDict(new Dict
|
||||
{
|
||||
Category = "网站设置",
|
||||
Name = "默认应用程序",
|
||||
Code = enabled ? "1" : "0",
|
||||
Define = EnumDictDefine.System
|
||||
});
|
||||
|
||||
public string GetIconFolderPath()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Name == "头像路径" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "/images/uploder/";
|
||||
}
|
||||
|
||||
public string GetDefaultIcon()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Name == "头像文件" && d.Category == "头像地址" && d.Define == EnumDictDefine.System)?.Code ?? "default.jpg";
|
||||
}
|
||||
|
||||
public string? GetHomeUrlByAppId(string appId)
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(d => d.Category == "应用首页" && d.Name.Equals(appId, StringComparison.OrdinalIgnoreCase) && d.Define == EnumDictDefine.System)?.Code;
|
||||
}
|
||||
|
||||
public bool GetEnableDefaultApp()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var code = dicts.FirstOrDefault(d => d.Category == "网站设置" && d.Name == "默认应用程序")?.Code ?? "0";
|
||||
return code == "1";
|
||||
}
|
||||
|
||||
public bool GetAppSiderbar()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "侧边栏状态" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppSiderbar(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "侧边栏状态", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAppTitle()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "卡片标题状态" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppTitle(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "卡片标题状态", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAppFixHeader()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "固定表头" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppFixHeader(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "固定表头", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAppHealthCheck()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "健康检查" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppHealthCheck(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "健康检查", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAppMobileLogin()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "短信验证码登录" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppMobileLogin(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "短信验证码登录", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAppOAuthLogin()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "OAuth 认证登录" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAppOAuthLogin(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "OAuth 认证登录", Code = value ? "1" : "0" });
|
||||
|
||||
public bool GetAutoLockScreen()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "自动锁屏" && s.Define == EnumDictDefine.System)?.Code == "1";
|
||||
}
|
||||
|
||||
public bool SaveAutoLockScreen(bool value) => SaveDict(new Dict { Category = "网站设置", Name = "自动锁屏", Code = value ? "1" : "0" });
|
||||
|
||||
public int GetAutoLockScreenInterval()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "自动锁屏时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveAutoLockScreenInterval(int value) => SaveDict(new Dict { Category = "网站设置", Name = "自动锁屏时长", Code = value.ToString() });
|
||||
|
||||
public Dictionary<string, string> GetIpLocators()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(d => d.Category == "地理位置服务").Select(d => new KeyValuePair<string, string>(d.Code, d.Name)).OrderBy(i => i.Value).ToDictionary(i => i.Key, i => i.Value);
|
||||
}
|
||||
|
||||
public string? GetIpLocator()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP地理位置接口" && s.Define == EnumDictDefine.System)?.Code;
|
||||
}
|
||||
|
||||
public bool SaveCurrentIp(string value) => SaveDict(new Dict { Category = "网站设置", Name = "IP地理位置接口", Code = value });
|
||||
|
||||
public int GetCookieExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "Cookie保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SaveCookieExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "Cookie保留时长", Code = value.ToString() });
|
||||
|
||||
public int GetExceptionExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "程序异常保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret; ;
|
||||
}
|
||||
|
||||
public bool SaveExceptionExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "程序异常保留时长", Code = value.ToString() });
|
||||
|
||||
public int GetOperateExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "操作日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret; ;
|
||||
}
|
||||
|
||||
public bool SaveOperateExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "操作日志保留时长", Code = value.ToString() });
|
||||
|
||||
public int GetLoginExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "登录日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret; ;
|
||||
}
|
||||
|
||||
public bool SaveLoginExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "登录日志保留时长", Code = value.ToString() });
|
||||
|
||||
public int GetAccessExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "访问日志保留时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret; ;
|
||||
}
|
||||
|
||||
public bool SaveAccessExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "访问日志保留时长", Code = value.ToString() });
|
||||
|
||||
public int GetIPCacheExpired()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
var value = dicts.FirstOrDefault(s => s.Category == "网站设置" && s.Name == "IP请求缓存时长" && s.Define == EnumDictDefine.System)?.Code ?? "0";
|
||||
_ = int.TryParse(value, out var ret);
|
||||
return ret; ;
|
||||
}
|
||||
|
||||
public bool SaveIPCacheExpired(int value) => SaveDict(new Dict { Category = "网站设置", Name = "IP请求缓存时长", Code = value.ToString() });
|
||||
|
||||
public Dictionary<string, string>? GetClients()
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(s => s.Category == "应用程序" && s.Code != "BA").ToDictionary(s => s.Name, s => s.Code);
|
||||
}
|
||||
|
||||
public string GetClientUrl(string name)
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Where(s => s.Category == "应用首页" && s.Name == name).FirstOrDefault()?.Code ?? "";
|
||||
}
|
||||
|
||||
public bool ExistsAppId(string appId)
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return dicts.Exists(s => s.Category == "应用程序" && s.Code == appId);
|
||||
}
|
||||
|
||||
public bool SaveClient(ClientApp client)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
if (!string.IsNullOrEmpty(client.AppId))
|
||||
{
|
||||
DeleteClient(client.AppId);
|
||||
try
|
||||
{
|
||||
var items = new List<Dict>()
|
||||
{
|
||||
new Dict { Category = "应用程序", Name = client.AppName, Code = client.AppId, Define = EnumDictDefine.System },
|
||||
new Dict { Category = "应用首页", Name = client.AppId, Code = client.HomeUrl, Define = EnumDictDefine.System },
|
||||
new Dict { Category = client.AppId, Name = "网站页脚", Code = client.Footer, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "网站标题", Code = client.Title, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "favicon", Code = client.Favicon, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "网站图标", Code = client.Icon, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "个人中心地址", Code = client.ProfileUrl, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "系统设置地址", Code = client.SettingsUrl, Define = EnumDictDefine.Customer },
|
||||
new Dict { Category = client.AppId, Name = "系统通知地址", Code = client.NotificationUrl, Define = EnumDictDefine.Customer }
|
||||
};
|
||||
dbcontext.AddRange(items);
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (DbException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ClientApp GetClient(string appId)
|
||||
{
|
||||
var dicts = GetAll();
|
||||
return new ClientApp()
|
||||
{
|
||||
AppId = appId,
|
||||
AppName = dicts.FirstOrDefault(s => s.Category == "应用程序" && s.Code == appId)?.Name,
|
||||
HomeUrl = dicts.FirstOrDefault(s => s.Category == "应用首页" && s.Name == appId)?.Code,
|
||||
ProfileUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "个人中心地址")?.Code,
|
||||
SettingsUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "系统设置地址")?.Code,
|
||||
NotificationUrl = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "系统通知地址")?.Code,
|
||||
Title = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站标题")?.Code,
|
||||
Footer = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站页脚")?.Code,
|
||||
Icon = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "网站图标")?.Code,
|
||||
Favicon = dicts.FirstOrDefault(s => s.Category == appId && s.Name == "favicon")?.Code,
|
||||
};
|
||||
}
|
||||
|
||||
public bool DeleteClient(string appId)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
bool ret;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.BeginTransaction();
|
||||
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category={0} and Name={1} and Define={2}", "应用首页", appId, EnumDictDefine.System);
|
||||
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category={0} and Name={1} and Define={2}", "应用程序", appId, EnumDictDefine.System);
|
||||
dbcontext.Database.ExecuteSqlRaw("delete Dicts where Category=@{0} and Name in ({1})", new
|
||||
{
|
||||
Category = appId,
|
||||
Names = new List<string>
|
||||
{
|
||||
"网站标题",
|
||||
"网站页脚",
|
||||
"favicon",
|
||||
"网站图标",
|
||||
"个人中心地址",
|
||||
"系统设置地址",
|
||||
"系统通知地址"
|
||||
}
|
||||
});
|
||||
dbcontext.Database.CommitTransaction();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
dbcontext.Database.RollbackTransaction();
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool SaveDict(Dict dict)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = dbcontext.Database.ExecuteSqlRaw("update Dicts set Code = {1} where Category = {2} and Name = {0}", new[] { dict.Name, dict.Code, dict.Category }!) > 0;
|
||||
if (ret)
|
||||
{
|
||||
// 更新缓存
|
||||
CacheManager.Clear(DictServiceCacheKey);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private string? GetUrlByName(string appId, string dictName)
|
||||
{
|
||||
string? url = null;
|
||||
var dicts = GetAll();
|
||||
var appName = dicts.FirstOrDefault(d => d.Category == "应用程序" && d.Code == appId && d.Define == EnumDictDefine.System)?.Name;
|
||||
if (!string.IsNullOrEmpty(appName))
|
||||
{
|
||||
url = dicts.FirstOrDefault(d => d.Category == appName && d.Name == dictName && d.Define == EnumDictDefine.Customer)?.Code;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ExceptionService : IException
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dbFactory"></param>
|
||||
public ExceptionService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="searchText"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageItems"></param>
|
||||
/// <param name="sortList"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public (IEnumerable<Error> Items, int ItemsCount) GetAll(string? searchText, ExceptionFilter filter, int pageIndex, int pageItems, List<string> sortList)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
var items = dbcontext.Set<Error>();
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
items.Where(s => s.Message!.Contains(searchText) || s.StackTrace!.Contains(searchText) || s.ErrorPage!.Contains(searchText));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.Category))
|
||||
{
|
||||
items.Where(s => s.Category!.Contains(filter.Category));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.UserId))
|
||||
{
|
||||
items.Where(s => s.UserId!.Contains(filter.UserId));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.ErrorPage))
|
||||
{
|
||||
items.Where(s => s.ErrorPage!.Contains(filter.ErrorPage));
|
||||
}
|
||||
|
||||
items.Where(s => s.LogTime >= filter.Star && s.LogTime <= filter.End);
|
||||
|
||||
if (sortList.Any())
|
||||
{
|
||||
items.Sort(sortList);
|
||||
}
|
||||
else
|
||||
{
|
||||
items.OrderByDescending(s => s.LogTime);
|
||||
}
|
||||
|
||||
var data = items.Take(pageItems).Skip(pageItems * (pageIndex - 1)).AsNoTracking().ToList();
|
||||
return (data, items.Count());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="exception"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool Log(Error exception)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
dbcontext.Add(exception);
|
||||
return dbcontext.SaveChanges() > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class GroupService : IGroup, IDisposable
|
||||
{
|
||||
|
||||
private const string GroupServiceGetAllCacheKey = "GroupService-GetAll";
|
||||
|
||||
private const string GroupServiceGetGroupsByUserIdCacheKey = "GroupService-GetGroupsByUserId";
|
||||
|
||||
private const string GroupServiceGetGroupsByRoleIdCacheKey = "GroupService-GetGroupsByRoleId";
|
||||
|
||||
private CancellationTokenSource? GetGroupsByUserIdCancellationTokenSource { get; set; }
|
||||
|
||||
private CancellationTokenSource? GetGroupsByRoleIdCancellationTokenSource { get; set; }
|
||||
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dbFactory"></param>
|
||||
public GroupService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<Group> GetAll()
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return CacheManager.GetOrAdd(GroupServiceGetAllCacheKey, entry => dbcontext.Groups.AsNoTracking().ToList());
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetGroupsByRoleId(string? roleId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByRoleIdCacheKey}-{roleId}", entry =>
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
GetGroupsByRoleIdCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(10));
|
||||
var token = new CancellationChangeToken(GetGroupsByRoleIdCancellationTokenSource.Token);
|
||||
entry.ExpirationTokens.Add(token);
|
||||
return dbcontext.RoleGroup.Where(s => s.RoleId == roleId).Select(s => s.GroupId!).ToList();
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetGroupsByUserId(string? userId) => CacheManager.GetOrAdd($"{GroupServiceGetGroupsByUserIdCacheKey}-{userId}", entry =>
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
GetGroupsByUserIdCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(10));
|
||||
var token = new CancellationChangeToken(GetGroupsByUserIdCancellationTokenSource.Token);
|
||||
entry.ExpirationTokens.Add(token);
|
||||
return dbcontext.Set<UserGroup>().FromSqlRaw("select GroupID from UserGroup where UserID = {0}", userId!).Select(s => s.GroupId!).ToList();
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <param name="groupIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveGroupsByRoleId(string? roleId, IEnumerable<string> groupIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from RoleGroup where RoleID = {0}", roleId!);
|
||||
dbcontext.AddRange(groupIds.Select(g => new RoleGroup { GroupId = g, RoleId = roleId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
// reset cache
|
||||
GetGroupsByRoleIdCancellationTokenSource?.Cancel();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groupIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveGroupsByUserId(string? userId, IEnumerable<string> groupIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from UserGroup where UserID = {0}", userId!);
|
||||
dbcontext.AddRange(groupIds.Select(g => new UserGroup { GroupId = g, UserId = userId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
GetGroupsByUserIdCancellationTokenSource?.Cancel();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
GetGroupsByRoleIdCancellationTokenSource?.Cancel();
|
||||
GetGroupsByRoleIdCancellationTokenSource?.Dispose();
|
||||
|
||||
GetGroupsByUserIdCancellationTokenSource?.Cancel();
|
||||
GetGroupsByUserIdCancellationTokenSource?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class LoginService : ILogin
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public LoginService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="IP"></param>
|
||||
/// <param name="OS"></param>
|
||||
/// <param name="browser"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="userAgent"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool Log(string userName, string? IP, string? OS, string? browser, string? address, string? userAgent, bool result)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
var loginUser = new LoginLog()
|
||||
{
|
||||
UserName = userName,
|
||||
LoginTime = DateTime.Now,
|
||||
Ip = IP,
|
||||
City = address,
|
||||
OS = OS,
|
||||
Browser = browser,
|
||||
UserAgent = userAgent,
|
||||
Result = result ? "登录成功" : "登录失败"
|
||||
};
|
||||
dbcontext.Add(loginUser);
|
||||
return dbcontext.SaveChanges() > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
class NavigationService : INavigation
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
public NavigationService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
|
||||
|
||||
/// <summary>
|
||||
/// 获得指定用户名可访问的所有菜单集合
|
||||
/// </summary>
|
||||
/// <param name="userName">当前用户名</param>
|
||||
/// <returns>未层次化的菜单集合</returns>
|
||||
public List<Navigation> GetAllMenus(string userName)
|
||||
{
|
||||
return CacheManager.GetOrAdd($"{nameof(NavigationService)}-{nameof(GetAllMenus)}-{userName}", entry =>
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.Set<Navigation>().FromSqlRaw("select n.ID, n.ParentId, n.Name, n.[order], n.Icon, n.Url, n.Category, n.Target, n.IsResource, n.Application from Navigations n inner join (select nr.NavigationID from Users u inner join UserRole ur on ur.UserID = u.ID inner join NavigationRole nr on nr.RoleID = ur.RoleID where u.UserName = {0} union select nr.NavigationID from Users u inner join UserGroup ug on u.ID = ug.UserID inner join RoleGroup rg on rg.GroupID = ug.GroupID inner join NavigationRole nr on nr.RoleID = rg.RoleID where u.UserName = {0} union select n.ID from Navigations n where EXISTS (select UserName from Users u inner join UserRole ur on u.ID = ur.UserID inner join Roles r on ur.RoleID = r.ID where u.UserName = {0} and r.RoleName = {1})) nav on n.ID = nav.NavigationID ORDER BY n.Application, n.[order]", new[] { userName, "Administrators" }).AsNoTracking().ToList();
|
||||
});
|
||||
}
|
||||
|
||||
public List<string> GetMenusByRoleId(string? roleId)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
|
||||
return context.NavigationRole.Where(s => s.RoleId == roleId).Select(s => s.NavigationId!).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from NavigationRole where RoleID = {0}", roleId!);
|
||||
dbcontext.Set<NavigationRole>().AddRange(menuIds.Select(g => new NavigationRole { NavigationId = g, RoleId = roleId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
CacheManager.Clear($"{nameof(NavigationService)}-{nameof(GetAllMenus)}-*");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.Caching;
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RoleService : IRole
|
||||
{
|
||||
private const string RoleServiceGetAllCacheKey = "RoleService-GetAll";
|
||||
|
||||
private const string RoleServiceGetRolesByUserIdCacheKey = "RoleService-GetRolesByUserId";
|
||||
|
||||
private const string RoleServiceGetRolesByGroupIdCacheKey = "RoleService-GetRolesByGroupId";
|
||||
|
||||
private CancellationTokenSource? GetRolesByUserIdCancellationTokenSource { get; set; }
|
||||
|
||||
private CancellationTokenSource? GetRolesByGroupIdCancellationTokenSource { get; set; }
|
||||
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dbFactory"></param>
|
||||
public RoleService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<Role> GetAll()
|
||||
{
|
||||
return CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry =>
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return dbcontext.Roles.ToList();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public List<string> GetRolesByGroupId(string? groupId)
|
||||
{
|
||||
return CacheManager.GetOrAdd($"{RoleServiceGetRolesByGroupIdCacheKey}-{groupId}", entry =>
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return dbcontext.RoleGroup.Where(s => s.GroupId == groupId).Select(s => s.RoleId!).AsNoTracking().ToList();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="menuId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetRolesByMenuId(string? menuId)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return dbcontext.NavigationRole.Where(s => s.NavigationId == menuId).Select(s => s.RoleId!).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetRolesByUserId(string? userId)
|
||||
{
|
||||
return CacheManager.GetOrAdd($"{RoleServiceGetRolesByUserIdCacheKey}-{userId}", entry =>
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
return dbcontext.UserRole.Where(s => s.UserId == userId).Select(s => s.RoleId!).AsNoTracking().ToList();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <param name="roleIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveRolesByGroupId(string? groupId, IEnumerable<string> roleIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from RoleGroup where GroupID = {0}", groupId!);
|
||||
dbcontext.AddRange(roleIds.Select(g => new RoleGroup { RoleId = g, GroupId = groupId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="menuId"></param>
|
||||
/// <param name="roleIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveRolesByMenuId(string? menuId, IEnumerable<string> roleIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from NavigationRole where NavigationID = {0}", menuId!);
|
||||
dbcontext.AddRange(roleIds.Select(g => new NavigationRole { RoleId = g, NavigationId = menuId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="roleIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveRolesByUserId(string? userId, IEnumerable<string> roleIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var ret = false;
|
||||
try
|
||||
{
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from UserRole where UserID = {0}", userId!);
|
||||
dbcontext.AddRange(roleIds.Select(g => new UserRole { RoleId = g, UserId = userId }));
|
||||
dbcontext.SaveChanges();
|
||||
ret = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class TraceService : ITrace
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dbFactory"></param>
|
||||
public TraceService(IDbContextFactory<BootstrapAdminContext> dbFactory) => DbFactory = dbFactory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="searchText"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageItems"></param>
|
||||
/// <param name="sortList"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public (IEnumerable<Trace> Items, int ItemsCount) GetAll(string? searchText, TraceFilter filter, int pageIndex, int pageItems, List<string> sortList)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
var items = dbcontext.Set<Trace>();
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
items.Where(s => s.UserName!.Contains(searchText) || s.Ip!.Contains(searchText) || s.RequestUrl!.Contains(searchText));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.UserName))
|
||||
{
|
||||
items.Where(s => s.UserName!.Contains(filter.UserName));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.Ip))
|
||||
{
|
||||
items.Where(s => s.Ip!.Contains(filter.Ip));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.RequestUrl))
|
||||
{
|
||||
items.Where(s => s.RequestUrl!.Contains(filter.RequestUrl));
|
||||
}
|
||||
|
||||
items.Where(s => s.LogTime >= filter.Star && s.LogTime <= filter.End);
|
||||
|
||||
if (sortList.Any())
|
||||
{
|
||||
items.Sort(sortList);
|
||||
}
|
||||
else
|
||||
{
|
||||
items.OrderByDescending(s => s.LogTime);
|
||||
}
|
||||
|
||||
var data = items.Take(pageItems).Skip(pageItems * (pageIndex - 1)).AsNoTracking().ToList();
|
||||
return (data, items.Count());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="trace"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void Log(Trace trace)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
|
||||
dbcontext.Add(trace);
|
||||
dbcontext.SaveChanges();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapAdmin.DataAccess.EFCore.Models;
|
||||
using BootstrapAdmin.DataAccess.Models;
|
||||
using BootstrapAdmin.Web.Core;
|
||||
using Longbow.Security.Cryptography;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.EFCore.Services;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UserService : IUser
|
||||
{
|
||||
private IDbContextFactory<BootstrapAdminContext> DbFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
public UserService(IDbContextFactory<BootstrapAdminContext> factory) => DbFactory = factory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<User> GetAll()
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.Users.AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
public bool Authenticate(string userName, string password)
|
||||
{
|
||||
var isAuth = false;
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
var user = context.Users.Where(s => s.ApprovedTime != null).FirstOrDefault(x => x.UserName == userName);
|
||||
if (user != null && !string.IsNullOrEmpty(user.PassSalt))
|
||||
{
|
||||
isAuth = user.Password == LgbCryptography.ComputeHash(password, user.PassSalt);
|
||||
}
|
||||
return isAuth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetApps(string userName)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.Dicts.FromSqlRaw("select d.Code from Dicts d inner join RoleApp ra on d.Code = ra.AppId inner join (select r.Id from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = {0} union select r.Id from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = {0}) r on ra.RoleId = r.ID union select Code from Dicts where Category = {1} and exists(select r.ID from Roles r inner join UserRole ur on r.ID = ur.RoleID inner join Users u on ur.UserID = u.ID where u.UserName = {0} and r.RoleName = {2} union select r.ID from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID where u.UserName = {0} and r.RoleName = {2})", new[] { userName, "应用程序", "Administrators" }).Select(s => s.Code).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public string? GetDisplayName(string? userName)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return string.IsNullOrEmpty(userName) ? "" : context.Users.FirstOrDefault(s => s.UserName == userName)?.DisplayName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetRoles(string userName)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.Roles.FromSqlRaw("select r.RoleName from Roles r inner join UserRole ur on r.ID=ur.RoleID inner join Users u on ur.UserID = u.ID and u.UserName = {0} union select r.RoleName from Roles r inner join RoleGroup rg on r.ID = rg.RoleID inner join [Groups] g on rg.GroupID = g.ID inner join UserGroup ug on ug.GroupID = g.ID inner join Users u on ug.UserID = u.ID and u.UserName = {0}", userName).Select(s => s.RoleName).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetUsersByGroupId(string? groupId)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.UserGroup.Where(s => s.GroupId == groupId).Select(s => s.UserId!).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetUsersByRoleId(string? roleId)
|
||||
{
|
||||
using var context = DbFactory.CreateDbContext();
|
||||
return context.UserRole.Where(s => s.RoleId == roleId).Select(s => s.UserId!).AsNoTracking().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <param name="userIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveUsersByGroupId(string? groupId, IEnumerable<string> userIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from UserGroup where GroupId = {0}", groupId!);
|
||||
dbcontext.AddRange(userIds.Select(g => new UserGroup { UserId = g, GroupId = groupId }));
|
||||
dbcontext.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <param name="userIds"></param>
|
||||
/// <returns></returns>
|
||||
public bool SaveUsersByRoleId(string? roleId, IEnumerable<string> userIds)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
dbcontext.Database.ExecuteSqlRaw("delete from UserRole where RoleID = {0}", roleId!);
|
||||
dbcontext.AddRange(userIds.Select(g => new UserRole { UserId = g, RoleId = roleId }));
|
||||
dbcontext.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="phone"></param>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="appId"></param>
|
||||
/// <param name="roles"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles)
|
||||
{
|
||||
var ret = false;
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var salt = LgbCryptography.GenerateSalt();
|
||||
var pwd = LgbCryptography.ComputeHash(code, salt);
|
||||
var user = GetAll().FirstOrDefault(user => user.UserName == phone);
|
||||
if (user == null)
|
||||
{
|
||||
user = new User()
|
||||
{
|
||||
ApprovedBy = "Mobile",
|
||||
ApprovedTime = DateTime.Now,
|
||||
DisplayName = "手机用户",
|
||||
UserName = phone,
|
||||
Icon = "default.jpg",
|
||||
Description = "手机用户",
|
||||
App = appId
|
||||
};
|
||||
dbcontext.Add(user);
|
||||
|
||||
// Authorization
|
||||
var roleIds = dbcontext.Roles.Where(s => roles.Contains(s.RoleName)).Select(s => s.Id).ToList();
|
||||
dbcontext.AddRange(roleIds.Select(g => new { RoleID = g, UserID = user.Id }));
|
||||
ret = dbcontext.SaveChanges() > 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public User? GetUserByUserName(string? userName)
|
||||
{
|
||||
User? user = null;
|
||||
if (userName != null)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
user = dbcontext.Set<User>().FirstOrDefault(s => s.UserName == userName);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
|
||||
public string? GetAppIdByUserName(string userName)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
return dbcontext.Set<User>().FirstOrDefault(s => s.UserName == userName)?.App;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <param name="newPassword"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool ChangePassword(string userName, string password, string newPassword)
|
||||
{
|
||||
var ret = false;
|
||||
if (Authenticate(userName, password))
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var passSalt = LgbCryptography.GenerateSalt();
|
||||
password = LgbCryptography.ComputeHash(newPassword, passSalt);
|
||||
string sql = "update Users set Password = {0}, PassSalt = {1} where UserName = {2}";
|
||||
ret = dbcontext.Database.ExecuteSqlRaw(sql, new[] { password, passSalt, userName }) > 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="displayName"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveDisplayName(string userName, string displayName)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
return dbcontext.Database.ExecuteSqlRaw("update Users set DisplayName = {1} where UserName = {0}", userName, displayName!) > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="theme"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveTheme(string userName, string theme)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
return dbcontext.Database.ExecuteSqlRaw("update Users set Css = {1} where UserName = {0}", userName, theme) > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="logo"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveLogo(string userName, string? logo)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
return dbcontext.Database.ExecuteSqlRaw("update Users set Icon = {1} where UserName = {0}", userName, logo ?? "") > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="app"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveApp(string userName, string app)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
return dbcontext.Database.ExecuteSqlRaw("update Users Set App = {1} Where UserName = {0}", userName, app) > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="displayName"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public bool SaveUser(string userName, string displayName, string password)
|
||||
{
|
||||
using var dbcontext = DbFactory.CreateDbContext();
|
||||
var salt = LgbCryptography.GenerateSalt();
|
||||
var pwd = LgbCryptography.ComputeHash(password, salt);
|
||||
var user = GetAll().FirstOrDefault(s => s.UserName == userName);
|
||||
bool ret;
|
||||
if (user == null)
|
||||
{
|
||||
user = new User()
|
||||
{
|
||||
ApprovedBy = "System",
|
||||
ApprovedTime = DateTime.Now,
|
||||
DisplayName = "手机用户",
|
||||
UserName = userName,
|
||||
Icon = "default.jpg",
|
||||
Description = "系统默认创建",
|
||||
PassSalt = salt,
|
||||
Password = pwd
|
||||
};
|
||||
dbcontext.Add(user);
|
||||
// 授权 Default 角色
|
||||
dbcontext.Database.ExecuteSqlRaw("insert into UserRole (UserID, RoleID) select ID, (select ID from Roles where RoleName = 'Default') RoleId from Users where UserName = {0}", userName);
|
||||
ret = dbcontext.SaveChanges() > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.DisplayName = displayName;
|
||||
user.PassSalt = salt;
|
||||
user.Password = pwd;
|
||||
dbcontext.Update(user);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AppInfo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "系统名称")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[NotNull]
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "网站页脚")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[NotNull]
|
||||
public string? Footer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "登录首页")]
|
||||
[NotNull]
|
||||
public string? Login { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "后台地址")]
|
||||
[NotNull]
|
||||
public string? AuthUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "网站主题")]
|
||||
[NotNull]
|
||||
public string? Theme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启默认应用功能
|
||||
/// </summary>
|
||||
[Display(Name = "默认应用")]
|
||||
public bool EnableDefaultApp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "系统演示")]
|
||||
public bool IsDemo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "侧边栏设置")]
|
||||
public bool SiderbarSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "标题设置")]
|
||||
public bool TitleSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "固定表头")]
|
||||
public bool FixHeaderSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "健康检查")]
|
||||
public bool HealthCheckSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "手机登录")]
|
||||
public bool MobileLogin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "OAuth认证")]
|
||||
public bool OAuthLogin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "自动锁屏")]
|
||||
public bool AutoLock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "时长间隔(秒)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int Interval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "地理位置定位器")]
|
||||
public string? IpLocator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "异常日志(月)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int ExceptionExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作日志(月)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int OperateExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作日志(月)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int LoginExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "访问日志(月)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int AccessExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "Cookie(天)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int CookieExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "IP 缓存(分)")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
public int IPCacheExpired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "授权码")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[NotNull]
|
||||
public string? AuthCode { get; set; }
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 后台数据库脚本执行日志实体类
|
||||
/// </summary>
|
||||
public class DBLog
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 主键ID
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 当前登陆名
|
||||
/// </summary>
|
||||
[DisplayName("所属用户")]
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 数据库执行脚本
|
||||
/// </summary>
|
||||
[DisplayName("脚本内容")]
|
||||
public string SQL { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取/设置 用户角色关联状态 checked 标示已经关联 '' 标示未关联
|
||||
/// </summary>
|
||||
[DisplayName("执行时间")]
|
||||
public DateTime LogTime { get; set; }
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 字典配置项
|
||||
/// </summary>
|
||||
[Table("Dicts")]
|
||||
public class Dict
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 字典主键 数据库自增列
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 字典标签
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[Display(Name = "字典标签")]
|
||||
public string? Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 字典名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[Display(Name = "字典名称")]
|
||||
[NotNull]
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 字典字典值
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[Display(Name = "字典代码")]
|
||||
[NotNull]
|
||||
public string? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 字典定义值 0 表示系统使用,1 表示用户自定义 默认为 1
|
||||
/// </summary>
|
||||
[Display(Name = "字典类型")]
|
||||
public EnumDictDefine Define { get; set; } = EnumDictDefine.Customer;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 字典定义值 0 表示系统使用,1 表示用户自定义 默认为 1
|
||||
/// </summary>
|
||||
public enum EnumDictDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统使用
|
||||
/// </summary>
|
||||
[Description("系统使用")]
|
||||
System,
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义
|
||||
/// </summary>
|
||||
[Description("自定义")]
|
||||
Customer
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 菜单分类 0 表示系统菜单 1 表示用户自定义菜单
|
||||
/// </summary>
|
||||
public enum EnumNavigationCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// 系统使用
|
||||
/// </summary>
|
||||
[Description("后台菜单")]
|
||||
System,
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义
|
||||
/// </summary>
|
||||
[Description("前台菜单")]
|
||||
Customer
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 资源类型枚举 0 表示菜单 1 表示资源 2 表示按钮
|
||||
/// </summary>
|
||||
public enum EnumResource
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Description("菜单")]
|
||||
Navigation,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Description("资源")]
|
||||
Resource,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Description("代码块")]
|
||||
Block
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 异常实体类
|
||||
/// </summary>
|
||||
public class Error
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 主键
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[DisplayName("应用程序")]
|
||||
public string? AppDomainName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户请求页面地址
|
||||
/// </summary>
|
||||
[DisplayName("请求网址")]
|
||||
public string? ErrorPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户 ID
|
||||
/// </summary>
|
||||
[DisplayName("用户名")]
|
||||
public string? UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户 IP
|
||||
/// </summary>
|
||||
[DisplayName("登录主机")]
|
||||
public string? UserIp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 异常类型
|
||||
/// </summary>
|
||||
[DisplayName("异常类型")]
|
||||
public string? ExceptionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 异常错误描述信息
|
||||
/// </summary>
|
||||
[DisplayName("异常描述")]
|
||||
public string? Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 异常堆栈信息
|
||||
/// </summary>
|
||||
public string? StackTrace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 日志时间戳
|
||||
/// </summary>
|
||||
[DisplayName("记录时间")]
|
||||
public DateTime LogTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 分类信息
|
||||
/// </summary>
|
||||
[DisplayName("分类信息")]
|
||||
public string? Category { get; set; }
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Group 实体类
|
||||
/// </summary>
|
||||
public class Group
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 主键 ID
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 群组名称
|
||||
/// </summary>
|
||||
[Display(Name = "群组名称")]
|
||||
[NotNull]
|
||||
public string? GroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 群组编码
|
||||
/// </summary>
|
||||
[Display(Name = "群组编码")]
|
||||
[NotNull]
|
||||
public string? GroupCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 群组描述
|
||||
/// </summary>
|
||||
[Display(Name = "群组描述")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString() => $"{GroupName} ({GroupCode})";
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 登录用户信息实体类
|
||||
/// </summary>
|
||||
public class LoginLog
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 Id
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户名
|
||||
/// </summary>
|
||||
[DisplayName("登录名称")]
|
||||
[NotNull]
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录时间
|
||||
/// </summary>
|
||||
[DisplayName("登录时间")]
|
||||
public DateTime LoginTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录IP地址
|
||||
/// </summary>
|
||||
[DisplayName("主机")]
|
||||
[NotNull]
|
||||
public string? Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录浏览器
|
||||
/// </summary>
|
||||
[DisplayName("浏览器")]
|
||||
[NotNull]
|
||||
public string? Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录操作系统
|
||||
/// </summary>
|
||||
[DisplayName("操作系统")]
|
||||
[NotNull]
|
||||
public string? OS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录地点
|
||||
/// </summary>
|
||||
[DisplayName("登录地点")]
|
||||
[NotNull]
|
||||
public string? City { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 登录是否成功
|
||||
/// </summary>
|
||||
[DisplayName("登录结果")]
|
||||
[NotNull]
|
||||
public string? Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户 UserAgent
|
||||
/// </summary>
|
||||
[DisplayName("登录名称")]
|
||||
[NotNull]
|
||||
public string? UserAgent { get; set; }
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Bootstrap Admin 后台管理菜单相关操作实体类
|
||||
/// </summary>
|
||||
public class Navigation
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单主键ID
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public string? Id { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 父级菜单ID 默认为 0
|
||||
/// </summary>
|
||||
public string ParentId { set; get; } = "0";
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单名称
|
||||
/// </summary>
|
||||
[Display(Name = "名称")]
|
||||
[NotNull]
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单序号
|
||||
/// </summary>
|
||||
[Display(Name = "序号")]
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单图标
|
||||
/// </summary>
|
||||
[Display(Name = "图标")]
|
||||
public string? Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单URL地址
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
[Display(Name = "地址")]
|
||||
public string? Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 菜单分类, 0 表示系统菜单 1 表示用户自定义菜单
|
||||
/// </summary>
|
||||
[Display(Name = "类别")]
|
||||
public EnumNavigationCategory Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 链接目标
|
||||
/// </summary>
|
||||
[Display(Name = "目标")]
|
||||
public string? Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否为资源文件, 0 表示菜单 1 表示资源 2 表示按钮
|
||||
/// </summary>
|
||||
[Display(Name = "类型")]
|
||||
public EnumResource IsResource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 所属应用程序,此属性由BA后台字典表分配
|
||||
/// </summary>
|
||||
[Display(Name = "所属应用")]
|
||||
public string? Application { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool HasChildren { get; set; }
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Role 实体类
|
||||
/// </summary>
|
||||
public class Role
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 角色主键ID
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 角色名称
|
||||
/// </summary>
|
||||
[DisplayName("角色名称")]
|
||||
[NotNull]
|
||||
public string? RoleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 角色描述
|
||||
/// </summary>
|
||||
[DisplayName("角色描述")]
|
||||
[NotNull]
|
||||
public string? Description { get; set; }
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Trace
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "登录用户")]
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作时间")]
|
||||
public DateTime LogTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "登录主机")]
|
||||
public string? Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "浏览器")]
|
||||
public string? Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作系统")]
|
||||
public string? OS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作地点")]
|
||||
public string? City { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "操作页面")]
|
||||
public string? RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? UserAgent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Referer { get; set; }
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.Models;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class User
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 系统登录用户名
|
||||
/// </summary>
|
||||
[Display(Name = "登录名称")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[RegularExpression("^[a-zA-Z0-9_@.]*$", ErrorMessage = "登录名称包含非法字符")]
|
||||
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
|
||||
[NotNull]
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户显示名称
|
||||
/// </summary>
|
||||
[Display(Name = "显示名称")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[MaxLength(20, ErrorMessage = "{0}不能超过 20 个字符")]
|
||||
[NotNull]
|
||||
public string? DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户头像图标路径
|
||||
/// </summary>
|
||||
[Display(Name = "用户头像")]
|
||||
public string? Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户设置样式表名称
|
||||
/// </summary>
|
||||
[Display(Name = "主题")]
|
||||
public string? Css { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户默认登陆 App 标识
|
||||
/// </summary>
|
||||
[Display(Name = "默认 APP")]
|
||||
[NotNull]
|
||||
public string? App { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户主键ID
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取/设置 密码
|
||||
/// </summary>
|
||||
[Display(Name = "密码")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
|
||||
[NotNull]
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取/设置 密码盐
|
||||
/// </summary>
|
||||
public string? PassSalt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户注册时间
|
||||
/// </summary>
|
||||
[Display(Name = "注册时间")]
|
||||
public DateTime RegisterTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户被批复时间
|
||||
/// </summary>
|
||||
[Display(Name = "授权时间")]
|
||||
public DateTime? ApprovedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户批复人
|
||||
/// </summary>
|
||||
[Display(Name = "授权人")]
|
||||
public string? ApprovedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 用户的申请理由
|
||||
/// </summary>
|
||||
[Display(Name = "说明")]
|
||||
[NotNull]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 通知描述 2分钟内为刚刚
|
||||
/// </summary>
|
||||
public string? Period { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 新密码
|
||||
/// </summary>
|
||||
[Display(Name = "新密码")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
|
||||
[NotNull]
|
||||
public string? NewPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 新密码
|
||||
/// </summary>
|
||||
[Display(Name = "确认密码")]
|
||||
[Required(ErrorMessage = "{0}不可为空")]
|
||||
[Compare("NewPassword", ErrorMessage = "{0}与{1}不一致")]
|
||||
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
|
||||
[NotNull]
|
||||
public string? ConfirmPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否重置密码
|
||||
/// </summary>
|
||||
public int IsReset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 默认格式为 DisplayName (UserName)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString() => $"{DisplayName} ({UserName})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户状态枚举类型
|
||||
/// </summary>
|
||||
public enum UserStates
|
||||
{
|
||||
/// <summary>
|
||||
/// 更改密码
|
||||
/// </summary>
|
||||
ChangePassword,
|
||||
|
||||
/// <summary>
|
||||
/// 更改样式
|
||||
/// </summary>
|
||||
ChangeTheme,
|
||||
|
||||
/// <summary>
|
||||
/// 更改显示名称
|
||||
/// </summary>
|
||||
ChangeDisplayName,
|
||||
|
||||
/// <summary>
|
||||
/// 审批用户
|
||||
/// </summary>
|
||||
ApproveUser,
|
||||
|
||||
/// <summary>
|
||||
/// 拒绝用户
|
||||
/// </summary>
|
||||
RejectUser,
|
||||
|
||||
/// <summary>
|
||||
/// 保存默认应用
|
||||
/// </summary>
|
||||
SaveApp
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
|
||||
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
|
||||
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BootstrapAdmin.Caching\BootstrapAdmin.Caching.csproj" />
|
||||
<ProjectReference Include="..\BootstrapAdmin.Web.Core\BootstrapAdmin.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using PetaPoco;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BootstrapAdmin.DataAccess.PetaPoco;
|
||||
|
||||
class BootstrapAdminConventionMapper : ConventionMapper
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pocoType"></param>
|
||||
/// <returns></returns>
|
||||
public override TableInfo GetTableInfo(Type pocoType)
|
||||
{
|
||||
var ti = base.GetTableInfo(pocoType);
|
||||
ti.AutoIncrement = true;
|
||||
|
||||
// 支持 Oracle 数据库
|
||||
ti.SequenceName = $"SEQ_{ti.TableName.ToUpperInvariant()}_ID";
|
||||
|
||||
ti.TableName = pocoType.Name switch
|
||||
{
|
||||
"Error" => "Exceptions",
|
||||
_ => $"{pocoType.Name}s"
|
||||
};
|
||||
return ti;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pocoProperty"></param>
|
||||
/// <returns></returns>
|
||||
public override ColumnInfo GetColumnInfo(PropertyInfo pocoProperty) => pocoProperty.DeclaringType?.Name switch
|
||||
{
|
||||
nameof(Models.User) => GetUserColumnInfo(pocoProperty),
|
||||
nameof(Models.Navigation) => GetNavigationColumnInfo(pocoProperty),
|
||||
_ => base.GetColumnInfo(pocoProperty)
|
||||
};
|
||||
|
||||
private ColumnInfo GetUserColumnInfo(PropertyInfo pocoProperty)
|
||||
{
|
||||
var ci = base.GetColumnInfo(pocoProperty);
|
||||
var resultColumns = new List<string>
|
||||
{
|
||||
nameof(Models.User.NewPassword),
|
||||
nameof(Models.User.ConfirmPassword),
|
||||
nameof(Models.User.Period),
|
||||
nameof(Models.User.IsReset)
|
||||
};
|
||||
ci.ResultColumn = resultColumns.Any(c => c == ci.ColumnName);
|
||||
return ci;
|
||||
}
|
||||
|
||||
private ColumnInfo GetNavigationColumnInfo(PropertyInfo pocoProperty)
|
||||
{
|
||||
var ci = base.GetColumnInfo(pocoProperty);
|
||||
var resultColumns = new List<string>
|
||||
{
|
||||
nameof(Models.Navigation.HasChildren)
|
||||
};
|
||||
ci.ResultColumn = resultColumns.Any(c => c == ci.ColumnName);
|
||||
return ci;
|
||||
}
|
||||
|
||||
public override Func<object?, object?> GetFromDbConverter(PropertyInfo targetProperty, Type sourceType) => targetProperty.PropertyType.IsEnum && sourceType == typeof(string)
|
||||
? new NumberToEnumConverter(targetProperty.PropertyType).ConvertFromDb
|
||||
: base.GetFromDbConverter(targetProperty, sourceType);
|
||||
|
||||
public override Func<object?, object?> GetToDbConverter(PropertyInfo targetProperty) => targetProperty.PropertyType.IsEnum
|
||||
? new NumberToEnumConverter(targetProperty.PropertyType).ConvertToDb
|
||||
: base.GetToDbConverter(targetProperty);
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||
// Website: https://admin.blazor.zone
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using PetaPoco;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BootstrapAdmin.Web.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// PetaPoco 数据操作扩展类
|
||||
/// </summary>
|
||||
static class DatabaseExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Task<List<TModel>> FetchAsync<TModel>(this IDatabase db, QueryPageOptions options)
|
||||
{
|
||||
var sql = db.ProcessQuery<TModel>(options);
|
||||
return db.FetchAsync<TModel>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Task<Page<TModel>> PageAsync<TModel>(this IDatabase db, QueryPageOptions options)
|
||||
{
|
||||
var sql = db.ProcessQuery<TModel>(options);
|
||||
return db.PageAsync<TModel>(options.PageIndex, options.PageItems, sql);
|
||||
}
|
||||
|
||||
private static Sql ProcessQuery<TModel>(this IDatabase db, QueryPageOptions options)
|
||||
{
|
||||
var sql = new Sql();
|
||||
|
||||
// 处理模糊查询
|
||||
if (options.Searchs.Any())
|
||||
{
|
||||
var searchTextSql = new Sql();
|
||||
AnalysisExpression(options.Searchs.GetFilterLambda<TModel>(FilterLogic.Or), db, searchTextSql);
|
||||
sql.Append(searchTextSql.ToString().Replace("\nAND", "OR"), searchTextSql.Arguments);
|
||||
}
|
||||
|
||||
// 处理高级搜索
|
||||
if (options.AdvanceSearchs.Any())
|
||||
{
|
||||
AnalysisExpression(options.AdvanceSearchs.GetFilterLambda<TModel>(), db, sql);
|
||||
}
|
||||
|
||||
// 处理自定义搜索与过滤
|
||||
var filters = options.Filters.Concat(options.CustomerSearchs);
|
||||
if (filters.Any())
|
||||
{
|
||||
AnalysisExpression(filters.GetFilterLambda<TModel>(), db, sql);
|
||||
}
|
||||
|
||||
// 支持多列排序
|
||||
var sortName = options.SortName;
|
||||
var sortOrder = options.SortOrder;
|
||||
if (!string.IsNullOrEmpty(sortName) && sortOrder != SortOrder.Unset)
|
||||
{
|
||||
sql.OrderBy(sortOrder == SortOrder.Asc ? sortName : $"{sortName} desc");
|
||||
}
|
||||
else if (options.SortList != null && options.SortList.Any())
|
||||
{
|
||||
sql.OrderBy(string.Join(",", options.SortList));
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
private static void AnalysisExpression(Expression expression, IDatabase db, Sql sql)
|
||||
{
|
||||
switch (expression.NodeType)
|
||||
{
|
||||
case ExpressionType.Lambda:
|
||||
if (expression is LambdaExpression exp)
|
||||
{
|
||||
AnalysisExpression(exp.Body, db, sql);
|
||||
}
|
||||
break;
|
||||
case ExpressionType.AndAlso:
|
||||
if (expression is BinaryExpression andExp)
|
||||
{
|
||||
AnalysisExpression(andExp.Left, db, sql);
|
||||
AnalysisExpression(andExp.Right, db, sql);
|
||||
}
|
||||
break;
|
||||
case ExpressionType.OrElse:
|
||||
if (expression is BinaryExpression orExp)
|
||||
{
|
||||
AnalysisExpression(orExp.Left, db, sql);
|
||||
AnalysisExpression(orExp.Right, db, sql);
|
||||
}
|
||||
break;
|
||||
case ExpressionType.Call:
|
||||
if (expression is MethodCallExpression callExp)
|
||||
{
|
||||
if (callExp.Method.Name == "Contains")
|
||||
{
|
||||
if (callExp.Object is MemberExpression callLeft)
|
||||
{
|
||||
var callColName = GetColumnName(callLeft.Member) ?? callLeft.Member.Name;
|
||||
var p = (callExp.Arguments[0] as ConstantExpression)?.Value;
|
||||
if (p != null)
|
||||
{
|
||||
sql.Where($"{db.Provider.EscapeSqlIdentifier(callColName)} like @0", $"%{p}%");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
if (expression is BinaryExpression binaryExp)
|
||||
{
|
||||
MemberExpression? left = null;
|
||||
if (binaryExp.Left is MethodCallExpression methodLeft && methodLeft.Method.Name == "ToString" && methodLeft.Object is MemberExpression p && p.Type.IsEnum)
|
||||
{
|
||||
// 枚举转字符串
|
||||
left = p;
|
||||
}
|
||||
else if (binaryExp.Left is MemberExpression m)
|
||||
{
|
||||
left = m;
|
||||
}
|
||||
|
||||
if (left != null)
|
||||
{
|
||||
// 查找 PetaPoco.Column 标签
|
||||
var columnName = GetColumnName(left.Member) ?? left.Member.Name;
|
||||
|
||||
// 查找操作符右侧
|
||||
if (binaryExp.Right is ConstantExpression right)
|
||||
{
|
||||
var v = right.Value;
|
||||
|
||||
if (v != null)
|
||||
{
|
||||
var val = v.GetType().IsEnum ? (int)v : v;
|
||||
var operatorExp = GetOperatorExpression(expression);
|
||||
sql.Where($"{db.Provider.EscapeSqlIdentifier(columnName)} {operatorExp} @0", val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetColumnName(MemberInfo member) => member.CustomAttributes
|
||||
.FirstOrDefault(i => i.AttributeType == typeof(ColumnAttribute))?.NamedArguments
|
||||
.FirstOrDefault(i => i.MemberName == "Name").TypedValue.Value?.ToString();
|
||||
|
||||
private static string GetOperatorExpression(Expression expression) => expression.NodeType switch
|
||||
{
|
||||
ExpressionType.Equal => "=",
|
||||
ExpressionType.NotEqual => "!=",
|
||||
ExpressionType.GreaterThan => ">",
|
||||
ExpressionType.GreaterThanOrEqual => ">=",
|
||||
ExpressionType.LessThan => "<",
|
||||
ExpressionType.LessThanOrEqual => "<=",
|
||||
_ => ""
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue