Compare commits
546 Commits
9afeb59766
...
ai-agent
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67cb142c07 | ||
|
|
f164b7dccc | ||
|
|
6cc14c1e32 | ||
|
|
e992cfc928 | ||
|
|
42edd4c230 | ||
|
|
3892ff1937 | ||
|
|
12878ba022 | ||
|
|
a3259ad36f | ||
|
|
5bb7dfb7cd | ||
|
|
3447e2dc5d | ||
|
|
88fae0cdc2 | ||
|
|
5a7f0ab108 | ||
|
|
be5f57f654 | ||
|
|
a6e7a5e906 | ||
|
|
c4ab176089 | ||
|
|
a50f877964 | ||
|
|
28cdc29369 | ||
|
|
e39cbaf5e7 | ||
|
|
9d1dd72584 | ||
|
|
ea403fcae0 | ||
|
|
91533909c2 | ||
|
|
61d5d40dbb | ||
|
|
38dbd0aca7 | ||
|
|
343347ea11 | ||
|
|
a9e11d161c | ||
|
|
d25ca6dc4a | ||
|
|
ba95d1798f | ||
|
|
436b5b910c | ||
|
|
560a76558a | ||
|
|
a1be2bebf7 | ||
|
|
3f53eb14ab | ||
|
|
e46044e217 | ||
|
|
80dcd76749 | ||
|
|
9c842ab802 | ||
|
|
b8c0f9a212 | ||
|
|
6cc0059691 | ||
|
|
33d28a8cb0 | ||
|
|
e4621d9049 | ||
|
|
953fbc043b | ||
|
|
c649ad31c2 | ||
|
|
50fc8c5f0a | ||
|
|
64bc65114a | ||
|
|
ae9d778ac7 | ||
|
|
77a9a64a41 | ||
|
|
19ea76bd60 | ||
|
|
0c31b97824 | ||
|
|
70ae2fab44 | ||
|
|
411a9058ca | ||
|
|
4b9f845fae | ||
|
|
bdaa53bac8 | ||
|
|
e5b81c08f3 | ||
|
|
1ffab89e97 | ||
|
|
5440b226c4 | ||
|
|
90c6022839 | ||
|
|
184467e482 | ||
|
|
68045d6458 | ||
|
|
d52f17a17b | ||
|
|
047937af4c | ||
|
|
a9267bfc0e | ||
|
|
1019fd685b | ||
|
|
34246d8a62 | ||
|
|
599b6335d5 | ||
|
|
46bc48d1c1 | ||
|
|
17675e702d | ||
|
|
639c683144 | ||
|
|
96a21210b5 | ||
|
|
7495dc86a0 | ||
|
|
ee4cb20eef | ||
|
|
9ca3cd0b1a | ||
|
|
eb6ec06157 | ||
|
|
62940ae25a | ||
|
|
dfc143379f | ||
|
|
bd3a9a5ce8 | ||
|
|
ec4fdc39fe | ||
|
|
3c3e134d2b | ||
|
|
81089cc058 | ||
|
|
681194a517 | ||
|
|
8f515f76c0 | ||
|
|
fcb74eb28c | ||
|
|
44afdaef8e | ||
|
|
41c55d088d | ||
|
|
3b71fe3135 | ||
|
|
4326c41258 | ||
|
|
7f0d57b311 | ||
|
|
75c208dafc | ||
|
|
8021ca9eff | ||
|
|
2cf06a5677 | ||
|
|
2fa42cd8a3 | ||
|
|
a600eb9e7e | ||
|
|
fcf0fd7f70 | ||
|
|
4e421c160c | ||
|
|
340e2016d6 | ||
|
|
5dfaead60e | ||
|
|
c8acb12e4a | ||
|
|
5fbcb8cbd9 | ||
|
|
fd8d4399d3 | ||
|
|
6f1efafd86 | ||
|
|
2714a507d9 | ||
|
|
9a9230786b | ||
|
|
4a8b58a65c | ||
|
|
7d81f88658 | ||
|
|
0ce3c0bbdd | ||
|
|
981235e6e9 | ||
|
|
d0ecb232a1 | ||
|
|
c7a52604e7 | ||
|
|
da81b2d8a3 | ||
|
|
7b14fdd8de | ||
|
|
1fc2734eb7 | ||
|
|
f3bef72ebb | ||
|
|
7e6d2e829b | ||
|
|
944626960b | ||
|
|
c073868989 | ||
|
|
d2981100fa | ||
|
|
ce4f7e5711 | ||
|
|
cc812ba2cb | ||
|
|
5ed79c6dd0 | ||
|
|
6e2ca8f1c3 | ||
|
|
a46a552097 | ||
|
|
53e56134d4 | ||
|
|
f90105ebb4 | ||
|
|
67ed1ac1e3 | ||
|
|
69b84f6613 | ||
|
|
433d616b9b | ||
|
|
53aa575ad4 | ||
|
|
b7847c7e7d | ||
|
|
94eb41996e | ||
|
|
381b712b25 | ||
|
|
c319b0b4e4 | ||
|
|
1a32fa9e20 | ||
|
|
909406238c | ||
|
|
54a1d2a66f | ||
|
|
8dcbfcad33 | ||
|
|
f64fd43951 | ||
|
|
bfda33280a | ||
|
|
8d0411f1f4 | ||
|
|
3995d4acab | ||
|
|
6ff5727156 | ||
|
|
f654386dfe | ||
|
|
c03ef82643 | ||
|
|
525545329b | ||
|
|
755cb6f509 | ||
|
|
55469708f0 | ||
|
|
94c52c62fe | ||
|
|
37b4709d76 | ||
|
|
86555af6ce | ||
|
|
ddb00879f4 | ||
|
|
2d0ca08314 | ||
|
|
b78ecf27d5 | ||
|
|
02a5f69958 | ||
|
|
cf5bf746ef | ||
|
|
0a5e40ee25 | ||
|
|
51a266ef58 | ||
|
|
1f0901c90c | ||
|
|
a725c06396 | ||
|
|
54547f0d7c | ||
|
|
afe9c8bcae | ||
|
|
688d93e5c1 | ||
|
|
4c65b2398d | ||
|
|
41435f1aa3 | ||
|
|
20206bbc44 | ||
|
|
f2dc0d1825 | ||
|
|
51b4d1b072 | ||
|
|
9180799e4e | ||
|
|
9788b9182b | ||
|
|
260b9a4795 | ||
|
|
9380e3daa8 | ||
|
|
bb894e14a4 | ||
|
|
b492d82442 | ||
|
|
d7bcad9da7 | ||
|
|
04e11d15e2 | ||
|
|
97e3dc5eed | ||
|
|
695bd56a27 | ||
|
|
7919383be3 | ||
|
|
d6cc3c5d96 | ||
|
|
19f0d05a69 | ||
|
|
3c5e575e9b | ||
|
|
f875617de1 | ||
|
|
9976e8a6e2 | ||
|
|
38e8cbc5ca | ||
|
|
d95c14c903 | ||
|
|
ffb2f2fb4c | ||
|
|
4bd2fc357d | ||
|
|
da23d17af8 | ||
|
|
c1a6046107 | ||
|
|
d21f61646a | ||
|
|
eecdf442fb | ||
|
|
8e8338743d | ||
|
|
1b4c3cbb8d | ||
|
|
b7756e2112 | ||
|
|
cb49059e84 | ||
|
|
690cabfd96 | ||
|
|
771ecd9d81 | ||
|
|
a9b2979a21 | ||
|
|
17337b8d78 | ||
|
|
09fb43ee14 | ||
|
|
477c0e3f2c | ||
|
|
2e4f520dac | ||
|
|
067b25b9af | ||
|
|
36370c215d | ||
|
|
e24731acfe | ||
|
|
927e9df7de | ||
|
|
114b41144e | ||
|
|
5019a36138 | ||
|
|
e15eb6149b | ||
|
|
9d401a9c93 | ||
|
|
eacf86e118 | ||
|
|
c4b631c815 | ||
|
|
fb25e75a3a | ||
|
|
e9099bbe04 | ||
|
|
f02fb91175 | ||
|
|
5beef22269 | ||
|
|
933cbb91d8 | ||
|
|
efd917d184 | ||
|
|
e906208f4a | ||
|
|
cf137f6307 | ||
|
|
e6b991fe86 | ||
|
|
3e75792e43 | ||
|
|
dd3f6325bb | ||
|
|
108ba348f6 | ||
|
|
bcdcec40e0 | ||
|
|
2ce8baea42 | ||
|
|
c6425ca206 | ||
|
|
acb359ec33 | ||
|
|
a1395d9a33 | ||
|
|
609de29e71 | ||
|
|
2efed4f4a5 | ||
|
|
aec90ec9d6 | ||
|
|
1aaff2942d | ||
|
|
cdbfc5383d | ||
|
|
f302555e0c | ||
|
|
86c5890476 | ||
|
|
a13ee395c7 | ||
|
|
9abcd72aca | ||
|
|
4ddea6d468 | ||
|
|
867a2dc861 | ||
|
|
4a72e3fa0d | ||
|
|
8b4371aabb | ||
|
|
799dd08ec0 | ||
|
|
c5c22224cf | ||
|
|
2dae47e85c | ||
|
|
375dd4f797 | ||
|
|
acb2db8397 | ||
|
|
b7a3e76d0b | ||
|
|
48150b712a | ||
|
|
6db9dfc308 | ||
|
|
2d6c1f3c46 | ||
|
|
161e10d2d1 | ||
|
|
a9a2a91183 | ||
|
|
1c9a6f108e | ||
|
|
d6adf9b736 | ||
|
|
959eb3f782 | ||
|
|
7a53e0c90c | ||
|
|
533b87fc5b | ||
|
|
15713cf7fe | ||
|
|
31dc756868 | ||
|
|
52f6b6130f | ||
|
|
16945b3d5b | ||
|
|
bdc664fc44 | ||
|
|
9555ef10e0 | ||
|
|
49e6cb26fc | ||
|
|
3ace29e692 | ||
|
|
aa9dd0129b | ||
|
|
1464271fbd | ||
|
|
754f145559 | ||
|
|
6afd0cb955 | ||
|
|
d32906702a | ||
|
|
9bcdaf6bd8 | ||
|
|
db82a8cf08 | ||
|
|
a9e8b2b01f | ||
|
|
85bd1ce8d6 | ||
|
|
4d09243efd | ||
|
|
5934056fe6 | ||
|
|
2a81062fa3 | ||
|
|
fdc868323f | ||
|
|
593b3a4cdd | ||
|
|
2b12e18e6c | ||
|
|
345ed80ec8 | ||
|
|
29dc1ae250 | ||
|
|
9fdd41b134 | ||
|
|
31ee5e8ffb | ||
|
|
d7922bb71d | ||
|
|
fa3ac91ba4 | ||
|
|
e7c152e955 | ||
|
|
0223b5c104 | ||
|
|
9e41a7c446 | ||
|
|
2ba0ffc1b7 | ||
|
|
7d038e1266 | ||
|
|
b98285f314 | ||
|
|
73438da666 | ||
|
|
85f2e1b579 | ||
|
|
ece89ebad0 | ||
|
|
6e2dd39246 | ||
|
|
a61286e534 | ||
|
|
4f944a5466 | ||
|
|
d29aac088a | ||
|
|
8abd122773 | ||
|
|
08084aa0bc | ||
|
|
e69cd5a73c | ||
|
|
76aa3bdc64 | ||
|
|
93251104af | ||
|
|
3cae477f3e | ||
|
|
25c736dc0a | ||
|
|
96a09d8980 | ||
|
|
72387235a0 | ||
|
|
1b00e505b7 | ||
|
|
1c54e47b9e | ||
|
|
ba07e2c905 | ||
|
|
bde4611a50 | ||
|
|
e7326fea7b | ||
|
|
d13b23ad2e | ||
|
|
8b1830a711 | ||
|
|
b70c530754 | ||
|
|
d90e24f9ed | ||
|
|
1fbd521d1a | ||
|
|
2ae6183e7f | ||
|
|
7905911624 | ||
|
|
c5b6b33d8e | ||
|
|
5d29fd6d3b | ||
|
|
ad8f48f36b | ||
|
|
f9843c13d4 | ||
|
|
6bd561b094 | ||
|
|
d2c6238df1 | ||
|
|
1d108983e8 | ||
|
|
b768bca638 | ||
|
|
28fcd6c9ce | ||
|
|
10559a925c | ||
|
|
942e218a9e | ||
|
|
f6af9edc38 | ||
|
|
e0f6331ec3 | ||
|
|
06f0c6caa7 | ||
|
|
56ec260e3a | ||
|
|
176cf84369 | ||
|
|
6de3b722ed | ||
|
|
2cf6326764 | ||
|
|
ec27ee58b4 | ||
|
|
4e42e2202e | ||
|
|
e60d8eceb7 | ||
|
|
08fb939b38 | ||
|
|
482dd73afd | ||
|
|
f09a9fee75 | ||
|
|
9a31d14b41 | ||
|
|
2fd7f88f04 | ||
|
|
9d4cc802e9 | ||
|
|
ee6b4827fa | ||
|
|
48d8c528f6 | ||
|
|
40c0a5ac64 | ||
|
|
3a60bcc174 | ||
|
|
2b3fad16fd | ||
|
|
f0cf6bf5c8 | ||
|
|
0ba4e3240b | ||
|
|
9332b17fc1 | ||
|
|
4ec4023f40 | ||
|
|
d9971541f2 | ||
|
|
7b0e4fcc73 | ||
|
|
cfde73d13a | ||
|
|
c17c9000a8 | ||
|
|
42d537a68b | ||
|
|
25eebec8f7 | ||
|
|
bbe5b01872 | ||
|
|
6b31536de5 | ||
|
|
2e5db5500f | ||
|
|
7038d31c53 | ||
|
|
3eb27c3d35 | ||
|
|
a9c3a1bcec | ||
|
|
384926e73a | ||
|
|
4335c12659 | ||
|
|
e6e4829164 | ||
|
|
f3c67cf598 | ||
|
|
4681d468ce | ||
|
|
63e7d3d5f5 | ||
|
|
f47d8c8ce3 | ||
|
|
6f69f45ddc | ||
|
|
e73678c788 | ||
|
|
09a2f91cbf | ||
|
|
29da7499a4 | ||
|
|
5b024e9443 | ||
|
|
225932eff1 | ||
|
|
65d5f5ae86 | ||
|
|
3e647ef14d | ||
|
|
7cb3aea2e6 | ||
|
|
7f4b8f1c8a | ||
|
|
0a2710b865 | ||
|
|
2a301c4983 | ||
|
|
faa8131a1b | ||
|
|
71bd885bd0 | ||
|
|
691a1e50f0 | ||
|
|
ef6e9fd16d | ||
|
|
17f9ac6d54 | ||
|
|
3f8e6e48c0 | ||
|
|
bda4fdf69d | ||
|
|
5c85ed13fd | ||
|
|
1986901031 | ||
|
|
e1d3ec21e5 | ||
|
|
f45283dade | ||
|
|
31c44d8df7 | ||
|
|
bf443963c8 | ||
|
|
a0eb234539 | ||
|
|
b6d670c240 | ||
|
|
b5fb2c42c6 | ||
|
|
d72cc529ba | ||
|
|
660bd00cae | ||
|
|
b5489711ec | ||
|
|
76717c4f8a | ||
|
|
3d53d0bcd6 | ||
|
|
c7c9428b68 | ||
|
|
991a970d6a | ||
|
|
cbe93b9f7e | ||
|
|
5d7217b775 | ||
|
|
d6836b8bcf | ||
|
|
c367651c78 | ||
|
|
77123fd971 | ||
|
|
9d73a6837b | ||
|
|
651f0157dc | ||
|
|
90e8dbe449 | ||
|
|
ccba2667bc | ||
|
|
3ce9fc9790 | ||
|
|
2f24dd77bf | ||
|
|
2bc07cb3df | ||
|
|
30678dbbb4 | ||
|
|
c5b0f69b51 | ||
|
|
e593f2cba4 | ||
|
|
10f7499066 | ||
|
|
36b7e495f7 | ||
|
|
94b96e3c19 | ||
|
|
0d1ee18da0 | ||
|
|
cab0b61ee0 | ||
|
|
8e6611d76d | ||
|
|
1ef82e5f93 | ||
|
|
43dc962606 | ||
|
|
020d674ca2 | ||
|
|
bb0e1081cc | ||
|
|
5162f9ce3b | ||
|
|
57fae7fe4b | ||
|
|
17412d7de7 | ||
|
|
d59f40dfba | ||
|
|
5953be63cb | ||
|
|
58a4311947 | ||
|
|
c5a9b9a15f | ||
|
|
716c344780 | ||
|
|
9af8c4897b | ||
|
|
ca72024a68 | ||
|
|
0d2bc585a9 | ||
|
|
4e3edefb35 | ||
|
|
9408242726 | ||
|
|
4710208e81 | ||
|
|
4fc6a1e818 | ||
|
|
c9b79a074b | ||
|
|
2e79eb346f | ||
|
|
3f88bd4158 | ||
|
|
f58e079741 | ||
|
|
6f1eb1f4b9 | ||
|
|
826d529997 | ||
|
|
43e60eab4a | ||
|
|
6c33024790 | ||
|
|
d27e625fde | ||
|
|
23cecb9360 | ||
|
|
7e4c835ced | ||
|
|
aff460f555 | ||
|
|
52961b459e | ||
|
|
0af2f867fc | ||
|
|
85e291e0b8 | ||
|
|
6d8a859b20 | ||
|
|
a70dfb0769 | ||
|
|
c637d412e6 | ||
|
|
e996bc2d7f | ||
|
|
15be047371 | ||
|
|
0a0e0bca10 | ||
|
|
9a8f3bd161 | ||
|
|
7e2c035692 | ||
|
|
44b2ade9bc | ||
|
|
1200d02fbf | ||
|
|
b020f48325 | ||
|
|
917857f1ff | ||
|
|
69d8ff1034 | ||
|
|
9a334101ca | ||
|
|
ee53b3d9c4 | ||
|
|
01a5ad5302 | ||
|
|
f12f0e1f84 | ||
|
|
6aefcdbed8 | ||
|
|
3d22a2ef65 | ||
|
|
a33c6dbf1a | ||
|
|
2b7c779e14 | ||
|
|
0e36f7c0b3 | ||
|
|
228a309545 | ||
|
|
b15ad8eb5e | ||
|
|
a525735b0b | ||
|
|
6a58af8dfb | ||
|
|
0089e63832 | ||
|
|
d4f00eb89f | ||
|
|
d15e6e395b | ||
|
|
39eb4bef07 | ||
|
|
03de576d8c | ||
|
|
216b57a4c7 | ||
|
|
5383d2d40e | ||
|
|
1d7a2013e3 | ||
|
|
24d2908cca | ||
|
|
330845a387 | ||
|
|
bbedd01a72 | ||
|
|
2b07061c18 | ||
|
|
01a3c81359 | ||
|
|
96e275efa6 | ||
|
|
12eb6c73c3 | ||
|
|
4166eddd28 | ||
|
|
6ea1592c19 | ||
|
|
f8799a073c | ||
|
|
0eb83fc930 | ||
|
|
a5dd3946f8 | ||
|
|
2732df24af | ||
|
|
f0ae27a50b | ||
|
|
c5037ea397 | ||
|
|
695aaedfba | ||
|
|
4f71d874bd | ||
|
|
c69729fadd | ||
|
|
64d04996af | ||
|
|
8eea510583 | ||
|
|
04c2b246f6 | ||
|
|
a46eb176d7 | ||
|
|
2bea88f1a3 | ||
|
|
06617de984 | ||
|
|
6459d7c024 | ||
|
|
bd4af8039f | ||
|
|
8aaa22cea3 | ||
|
|
7d902682f8 | ||
|
|
a81be99100 | ||
|
|
b6dfe93d2c | ||
|
|
35aa022984 | ||
|
|
dfe2d4cc37 | ||
|
|
1d16502d32 | ||
|
|
25c88187a3 | ||
|
|
ac04e846fa | ||
|
|
29985e2118 | ||
|
|
3b74dfd49a | ||
|
|
6abcc49ed4 | ||
|
|
f16e1cd7a6 | ||
|
|
4341b8a24b | ||
|
|
a89e11d132 | ||
|
|
bc91a8cff2 | ||
|
|
8040010b98 | ||
|
|
b39f15c798 | ||
|
|
c3cf49c63e | ||
|
|
899bd7e316 | ||
|
|
890727d495 | ||
|
|
8a8e69596a | ||
|
|
58fcc92e4d | ||
|
|
0cd795f57a | ||
|
|
4830be6388 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -154,10 +154,6 @@ PublishScripts/
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
|
||||
# 把 Yi.Vben5.Vue3 下的 packages 目录重新放出来
|
||||
!**/Yi.Vben5.Vue3/packages/
|
||||
!**/Yi.Vben5.Vue3/packages/**
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
@@ -269,6 +265,7 @@ src/Acme.BookStore.Blazor.Server.Tiered/Logs/*
|
||||
**/wwwroot/libs/*
|
||||
public
|
||||
dist
|
||||
dist - 副本
|
||||
.vscode
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Development.json
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/appsettings.Production.json
|
||||
@@ -281,3 +278,5 @@ database_backup
|
||||
/Yi.Abp.Net8/src/Yi.Abp.Web/yi-abp-dev.db
|
||||
|
||||
package-lock.json
|
||||
|
||||
.claude
|
||||
|
||||
75
README.md
75
README.md
@@ -1,6 +1,6 @@
|
||||
<h1 align="center"><img align="left" height="150px" src="https://ccnetcore.com/prod-api/wwwroot/logo.png"> Yi框架</h1>
|
||||
<h4 align="center">一套以用户体验出发的.Net8 Web开源框架</h4>
|
||||
<h5 align="center">支持Abp.vNext 版本原生版本、Furion版本,前端接入Vben/Ruoyi/Pure Vue</h5>
|
||||
<h5 align="center">支持Abp.vNext 版本原生版本、Furion版本,前端接入Ruoyi/Pure Vue</h5>
|
||||
<h2 align="center">集大成者,终究轮子</h2>
|
||||
|
||||
[](https://gitee.com/ccnetcore/Yi)
|
||||
@@ -39,17 +39,14 @@ Yi框架-一套与SqlSugar一样爽的.Net8开源框架。
|
||||
|
||||
**分支目录:**
|
||||
|
||||
- 分支**main**: 基于Abp.vNext分支,默认分支,只使用Rbac权限管理后台
|
||||
- 分支**abp**: 基于Abp.vNext分支,完整分支,具备超多内置模块
|
||||
|
||||
- 分支**Abp**: 基于Abp.vNext分支,DDD领域驱动设计,回归开发本质,极度简单,一个后台支持以下多个前端
|
||||
|
||||
- Yi.Abp.Net8:后端
|
||||
- Yi.Bbs.Vue3:Bbs社区 前端
|
||||
- Yi.Doc.Md: 开源文档教程
|
||||
- Yi.Vben5.Vue3:Vben ts后台前端
|
||||
- Yi.Pure.Vue3:Pure ts后台前端
|
||||
- Yi.RuoYi.Vue3:RuoYi js后台前端
|
||||
|
||||
|
||||
****
|
||||
## 🍉 docker 一键启动
|
||||
|
||||
@@ -59,7 +56,7 @@ Yi框架-一套与SqlSugar一样爽的.Net8开源框架。
|
||||
|
||||
bbs前端:`docker run -d --name yi.bbs -p 18001:18001 -v /home/Yi/Yi.Bbs.Vue3/yi-bbs.conf:/etc/nginx/conf.d/yi-bbs.conf jiftcc/yi.bbs:last`
|
||||
|
||||
> 另外我们提供docker的build操作,我们更希望你能通过此种方式二开构建属于自己的镜像,因为上面镜像更新不及时
|
||||
> 另外我们提供docker的build操作,我们更希望你能通过此种方式二开构建属于自己的镜像
|
||||
|
||||
****
|
||||
|
||||
@@ -67,24 +64,11 @@ bbs前端:`docker run -d --name yi.bbs -p 18001:18001 -v /home/Yi/Yi.Bbs.Vue3/
|
||||
|
||||
废话少说直接上地址
|
||||
|
||||
- Yi社区官网网址(Bbs社区正式):[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
Yi社区官网网址(Bbs社区正式):[ccnetcore.com](https://ccnetcore.com) (已上线,欢迎加入)
|
||||
|
||||
DotNet后端主要由:SharpDance 意框架官方团队 及 数百名 开源用户 共同维护
|
||||
Rbac后台演示地址:https://data.ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
|
||||
- Vben后台演示地址:https://data.ccnetcore.com:2000 (用户cc、密码123456)
|
||||
|
||||
Vben前端主要由:【https://gitee.com/vichen2021】贡献维护
|
||||
|
||||
|
||||
- Ruoyi后台演示地址:https://data.ccnetcore.com:1000 (用户cc、密码123456)
|
||||
|
||||
Ruoyi前端主要由:30多名开源用户共同贡献维护
|
||||
|
||||
|
||||
- Pure后台演示地址:https://data.ccnetcore.com:1001 (用户cc、密码123456)
|
||||
|
||||
Pure前端主要由:3名开源用户共同贡献维护
|
||||
Pure后台演示地址:https://data.ccnetcore.com:1001 (用户cc、密码123456)
|
||||
|
||||
## 🍏 支持:
|
||||
|
||||
@@ -134,13 +118,8 @@ Pure前端主要由:3名开源用户共同贡献维护
|
||||
- [SqlSugar官网](https://www.donet5.com/home/doc)
|
||||
|
||||
## 🍅 内置模块简介
|
||||
|
||||
- rbac 权限管理系统(已上线)(支持vben、pure、ruoyi前端)
|
||||
- bbs 论坛社区系统(已上线)
|
||||
- ai-stock Ai模拟炒股系统(已上线)
|
||||
- chat-hub Ai在线聊天室系统(已上线)
|
||||
- code-gen 代码生成器工具系统(已上线)
|
||||
- digital-collectibles 数字藏品小程序系统(已上线)
|
||||
- Rbac权限管理系统(已上线)(支持pure、ruoyi前端)
|
||||
- Bbs论坛社区系统(已上线)
|
||||
|
||||
> 重复的东西,无需再写一遍,这也是优雅的体现之一
|
||||
|
||||
@@ -161,6 +140,14 @@ C# Asp.NetCore 8.0
|
||||
- [x] 分布式缓存:Abp.vNext
|
||||
- [x] 事件总线:Abp.vNext
|
||||
|
||||
#### 前端
|
||||
js Vue3
|
||||
- [x] 异步请求:axios
|
||||
- [x] 图表:echarts
|
||||
- [x] ui:element-plus
|
||||
- [x] 存储:pinia
|
||||
- [x] 路由:vue-router
|
||||
- [x] 打包:vite
|
||||
|
||||
#### 运维
|
||||
- [x] 部署:nginx
|
||||
@@ -187,16 +174,24 @@ C# Asp.NetCore 8.0
|
||||
- 缓存列表
|
||||
- 服务监控
|
||||
|
||||
#### 🍐 BBS社区论坛系统(持续更新)
|
||||
(采用vue3前端)
|
||||
- 文章功能
|
||||
- 板块功能
|
||||
- 主题功能
|
||||
- 个人中心
|
||||
- 授权中心
|
||||
- 权限管理
|
||||
|
||||
#### 🍉 演示截图:
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="readme/303.png"/></td>
|
||||
<td><img src="readme/304.png"/></td>
|
||||
<td><img src="readme/101.png"/></td>
|
||||
<td><img src="readme/102.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="readme/301.png"/></td>
|
||||
<td><img src="readme/302.png"/></td>
|
||||
<td><img src="readme/103.png"/></td>
|
||||
<td><img src="readme/104.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -267,8 +262,6 @@ C# Asp.NetCore 8.0
|
||||
|
||||
[Furion百小僧]https://furion.baiqian.ltd/
|
||||
|
||||
[du白]https://gitee.com/vichen2021
|
||||
|
||||
****
|
||||
## 🌽 联系我们:
|
||||
|
||||
@@ -276,7 +269,7 @@ C# Asp.NetCore 8.0
|
||||
|
||||
QQ交流群:官方一群(已满)、官方二群(已满)、官方三群:`786308927`(已满)、官方四群:`498310311`(已满)、官方五群:`981136525`
|
||||
|
||||
微信交流群:官方微信一群(已满)、官方微信二群(已满)、官方微信三群(已满)、官方微信四群(即满)
|
||||
微信交流群:官方微信一群(已满)、官方微信二群(已满)、官方微信三群
|
||||
|
||||
微信交流群:加作者微信 chengzilaoge520 (橙子老哥520),备注拉群
|
||||
|
||||
@@ -287,12 +280,6 @@ QQ交流群:官方一群(已满)、官方二群(已满)、官方三群
|
||||
****
|
||||
## 🍄 FQA:
|
||||
|
||||
如何修改仓库代码:请直接pr即可,官方团队会第一时间处理,目前前端都是pr来的
|
||||
|
||||
gitee仓库官方地址:https://gitee.com/ccnetcore/Yi
|
||||
|
||||
github仓库官方地址:https://github.com/ccnetcore/Yi.Abp.Admin
|
||||
|
||||
前往官网查看留言区:
|
||||
前往官网查看留言区
|
||||
|
||||
[留言区](https://ccnetcore.com/discuss/1641030787056930818)
|
||||
11
Yi.Abp.Net8/.claude/settings.local.json
Normal file
11
Yi.Abp.Net8/.claude/settings.local.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(dotnet build \"E:\\code\\github\\Yi\\Yi.Abp.Net8\\module\\ai-hub\\Yi.Framework.AiHub.Application\\Yi.Framework.AiHub.Application.csproj\" --no-restore)",
|
||||
"Read(//e/code/github/Yi/Yi.Ai.Vue3/**)",
|
||||
"Bash(dotnet build:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
129
Yi.Abp.Net8/CLAUDE.md
Normal file
129
Yi.Abp.Net8/CLAUDE.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Overview
|
||||
|
||||
Yi.Abp.Net8 is a modular, multi-tenant SaaS platform built on ABP Framework 8.3.4 with .NET 8.0. It uses **SqlSugar** (not EF Core) as the ORM and follows Domain-Driven Design (DDD) principles. The platform includes AI/ML features (chat, models, agents, token tracking), RBAC, forum, messaging, and digital collectibles modules.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Solution Structure
|
||||
|
||||
```
|
||||
Yi.Abp.Net8/
|
||||
├── src/ # Main application host
|
||||
│ └── Yi.Abp.Web/ # ASP.NET Core 8.0 Web Host (port 19001)
|
||||
├── framework/ # Framework layer (shared infrastructure)
|
||||
│ ├── Yi.Framework.Core # Core utilities, JSON handling
|
||||
│ ├── Yi.Framework.SqlSugarCore # SqlSugar ORM abstraction (v5.1.4.197-preview22)
|
||||
│ ├── Yi.Framework.SqlSugarCore.Abstractions # Repository interfaces
|
||||
│ ├── Yi.Framework.AspNetCore # ASP.NET Core extensions
|
||||
│ ├── Yi.Framework.AspNetCore.Authentication.OAuth # QQ, Gitee OAuth
|
||||
│ ├── Yi.Framework.Ddd.Application # DDD application base classes
|
||||
│ ├── Yi.Framework.BackgroundWorkers.Hangfire # Job scheduling
|
||||
│ ├── Yi.Framework.Caching.FreeRedis # Redis caching
|
||||
│ └── Yi.Framework.SemanticKernel # AI/ML integration
|
||||
├── module/ # Business modules (each follows 5-layer DDD pattern)
|
||||
│ ├── ai-hub/ # AI services (chat, models, sessions, agents)
|
||||
│ ├── rbac/ # Role-Based Access Control (core auth/authz)
|
||||
│ ├── bbs/ # Forum/community
|
||||
│ ├── chat-hub/ # Real-time messaging
|
||||
│ ├── audit-logging/ # Audit trail tracking
|
||||
│ ├── code-gen/ # Code generation
|
||||
│ ├── tenant-management/ # Multi-tenancy support
|
||||
│ ├── digital-collectibles/ # NFT/digital assets
|
||||
│ └── ai-stock/ # AI-powered stock analysis
|
||||
├── test/ # Unit tests (xUnit + NSubstitute + Shouldly)
|
||||
├── client/ # HTTP API clients
|
||||
└── tool/ # Development utilities
|
||||
```
|
||||
|
||||
### Module Structure (DDD Layers)
|
||||
|
||||
Each module follows this pattern:
|
||||
|
||||
```
|
||||
module/[feature]/
|
||||
├── [Feature].Domain.Shared/ # Constants, enums, shared DTOs
|
||||
├── [Feature].Domain/ # Entities, aggregates, domain services
|
||||
├── [Feature].Application.Contracts/ # Service interfaces, DTOs
|
||||
├── [Feature].Application/ # Application services (implementations)
|
||||
└── [Feature].SqlSugarCore/ # Repository implementations, DbContext
|
||||
```
|
||||
|
||||
**Dependency Flow:** Application → Domain + Application.Contracts → Domain.Shared → Framework
|
||||
|
||||
### Module Registration
|
||||
|
||||
All modules are registered in `src/Yi.Abp.Web/YiAbpWebModule.cs`. When adding a new module:
|
||||
|
||||
1. Add `DependsOn` attribute in `YiAbpWebModule`
|
||||
2. Add conventional controller in `PreConfigureServices`:
|
||||
```csharp
|
||||
options.ConventionalControllers.Create(typeof(YiFramework[Feature]ApplicationModule).Assembly,
|
||||
option => option.RemoteServiceName = "[service-name]");
|
||||
```
|
||||
|
||||
### API Routing
|
||||
|
||||
All API routes use the unified prefix: `/api/app/{service-name}/{controller}/{action}`
|
||||
|
||||
Registered service names:
|
||||
- `default` - Main application services
|
||||
- `rbac` - Authentication, authorization, user/role management
|
||||
- `ai-hub` - AI chat, models, sessions, agents
|
||||
- `bbs` - Forum posts and comments
|
||||
- `chat-hub` - Real-time messaging
|
||||
- `tenant-management` - Multi-tenant configuration
|
||||
- `code-gen` - Code generation utilities
|
||||
- `digital-collectibles` - NFT/digital assets
|
||||
- `ai-stock` - Stock analysis
|
||||
|
||||
## Database
|
||||
|
||||
**ORM:** SqlSugar (NOT Entity Framework Core)
|
||||
|
||||
**Configuration** (`appsettings.json`):
|
||||
```json
|
||||
"DbConnOptions": {
|
||||
"Url": "DataSource=yi-abp-dev.db",
|
||||
"DbType": "Sqlite", // Sqlite, Mysql, Sqlserver, Oracle, PostgreSQL
|
||||
"EnabledCodeFirst": true, // Auto-create tables
|
||||
"EnabledDbSeed": true, // Auto-seed data
|
||||
"EnabledSaasMultiTenancy": true
|
||||
}
|
||||
```
|
||||
|
||||
**Multi-tenancy:** Tenant isolation via `HeaderTenantResolveContributor` (NOT cookie-based). Tenant is resolved from `__tenant` header.
|
||||
|
||||
## Key Technologies
|
||||
|
||||
| Component | Technology |
|
||||
|-----------|-----------|
|
||||
| Framework | ABP 8.3.4 |
|
||||
| .NET Version | .NET 8.0 |
|
||||
| ORM | SqlSugar 5.1.4.197-preview22 |
|
||||
| Authentication | JWT Bearer + Refresh Tokens |
|
||||
| OAuth | QQ, Gitee |
|
||||
| Caching | FreeRedis (optional) |
|
||||
| Background Jobs | Hangfire (in-memory or Redis) |
|
||||
| Logging | Serilog (daily rolling files) |
|
||||
| Testing | xUnit + NSubstitute + Shouldly |
|
||||
| Container | Autofac |
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **JSON Serialization:** Uses Microsoft's `System.Text.Json`, NOT Newtonsoft.Json. Date format handled via `DatetimeJsonConverter`.
|
||||
- **Multi-tenancy:** Tenant resolved from `__tenant` header, NOT cookies.
|
||||
- **Rate Limiting:** Disabled in development, enabled in production (1000 req/60s sliding window).
|
||||
- **Swagger:** Available at `/swagger` in development.
|
||||
- **Hangfire Dashboard:** Available at `/hangfire` (requires JWT authorization).
|
||||
- **Background Workers:** Disabled in development (`AbpBackgroundWorkerOptions.IsEnabled = false`).
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. **Branch:** Main branch is `abp`, current development branch is `ai-hub`.
|
||||
2. **Commit Convention:** Chinese descriptive messages with prefixes (`feat:`, `fix:`, `style:`).
|
||||
3. **Testing:** Run `dotnet test` before committing.
|
||||
4. **Building:** Use `dotnet build --no-restore` for faster builds after initial restore.
|
||||
@@ -64,6 +64,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Domain.Sh
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.SqlSugarCore", "module\rbac\Yi.Framework.Rbac.SqlSugarCore\Yi.Framework.Rbac.SqlSugarCore.csproj", "{4503A2F9-139D-4CBC-AF11-689C34F0D77B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bbs", "bbs", "{E902A945-4F41-4E96-A0DA-9F66CDA22261}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Domain.Shared", "module\bbs\Yi.Framework.Bbs.Domain.Shared\Yi.Framework.Bbs.Domain.Shared.csproj", "{EB9349E2-256D-41EB-A345-21635A1361B3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Domain", "module\bbs\Yi.Framework.Bbs.Domain\Yi.Framework.Bbs.Domain.csproj", "{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Application.Contracts", "module\bbs\Yi.Framework.Bbs.Application.Contracts\Yi.Framework.Bbs.Application.Contracts.csproj", "{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.Application", "module\bbs\Yi.Framework.Bbs.Application\Yi.Framework.Bbs.Application.csproj", "{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Bbs.SqlSugarCore", "module\bbs\Yi.Framework.Bbs.SqlSugarCore\Yi.Framework.Bbs.SqlSugarCore.csproj", "{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "audit-logging", "audit-logging", "{73CCF2C4-B9FD-44AB-8D4B-0A421805B094}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.AuditLogging.SqlSugarCore", "module\audit-logging\Yi.Framework.AuditLogging.SqlSugarCore\Yi.Framework.AuditLogging.SqlSugarCore.csproj", "{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}"
|
||||
@@ -86,8 +98,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManageme
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.TenantManagement.Application.Contracts", "module\tenant-management\Yi.Framework.TenantManagement.Application.Contracts\Yi.Framework.TenantManagement.Application.Contracts.csproj", "{FA735055-CBDD-4EFD-B84B-85810DA1425E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code-gen", "code-gen", "{4FFE7212-21F2-476D-B628-3C65E6C5075E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application", "module\code-gen\Yi.Framework.CodeGen.Application\Yi.Framework.CodeGen.Application.csproj", "{97EC40D7-DBFA-467A-98CB-221AF27B14F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Application.Contracts", "module\code-gen\Yi.Framework.CodeGen.Application.Contracts\Yi.Framework.CodeGen.Application.Contracts.csproj", "{882BC563-2F75-4B95-AC96-F4BF23F5E69D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain", "module\code-gen\Yi.Framework.CodeGen.Domain\Yi.Framework.CodeGen.Domain.csproj", "{85CB8517-2B80-42D8-B954-081079AC9BA0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.Domain.Shared", "module\code-gen\Yi.Framework.CodeGen.Domain.Shared\Yi.Framework.CodeGen.Domain.Shared.csproj", "{EEFF0F05-2709-4151-A8CE-667935CEAE0B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Caching.FreeRedis", "framework\Yi.Framework.Caching.FreeRedis\Yi.Framework.Caching.FreeRedis.csproj", "{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.CodeGen.SqlSugarCore", "module\code-gen\Yi.Framework.CodeGen.SqlSugarCore\Yi.Framework.CodeGen.SqlSugarCore.csproj", "{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{8B27846A-043D-4F2F-8140-5CEC9D1863B5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.HttpApi.Client", "client\Yi.Abp.HttpApi.Client\Yi.Abp.HttpApi.Client.csproj", "{6B554DCC-3A81-4624-9141-4E39365ADA35}"
|
||||
@@ -102,6 +126,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SettingManagem
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.SettingManagement.SqlSugarCore", "module\setting-management\Yi.Framework.SettingManagement.SqlSugarCore\Yi.Framework.SettingManagement.SqlSugarCore.csproj", "{495C4643-39D4-46E7-BDC8-237589627BE4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "chat-hub", "chat-hub", "{D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Application.Contracts", "module\chat-hub\Yi.Framework.ChatHub.Application.Contracts\Yi.Framework.ChatHub.Application.Contracts.csproj", "{65D4D033-5504-44B9-B152-0172ACD64CE6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Domain.Shared", "module\chat-hub\Yi.Framework.ChatHub.Domain.Shared\Yi.Framework.ChatHub.Domain.Shared.csproj", "{DEEC0B15-190C-4464-B469-C45C6563C592}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.SqlSugarCore", "module\chat-hub\Yi.Framework.ChatHub.SqlSugarCore\Yi.Framework.ChatHub.SqlSugarCore.csproj", "{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Domain", "module\chat-hub\Yi.Framework.ChatHub.Domain\Yi.Framework.ChatHub.Domain.csproj", "{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ChatHub.Application", "module\chat-hub\Yi.Framework.ChatHub.Application\Yi.Framework.ChatHub.Application.csproj", "{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.Rbac.Test", "test\Yi.Framework.Rbac.Test\Yi.Framework.Rbac.Test.csproj", "{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tool", "tool", "{084CBEEC-5D37-4716-B9C7-D80D6960DFF4}"
|
||||
@@ -122,10 +158,46 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Abp.Tool.HttpApi.Client"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.SettingManagement.Application", "module\setting-management\Yi.Framework.SettingManagement.Application\Yi.Framework.SettingManagement.Application.csproj", "{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "digital-collectibles", "digital-collectibles", "{B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollectibles.Application", "module\digital-collectibles\Yi.Framework.DigitalCollectibles.Application\Yi.Framework.DigitalCollectibles.Application.csproj", "{236B88D4-F018-4A5F-A506-7458F2308C70}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollectibles.Application.Contracts", "module\digital-collectibles\Yi.Framework.DigitalCollectibles.Application.Contracts\Yi.Framework.DigitalCollectibles.Application.Contracts.csproj", "{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollectibles.Domain", "module\digital-collectibles\Yi.Framework.DigitalCollectibles.Domain\Yi.Framework.DigitalCollectibles.Domain.csproj", "{9B5CAE1A-E062-4C9B-8121-E58FBF69309C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollectibles.Domain.Shared", "module\digital-collectibles\Yi.Framework.DigitalCollectibles.Domain.Shared\Yi.Framework.DigitalCollectibles.Domain.Shared.csproj", "{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.DigitalCollectibles.SqlSugarCore", "module\digital-collectibles\Yi.Framework.DigitalCollectibles.SqlSugarCore\Yi.Framework.DigitalCollectibles.SqlSugarCore.csproj", "{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.WeChat.MiniProgram", "framework\Yi.Framework.WeChat.MiniProgram\Yi.Framework.WeChat.MiniProgram.csproj", "{81CEA2ED-917B-41D8-BE0D-39A785B050C0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.BackgroundWorkers.Hangfire", "framework\Yi.Framework.BackgroundWorkers.Hangfire\Yi.Framework.BackgroundWorkers.Hangfire.csproj", "{862CA181-BEE6-4870-82D2-B662E527ED8C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ai-stock", "ai-stock", "{DB46873F-981A-43D8-91B0-D464CCB65943}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application", "module\ai-stock\Yi.Framework.Stock.Application\Yi.Framework.Stock.Application.csproj", "{B79CE23C-10F8-48A5-A039-5940A188CF5A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Application.Contracts", "module\ai-stock\Yi.Framework.Stock.Application.Contracts\Yi.Framework.Stock.Application.Contracts.csproj", "{846B781A-B77E-4F86-A31F-0B5B57AB0775}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain", "module\ai-stock\Yi.Framework.Stock.Domain\Yi.Framework.Stock.Domain.csproj", "{162821E4-8FE0-4A68-B3C0-49BD6596446F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.Domain.Shared", "module\ai-stock\Yi.Framework.Stock.Domain.Shared\Yi.Framework.Stock.Domain.Shared.csproj", "{10273544-715D-4BB3-893C-6F010D947BDD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.Stock.SqlSugarCore", "module\ai-stock\Yi.Framework.Stock.SqlSugarCore\Yi.Framework.Stock.SqlSugarCore.csproj", "{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ai-hub", "ai-hub", "{7AD5DBAE-44F9-474B-8F7B-837EDE908934}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AiHub.Application", "module\ai-hub\Yi.Framework.AiHub.Application\Yi.Framework.AiHub.Application.csproj", "{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AiHub.Application.Contracts", "module\ai-hub\Yi.Framework.AiHub.Application.Contracts\Yi.Framework.AiHub.Application.Contracts.csproj", "{123D1C81-D667-4060-8E85-FFE7FB4584AD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AiHub.Domain", "module\ai-hub\Yi.Framework.AiHub.Domain\Yi.Framework.AiHub.Domain.csproj", "{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AiHub.Domain.Shared", "module\ai-hub\Yi.Framework.AiHub.Domain.Shared\Yi.Framework.AiHub.Domain.Shared.csproj", "{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.AiHub.SqlSugarCore", "module\ai-hub\Yi.Framework.AiHub.SqlSugarCore\Yi.Framework.AiHub.SqlSugarCore.csproj", "{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -204,6 +276,26 @@ Global
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -240,10 +332,30 @@ Global
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -264,6 +376,26 @@ Global
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -300,6 +432,26 @@ Global
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{236B88D4-F018-4A5F-A506-7458F2308C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{236B88D4-F018-4A5F-A506-7458F2308C70}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{236B88D4-F018-4A5F-A506-7458F2308C70}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{236B88D4-F018-4A5F-A506-7458F2308C70}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9B5CAE1A-E062-4C9B-8121-E58FBF69309C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9B5CAE1A-E062-4C9B-8121-E58FBF69309C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9B5CAE1A-E062-4C9B-8121-E58FBF69309C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9B5CAE1A-E062-4C9B-8121-E58FBF69309C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81CEA2ED-917B-41D8-BE0D-39A785B050C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -308,6 +460,46 @@ Global
|
||||
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{862CA181-BEE6-4870-82D2-B662E527ED8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B79CE23C-10F8-48A5-A039-5940A188CF5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B79CE23C-10F8-48A5-A039-5940A188CF5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B79CE23C-10F8-48A5-A039-5940A188CF5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B79CE23C-10F8-48A5-A039-5940A188CF5A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{846B781A-B77E-4F86-A31F-0B5B57AB0775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{846B781A-B77E-4F86-A31F-0B5B57AB0775}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{846B781A-B77E-4F86-A31F-0B5B57AB0775}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{846B781A-B77E-4F86-A31F-0B5B57AB0775}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{162821E4-8FE0-4A68-B3C0-49BD6596446F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{162821E4-8FE0-4A68-B3C0-49BD6596446F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{162821E4-8FE0-4A68-B3C0-49BD6596446F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{162821E4-8FE0-4A68-B3C0-49BD6596446F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{10273544-715D-4BB3-893C-6F010D947BDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{10273544-715D-4BB3-893C-6F010D947BDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{10273544-715D-4BB3-893C-6F010D947BDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{10273544-715D-4BB3-893C-6F010D947BDD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5F49318F-E6C7-4194-BAE0-83D4FB8D1983}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{123D1C81-D667-4060-8E85-FFE7FB4584AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{123D1C81-D667-4060-8E85-FFE7FB4584AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{123D1C81-D667-4060-8E85-FFE7FB4584AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{123D1C81-D667-4060-8E85-FFE7FB4584AD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -332,6 +524,12 @@ Global
|
||||
{C04D3F71-1557-46D0-B810-97B1FBB6AB73} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{A2BB899D-4F9A-4184-81BD-94B938E2AB03} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{4503A2F9-139D-4CBC-AF11-689C34F0D77B} = {9CC7A457-1236-40BA-B47B-E7B710A3F061}
|
||||
{E902A945-4F41-4E96-A0DA-9F66CDA22261} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{EB9349E2-256D-41EB-A345-21635A1361B3} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{4EABBC84-BCED-46C1-8CF1-62A7B8081ED7} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{7E569FD9-B1AB-4848-8AB7-FD9EFA1DBA20} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{AD4EE9E6-F4A3-4139-AF05-71388167DE5B} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{6C86BA71-9F87-4E2C-B467-2950D77DCDFA} = {E902A945-4F41-4E96-A0DA-9F66CDA22261}
|
||||
{73CCF2C4-B9FD-44AB-8D4B-0A421805B094} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{48806510-8E18-4E1E-9BAF-5B97E88C5FC3} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
|
||||
{791AC2FA-50D3-4408-8D68-31DA72F608BE} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
@@ -343,13 +541,25 @@ Global
|
||||
{9C8C3C53-3DCE-4516-867E-228858E61B26} = {73CCF2C4-B9FD-44AB-8D4B-0A421805B094}
|
||||
{17816837-E53B-486B-B796-53C601FE6CD9} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{FA735055-CBDD-4EFD-B84B-85810DA1425E} = {499A8C71-7892-42D0-A77E-48756E1EFF16}
|
||||
{4FFE7212-21F2-476D-B628-3C65E6C5075E} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{97EC40D7-DBFA-467A-98CB-221AF27B14F2} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{882BC563-2F75-4B95-AC96-F4BF23F5E69D} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{85CB8517-2B80-42D8-B954-081079AC9BA0} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{EEFF0F05-2709-4151-A8CE-667935CEAE0B} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{862BB0EF-3D4E-44FF-AB15-0EB74CE553D3} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{FB09ACC2-A27D-4D87-8D85-1435FDED4D04} = {4FFE7212-21F2-476D-B628-3C65E6C5075E}
|
||||
{6B554DCC-3A81-4624-9141-4E39365ADA35} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{2D23B44A-DFA3-4C36-8516-4F5AE442403C} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{00E49781-C6A0-491C-86A1-46F685C90915} = {8B27846A-043D-4F2F-8140-5CEC9D1863B5}
|
||||
{8C68059E-F3B1-4D28-A1C9-A5830F53E5D3} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{6FEE0EB3-EAD2-47F8-B6FC-3D0FD3CCABFF} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
{495C4643-39D4-46E7-BDC8-237589627BE4} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
{D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{65D4D033-5504-44B9-B152-0172ACD64CE6} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{DEEC0B15-190C-4464-B469-C45C6563C592} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{E476D266-8FB2-4D6B-AE2B-F0D279D4264E} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{C2DCA2FD-BFB4-4E76-967B-0AF8CC4F4D47} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{B7A1A8F3-CFA6-4ECF-A707-0F33FE0A6F1D} = {D8CDDE99-3684-4EED-A5E5-87F2AF4C78AB}
|
||||
{9ECF0841-53BE-4FD8-95D1-A7223C7F3A07} = {0D10EEF2-FBAE-4C72-B816-A52823FC299B}
|
||||
{4FEBBDD9-E4F4-4BAF-8599-E2D57C08A74F} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{2CE51D4C-1EF9-462B-BA14-7EA01A7E4AF1} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
@@ -359,8 +569,26 @@ Global
|
||||
{4AE84CDE-2A47-4D68-8E93-86193F72E4E8} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{C8F97775-D903-4365-A4FF-3DA97E318CD2} = {084CBEEC-5D37-4716-B9C7-D80D6960DFF4}
|
||||
{2A31D7CB-BDCC-4253-BA73-273B6B5E1956} = {8C68059E-F3B1-4D28-A1C9-A5830F53E5D3}
|
||||
{B8F76A6B-2EEB-4E64-9F26-D84584E16B9C} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{236B88D4-F018-4A5F-A506-7458F2308C70} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
|
||||
{4FE7AC0E-91CC-4DF1-ACA7-ED83483C3F3B} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
|
||||
{9B5CAE1A-E062-4C9B-8121-E58FBF69309C} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
|
||||
{FFEC9DA6-1A13-480A-AE9E-2BF8763D3061} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
|
||||
{4CE6E4AE-0BA4-4984-A4F1-A9A414B1BB8F} = {B8F76A6B-2EEB-4E64-9F26-D84584E16B9C}
|
||||
{81CEA2ED-917B-41D8-BE0D-39A785B050C0} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{862CA181-BEE6-4870-82D2-B662E527ED8C} = {77B949E9-530E-45A5-9657-20F7D5C6875C}
|
||||
{DB46873F-981A-43D8-91B0-D464CCB65943} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{B79CE23C-10F8-48A5-A039-5940A188CF5A} = {DB46873F-981A-43D8-91B0-D464CCB65943}
|
||||
{846B781A-B77E-4F86-A31F-0B5B57AB0775} = {DB46873F-981A-43D8-91B0-D464CCB65943}
|
||||
{162821E4-8FE0-4A68-B3C0-49BD6596446F} = {DB46873F-981A-43D8-91B0-D464CCB65943}
|
||||
{10273544-715D-4BB3-893C-6F010D947BDD} = {DB46873F-981A-43D8-91B0-D464CCB65943}
|
||||
{5F49318F-E6C7-4194-BAE0-83D4FB8D1983} = {DB46873F-981A-43D8-91B0-D464CCB65943}
|
||||
{7AD5DBAE-44F9-474B-8F7B-837EDE908934} = {2317227D-7796-4E7B-BEDB-7CD1CAE7B853}
|
||||
{1AD10DD2-535E-4EAB-A8A4-EC3FCA206895} = {7AD5DBAE-44F9-474B-8F7B-837EDE908934}
|
||||
{123D1C81-D667-4060-8E85-FFE7FB4584AD} = {7AD5DBAE-44F9-474B-8F7B-837EDE908934}
|
||||
{8EB4C8BB-6B21-4811-9FAB-B98FA5CA754D} = {7AD5DBAE-44F9-474B-8F7B-837EDE908934}
|
||||
{5FC6CA90-D5B4-433E-9B2C-94330FFB4C48} = {7AD5DBAE-44F9-474B-8F7B-837EDE908934}
|
||||
{8698C812-4DDC-4E80-BCD6-24C5D56AEDB1} = {7AD5DBAE-44F9-474B-8F7B-837EDE908934}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {23D6FBC9-C970-4641-BC1E-2AEA59F51C18}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.Core.Authentication;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.AspNetCore.Authentication;
|
||||
|
||||
/// <summary>
|
||||
/// 可刷新的鉴权提供者
|
||||
/// </summary>
|
||||
public class RefreshAuthenticationHandlerProvider : IRefreshAuthenticationHandlerProvider
|
||||
{
|
||||
private Dictionary<string, IAuthenticationHandler> _handlerMap =
|
||||
new Dictionary<string, IAuthenticationHandler>((IEqualityComparer<string>)StringComparer.Ordinal);
|
||||
|
||||
/// <summary>Constructor.</summary>
|
||||
/// <param name="schemes">The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider" />.</param>
|
||||
public RefreshAuthenticationHandlerProvider(IAuthenticationSchemeProvider schemes)
|
||||
{
|
||||
this.Schemes = schemes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="T:Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider" />.
|
||||
/// </summary>
|
||||
public IAuthenticationSchemeProvider Schemes { get; }
|
||||
|
||||
/// <summary>Returns the handler instance that will be used.</summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="authenticationScheme">The name of the authentication scheme being handled.</param>
|
||||
/// <returns>The handler instance.</returns>
|
||||
public async Task<IAuthenticationHandler?> GetHandlerAsync(
|
||||
HttpContext context,
|
||||
string authenticationScheme)
|
||||
{
|
||||
IAuthenticationHandler handlerAsync;
|
||||
if (this._handlerMap.TryGetValue(authenticationScheme, out handlerAsync))
|
||||
return handlerAsync;
|
||||
AuthenticationScheme schemeAsync = await this.Schemes.GetSchemeAsync(authenticationScheme);
|
||||
if (schemeAsync == null)
|
||||
return (IAuthenticationHandler)null;
|
||||
|
||||
if ((context.RequestServices.GetService(schemeAsync.HandlerType) ??
|
||||
ActivatorUtilities.CreateInstance(context.RequestServices, schemeAsync.HandlerType)) is
|
||||
IAuthenticationHandler handler)
|
||||
{
|
||||
handlerAsync = handler;
|
||||
await handler.InitializeAsync(schemeAsync, context);
|
||||
this._handlerMap[authenticationScheme] = handler;
|
||||
}
|
||||
|
||||
return handlerAsync;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 刷新鉴权
|
||||
/// </summary>
|
||||
public void RefreshAuthentication()
|
||||
{
|
||||
_handlerMap = new Dictionary<string, IAuthenticationHandler>((IEqualityComparer<string>)StringComparer.Ordinal);
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,12 @@ namespace Yi.Framework.AspNetCore.Microsoft.AspNetCore.Middlewares
|
||||
/// <returns>异步任务</returns>
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
// // 在响应开始时处理文件下载相关的响应头
|
||||
// context.Response.OnStarting(() =>
|
||||
// {
|
||||
// HandleFileDownloadResponse(context);
|
||||
// return Task.CompletedTask;
|
||||
// });
|
||||
// 在响应开始时处理文件下载相关的响应头
|
||||
context.Response.OnStarting(() =>
|
||||
{
|
||||
HandleFileDownloadResponse(context);
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
// 继续处理管道中的下一个中间件
|
||||
await next(context);
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.AspNetCore.Mvc.Conventions;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Options;
|
||||
|
||||
namespace Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.AspNetCore.Mvc;
|
||||
using Volo.Abp.AspNetCore.WebClientInfo;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.Modularity;
|
||||
using Yi.Framework.AspNetCore.Mvc;
|
||||
using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Authentication;
|
||||
using Yi.Framework.Core;
|
||||
using Yi.Framework.Core.Authentication;
|
||||
|
||||
namespace Yi.Framework.AspNetCore
|
||||
{
|
||||
@@ -35,8 +24,14 @@ namespace Yi.Framework.AspNetCore
|
||||
// 替换默认的WebClientInfoProvider为支持代理的实现
|
||||
services.Replace(new ServiceDescriptor(
|
||||
typeof(IWebClientInfoProvider),
|
||||
typeof(RealIpHttpContextWebClientInfoProvider),
|
||||
typeof(RealIpHttpContextWebClientInfoProvider),
|
||||
ServiceLifetime.Transient));
|
||||
|
||||
// 替换默认的AuthenticationHandlerProvider为支持刷新鉴权
|
||||
services.Replace(new ServiceDescriptor(
|
||||
typeof(IAuthenticationHandlerProvider),
|
||||
typeof(RefreshAuthenticationHandlerProvider),
|
||||
ServiceLifetime.Scoped));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using Hangfire;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Volo.Abp.BackgroundJobs.Hangfire;
|
||||
using Volo.Abp.BackgroundWorkers;
|
||||
using Volo.Abp.BackgroundWorkers.Hangfire;
|
||||
@@ -32,13 +33,19 @@ public sealed class YiFrameworkBackgroundWorkersHangfireModule : AbpModule
|
||||
/// <param name="context">应用程序初始化上下文</param>
|
||||
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
|
||||
{
|
||||
if (!context.ServiceProvider.GetRequiredService<IOptions<AbpBackgroundWorkerOptions>>().Value.IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 获取后台任务管理器和所有 Hangfire 后台任务
|
||||
var backgroundWorkerManager = context.ServiceProvider.GetRequiredService<IBackgroundWorkerManager>();
|
||||
var workers = context.ServiceProvider.GetServices<IHangfireBackgroundWorker>();
|
||||
|
||||
// 获取配置
|
||||
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
|
||||
|
||||
|
||||
// 检查是否启用 Redis
|
||||
var isRedisEnabled = configuration.GetValue<bool>("Redis:IsEnabled");
|
||||
|
||||
@@ -56,11 +63,11 @@ public sealed class YiFrameworkBackgroundWorkersHangfireModule : AbpModule
|
||||
{
|
||||
// 内存模式:直接使用 Hangfire
|
||||
var unProxyWorker = ProxyHelper.UnProxy(worker);
|
||||
|
||||
|
||||
// 添加或更新循环任务
|
||||
RecurringJob.AddOrUpdate(
|
||||
worker.RecurringJobId,
|
||||
(Expression<Func<Task>>)(() =>
|
||||
(Expression<Func<Task>>)(() =>
|
||||
((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(default)),
|
||||
worker.CronExpression,
|
||||
new RecurringJobOptions
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Yi.Framework.Core.Authentication;
|
||||
|
||||
public static class AuthenticationExtensions
|
||||
{
|
||||
public static void RefreshAuthentication(this HttpContext context)
|
||||
{
|
||||
var currentAuthenticationHandler =
|
||||
context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
|
||||
if (currentAuthenticationHandler is IRefreshAuthenticationHandlerProvider refreshAuthenticationHandler)
|
||||
{
|
||||
refreshAuthenticationHandler.RefreshAuthentication();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Yi.Framework.Core.Authentication;
|
||||
|
||||
public interface IRefreshAuthenticationHandlerProvider: IAuthenticationHandlerProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷新鉴权
|
||||
/// </summary>
|
||||
void RefreshAuthentication();
|
||||
}
|
||||
@@ -185,23 +185,25 @@ namespace Yi.Framework.Ddd.Application
|
||||
/// </summary>
|
||||
/// <param name="keywords">查询关键字</param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<List<TGetListOutputDto>> GetSelectDataListAsync(string? keywords = null)
|
||||
public virtual async Task<PagedResultDto<TGetListOutputDto>> GetSelectDataListAsync(string? keywords = null)
|
||||
{
|
||||
List<TEntity> entities = await Repository.GetListAsync();
|
||||
|
||||
// 获取总数并映射结果
|
||||
var totalCount = entities.Count;
|
||||
var dtos = await MapToGetListOutputDtosAsync(entities);
|
||||
|
||||
return dtos;
|
||||
return new PagedResultDto<TGetListOutputDto>(totalCount, dtos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除实体
|
||||
/// </summary>
|
||||
/// <param name="ids">实体ID集合</param>
|
||||
/// <param name="id">实体ID集合</param>
|
||||
[RemoteService(isEnabled: true)]
|
||||
public virtual async Task DeleteAsync(IEnumerable<TKey> ids)
|
||||
public virtual async Task DeleteAsync(IEnumerable<TKey> id)
|
||||
{
|
||||
await Repository.DeleteManyAsync(ids);
|
||||
await Repository.DeleteManyAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Yi.Framework.Core\Yi.Framework.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.57.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Yi.Framework.Core.Options;
|
||||
|
||||
namespace Yi.Framework.SemanticKernel;
|
||||
|
||||
public class YiFrameworkSemanticKernelModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var configuration = context.Services.GetConfiguration();
|
||||
var services = context.Services;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nito.AsyncEx;
|
||||
using SqlSugar;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
|
||||
/// <summary>
|
||||
/// 批量生成激活码输入
|
||||
/// </summary>
|
||||
public class ActivationCodeCreateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
public ActivationCodeGoodsTypeEnum GoodsType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数量
|
||||
/// </summary>
|
||||
public int Count { get; set; } = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量生成激活码列表输入
|
||||
/// </summary>
|
||||
public class ActivationCodeCreateListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成项列表
|
||||
/// </summary>
|
||||
public List<ActivationCodeCreateInput> Items { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
|
||||
/// <summary>
|
||||
/// 批量生成激活码输出
|
||||
/// </summary>
|
||||
public class ActivationCodeCreateOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
public ActivationCodeGoodsTypeEnum GoodsType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数量
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激活码列表
|
||||
/// </summary>
|
||||
public List<string> Codes { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量生成激活码列表输出
|
||||
/// </summary>
|
||||
public class ActivationCodeCreateListOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 分组输出
|
||||
/// </summary>
|
||||
public List<ActivationCodeCreateOutput> Items { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
|
||||
/// <summary>
|
||||
/// 激活码兑换输入
|
||||
/// </summary>
|
||||
public class ActivationCodeRedeemInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 激活码
|
||||
/// </summary>
|
||||
public string Code { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
|
||||
/// <summary>
|
||||
/// 激活码兑换输出
|
||||
/// </summary>
|
||||
public class ActivationCodeRedeemOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
public ActivationCodeGoodsTypeEnum GoodsType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品名称
|
||||
/// </summary>
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 内容描述
|
||||
/// </summary>
|
||||
public string Content { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class AiUserRoleMenuDto:UserRoleMenuDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否绑定服务号
|
||||
/// </summary>
|
||||
public bool IsBindFuwuhao { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为VIP用户
|
||||
/// </summary>
|
||||
public bool IsVip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VIP到期时间
|
||||
/// </summary>
|
||||
public DateTime? VipExpireTime { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
|
||||
|
||||
/// <summary>
|
||||
/// 公告缓存 DTO
|
||||
/// </summary>
|
||||
public class AnnouncementCacheDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// </summary>
|
||||
public string Version { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 公告日志列表
|
||||
/// </summary>
|
||||
public List<AnnouncementLogDto> Logs { get; set; } = new List<AnnouncementLogDto>();
|
||||
|
||||
/// <summary>
|
||||
/// 跳转链接
|
||||
/// </summary>
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
|
||||
|
||||
/// <summary>
|
||||
/// 公告日志 DTO
|
||||
/// </summary>
|
||||
public class AnnouncementLogDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容列表
|
||||
/// </summary>
|
||||
public List<string> Content { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 图片url
|
||||
/// </summary>
|
||||
public string? ImageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开始时间(系统公告时间、活动开始时间)
|
||||
/// </summary>
|
||||
public DateTime StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 活动结束时间
|
||||
/// </summary>
|
||||
public DateTime? EndTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公告类型(系统、活动)
|
||||
/// </summary>
|
||||
public AnnouncementTypeEnum Type{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 跳转链接
|
||||
/// </summary>
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
|
||||
|
||||
/// <summary>
|
||||
/// 公告输出 DTO
|
||||
/// </summary>
|
||||
public class AnnouncementOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// </summary>
|
||||
public string Version { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 公告日志列表
|
||||
/// </summary>
|
||||
public List<AnnouncementLogDto> Logs { get; set; } = new List<AnnouncementLogDto>();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌任务状态输出
|
||||
/// </summary>
|
||||
public class CardFlipStatusOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 本周总翻牌次数
|
||||
/// </summary>
|
||||
public int TotalFlips { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余免费次数
|
||||
/// </summary>
|
||||
public int RemainingFreeFlips { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余赠送次数
|
||||
/// </summary>
|
||||
public int RemainingBonusFlips { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余邀请解锁次数
|
||||
/// </summary>
|
||||
public int RemainingInviteFlips { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以翻牌
|
||||
/// </summary>
|
||||
public bool CanFlip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户的邀请码
|
||||
/// </summary>
|
||||
public string? MyInviteCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 本周邀请人数
|
||||
/// </summary>
|
||||
public int InvitedCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌记录
|
||||
/// </summary>
|
||||
public List<CardFlipRecord> FlipRecords { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 下次可翻牌提示
|
||||
/// </summary>
|
||||
public string? NextFlipTip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前用户是否已经填写过邀请码
|
||||
/// </summary>
|
||||
public bool IsFilledInviteCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌记录
|
||||
/// </summary>
|
||||
public class CardFlipRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// 翻牌序号(1-10)
|
||||
/// </summary>
|
||||
public int FlipNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已翻
|
||||
/// </summary>
|
||||
public bool IsFlipped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否中奖
|
||||
/// </summary>
|
||||
public bool IsWin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 奖励金额(token数)
|
||||
/// </summary>
|
||||
public long? RewardAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌类型描述
|
||||
/// </summary>
|
||||
public string? FlipTypeDesc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 在翻牌顺序中的位置(1-10,表示第几个翻)
|
||||
/// </summary>
|
||||
public int FlipOrderIndex { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌输入
|
||||
/// </summary>
|
||||
public class FlipCardInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 翻牌序号(1-10)
|
||||
/// </summary>
|
||||
public int FlipNumber { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌输出
|
||||
/// </summary>
|
||||
public class FlipCardOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 翻牌序号(1-10)
|
||||
/// </summary>
|
||||
public int FlipNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否中奖
|
||||
/// </summary>
|
||||
public bool IsWin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 奖励金额(token数)
|
||||
/// </summary>
|
||||
public long? RewardAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 奖励描述
|
||||
/// </summary>
|
||||
public string? RewardDesc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余可翻次数
|
||||
/// </summary>
|
||||
public int RemainingFlips { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请码信息输出
|
||||
/// </summary>
|
||||
public class InviteCodeOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 我的邀请码
|
||||
/// </summary>
|
||||
public string? MyInviteCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 本周邀请人数
|
||||
/// </summary>
|
||||
public int InvitedCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已被邀请
|
||||
/// </summary>
|
||||
public bool IsInvited { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邀请历史记录
|
||||
/// </summary>
|
||||
public List<InvitationHistoryItem> InvitationHistory { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 邀请历史记录项
|
||||
/// </summary>
|
||||
public class InvitationHistoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 被邀请人昵称(脱敏)
|
||||
/// </summary>
|
||||
public string InvitedUserName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请时间
|
||||
/// </summary>
|
||||
public DateTime InvitationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 本周所在
|
||||
/// </summary>
|
||||
public string WeekDescription { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
/// <summary>
|
||||
/// 使用邀请码输入
|
||||
/// </summary>
|
||||
public class UseInviteCodeInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 邀请码
|
||||
/// </summary>
|
||||
public string InviteCode { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 创建AI应用输入
|
||||
/// </summary>
|
||||
public class AiAppCreateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用名称不能为空")]
|
||||
[StringLength(100, ErrorMessage = "应用名称不能超过100个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用终结点
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用终结点不能为空")]
|
||||
[StringLength(500, ErrorMessage = "应用终结点不能超过500个字符")]
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外URL
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "额外URL不能超过500个字符")]
|
||||
public string? ExtraUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用Key
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用Key不能为空")]
|
||||
[StringLength(500, ErrorMessage = "应用Key不能超过500个字符")]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "排序必须大于等于0")]
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// AI应用DTO
|
||||
/// </summary>
|
||||
public class AiAppDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用ID
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用终结点
|
||||
/// </summary>
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外URL
|
||||
/// </summary>
|
||||
public string? ExtraUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用Key
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 获取AI应用列表输入
|
||||
/// </summary>
|
||||
public class AiAppGetListInput : PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 搜索关键词(搜索应用名称)
|
||||
/// </summary>
|
||||
public string? SearchKey { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 更新AI应用输入
|
||||
/// </summary>
|
||||
public class AiAppUpdateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用ID不能为空")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用名称不能为空")]
|
||||
[StringLength(100, ErrorMessage = "应用名称不能超过100个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用终结点
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用终结点不能为空")]
|
||||
[StringLength(500, ErrorMessage = "应用终结点不能超过500个字符")]
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外URL
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "额外URL不能超过500个字符")]
|
||||
public string? ExtraUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用Key
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "应用Key不能为空")]
|
||||
[StringLength(500, ErrorMessage = "应用Key不能超过500个字符")]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "排序必须大于等于0")]
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 创建AI模型输入
|
||||
/// </summary>
|
||||
public class AiModelCreateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "处理名不能为空")]
|
||||
[StringLength(100, ErrorMessage = "处理名不能超过100个字符")]
|
||||
public string HandlerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型ID不能为空")]
|
||||
[StringLength(200, ErrorMessage = "模型ID不能超过200个字符")]
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型名称不能为空")]
|
||||
[StringLength(200, ErrorMessage = "模型名称不能超过200个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型描述
|
||||
/// </summary>
|
||||
[StringLength(1000, ErrorMessage = "模型描述不能超过1000个字符")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "排序必须大于等于0")]
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AI应用ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "AI应用ID不能为空")]
|
||||
public Guid AiAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外信息
|
||||
/// </summary>
|
||||
[StringLength(2000, ErrorMessage = "额外信息不能超过2000个字符")]
|
||||
public string? ExtraInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型类型不能为空")]
|
||||
public ModelTypeEnum ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型API类型
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型API类型不能为空")]
|
||||
public ModelApiTypeEnum ModelApiType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型倍率
|
||||
/// </summary>
|
||||
[Range(0.01, double.MaxValue, ErrorMessage = "模型倍率必须大于0")]
|
||||
public decimal Multiplier { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 模型显示倍率
|
||||
/// </summary>
|
||||
[Range(0.01, double.MaxValue, ErrorMessage = "模型显示倍率必须大于0")]
|
||||
public decimal MultiplierShow { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 供应商分组名称
|
||||
/// </summary>
|
||||
[StringLength(100, ErrorMessage = "供应商分组名称不能超过100个字符")]
|
||||
public string? ProviderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型图标URL
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "模型图标URL不能超过500个字符")]
|
||||
public string? IconUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为尊享模型
|
||||
/// </summary>
|
||||
public bool IsPremium { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// AI模型DTO
|
||||
/// </summary>
|
||||
public class AiModelDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理名
|
||||
/// </summary>
|
||||
public string HandlerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型描述
|
||||
/// </summary>
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AI应用ID
|
||||
/// </summary>
|
||||
public Guid AiAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外信息
|
||||
/// </summary>
|
||||
public string? ExtraInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型
|
||||
/// </summary>
|
||||
public ModelTypeEnum ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型API类型
|
||||
/// </summary>
|
||||
public ModelApiTypeEnum ModelApiType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型倍率
|
||||
/// </summary>
|
||||
public decimal Multiplier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型显示倍率
|
||||
/// </summary>
|
||||
public decimal MultiplierShow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 供应商分组名称
|
||||
/// </summary>
|
||||
public string? ProviderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型图标URL
|
||||
/// </summary>
|
||||
public string? IconUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为尊享模型
|
||||
/// </summary>
|
||||
public bool IsPremium { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 获取AI模型列表输入
|
||||
/// </summary>
|
||||
public class AiModelGetListInput : PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 搜索关键词(搜索模型名称、模型ID)
|
||||
/// </summary>
|
||||
public string? SearchKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AI应用ID筛选
|
||||
/// </summary>
|
||||
public Guid? AiAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否只显示尊享模型
|
||||
/// </summary>
|
||||
public bool? IsPremiumOnly { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
/// <summary>
|
||||
/// 更新AI模型输入
|
||||
/// </summary>
|
||||
public class AiModelUpdateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型ID不能为空")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理名
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "处理名不能为空")]
|
||||
[StringLength(100, ErrorMessage = "处理名不能超过100个字符")]
|
||||
public string HandlerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型ID不能为空")]
|
||||
[StringLength(200, ErrorMessage = "模型ID不能超过200个字符")]
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型名称不能为空")]
|
||||
[StringLength(200, ErrorMessage = "模型名称不能超过200个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型描述
|
||||
/// </summary>
|
||||
[StringLength(1000, ErrorMessage = "模型描述不能超过1000个字符")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "排序必须大于等于0")]
|
||||
public int OrderNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AI应用ID
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "AI应用ID不能为空")]
|
||||
public Guid AiAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 额外信息
|
||||
/// </summary>
|
||||
[StringLength(2000, ErrorMessage = "额外信息不能超过2000个字符")]
|
||||
public string? ExtraInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型类型不能为空")]
|
||||
public ModelTypeEnum ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型API类型
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "模型API类型不能为空")]
|
||||
public ModelApiTypeEnum ModelApiType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型倍率
|
||||
/// </summary>
|
||||
[Range(0.01, double.MaxValue, ErrorMessage = "模型倍率必须大于0")]
|
||||
public decimal Multiplier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型显示倍率
|
||||
/// </summary>
|
||||
[Range(0.01, double.MaxValue, ErrorMessage = "模型显示倍率必须大于0")]
|
||||
public decimal MultiplierShow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 供应商分组名称
|
||||
/// </summary>
|
||||
[StringLength(100, ErrorMessage = "供应商分组名称不能超过100个字符")]
|
||||
public string? ProviderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型图标URL
|
||||
/// </summary>
|
||||
[StringLength(500, ErrorMessage = "模型图标URL不能超过500个字符")]
|
||||
public string? IconUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为尊享模型
|
||||
/// </summary>
|
||||
public bool IsPremium { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
public class AgentResultOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public AgentResultTypeEnum TypeEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
public string Type => TypeEnum.GetJsonName();
|
||||
|
||||
/// <summary>
|
||||
/// 内容载体
|
||||
/// </summary>
|
||||
public object Content { get; set; }
|
||||
}
|
||||
|
||||
public enum AgentResultTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 文本内容
|
||||
/// </summary>
|
||||
[JsonPropertyName("text")]
|
||||
Text,
|
||||
/// <summary>
|
||||
/// 工具调用中
|
||||
/// </summary>
|
||||
[JsonPropertyName("toolCalling")]
|
||||
ToolCalling,
|
||||
|
||||
/// <summary>
|
||||
/// 工具调用完成
|
||||
/// </summary>
|
||||
[JsonPropertyName("toolCalled")]
|
||||
ToolCalled,
|
||||
|
||||
/// <summary>
|
||||
/// 用量
|
||||
/// </summary>
|
||||
[JsonPropertyName("usage")]
|
||||
Usage,
|
||||
|
||||
/// <summary>
|
||||
/// 工具调用用量
|
||||
/// </summary>
|
||||
[JsonPropertyName("toolCallUsage")]
|
||||
ToolCallUsage
|
||||
}
|
||||
|
||||
public static class AgentResultTypeEnumExtensions
|
||||
{
|
||||
public static string GetJsonName(this AgentResultTypeEnum value)
|
||||
{
|
||||
var member = typeof(AgentResultTypeEnum).GetMember(value.ToString()).FirstOrDefault();
|
||||
var attr = member?.GetCustomAttribute<JsonPropertyNameAttribute>();
|
||||
return attr?.Name ?? value.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
public class AgentSendInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 会话id
|
||||
/// </summary>
|
||||
public Guid SessionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// api密钥Id
|
||||
/// </summary>
|
||||
public Guid TokenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型id
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已选择工具
|
||||
/// </summary>
|
||||
public List<string> Tools { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
public class AgentToolOutput
|
||||
{
|
||||
public string Code { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 图片生成输入
|
||||
/// </summary>
|
||||
public class ImageGenerationInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 密钥id
|
||||
/// </summary>
|
||||
public Guid? TokenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词
|
||||
/// </summary>
|
||||
public string Prompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string ModelId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 参考图PrefixBase64列表(可选,包含前缀如 data:image/png;base64,...)
|
||||
/// </summary>
|
||||
public List<string>? ReferenceImagesPrefixBase64 { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 图片任务分页查询输入
|
||||
/// </summary>
|
||||
public class ImageMyTaskPageInput: PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 提示词
|
||||
/// </summary>
|
||||
public string? Prompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态筛选(可选)
|
||||
/// </summary>
|
||||
public TaskStatusEnum? TaskStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布状态
|
||||
/// </summary>
|
||||
public PublishStatusEnum? PublishStatus { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 图片任务分页查询输入
|
||||
/// </summary>
|
||||
public class ImagePlazaPageInput: PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 分类
|
||||
/// </summary>
|
||||
public string? Categories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词
|
||||
/// </summary>
|
||||
public string? Prompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态筛选(可选)
|
||||
/// </summary>
|
||||
public TaskStatusEnum? TaskStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
public string? UserName{ get; set; }
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 图片任务输出
|
||||
/// </summary>
|
||||
public class ImageTaskOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词
|
||||
/// </summary>
|
||||
public string Prompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否匿名
|
||||
/// </summary>
|
||||
public bool IsAnonymous { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成图片URL
|
||||
/// </summary>
|
||||
public string? StoreUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public TaskStatusEnum TaskStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发布状态
|
||||
/// </summary>
|
||||
public PublishStatusEnum PublishStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分类标签
|
||||
/// </summary>
|
||||
[SqlSugar.SugarColumn( IsJson = true)]
|
||||
public List<string> Categories { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string? ErrorInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名称Id
|
||||
/// </summary>
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 发布图片输入
|
||||
/// </summary>
|
||||
public class PublishImageInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否匿名
|
||||
/// </summary>
|
||||
public bool IsAnonymous { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 任务ID
|
||||
/// </summary>
|
||||
public Guid TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分类标签
|
||||
/// </summary>
|
||||
public List<string> Categories { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
||||
|
||||
/// <summary>
|
||||
/// 领取任务奖励输入
|
||||
/// </summary>
|
||||
public class ClaimTaskRewardInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务等级(1=1000w任务,2=3000w任务)
|
||||
/// </summary>
|
||||
public int TaskLevel { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
||||
|
||||
/// <summary>
|
||||
/// 每日任务状态输出
|
||||
/// </summary>
|
||||
public class DailyTaskStatusOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 今日消耗的尊享包Token数
|
||||
/// </summary>
|
||||
public long TodayConsumedTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务列表
|
||||
/// </summary>
|
||||
public List<DailyTaskItem> Tasks { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每日任务项
|
||||
/// </summary>
|
||||
public class DailyTaskItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务等级(1=1000w任务,2=3000w任务)
|
||||
/// </summary>
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 任务要求的Token消耗量
|
||||
/// </summary>
|
||||
public long RequiredTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 奖励的Token数量
|
||||
/// </summary>
|
||||
public long RewardTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态:0=未完成,1=可领取,2=已领取
|
||||
/// </summary>
|
||||
public int Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务进度百分比(0-100)
|
||||
/// </summary>
|
||||
public decimal Progress { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.FileMaster;
|
||||
|
||||
public class VerifyNextInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件数
|
||||
/// </summary>
|
||||
public int FileCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件夹数
|
||||
/// </summary>
|
||||
public int DirectoryCount { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Fuwuhao;
|
||||
|
||||
public class QrCodeOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Qrcode url
|
||||
/// </summary>
|
||||
public string QrCodeUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 场景值
|
||||
/// </summary>
|
||||
public string Scene { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums.Fuwuhao;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Fuwuhao;
|
||||
|
||||
public class QrCodeResultOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回状态
|
||||
/// </summary>
|
||||
public SceneResultEnum SceneResult { get; set; } = SceneResultEnum.Wait;
|
||||
|
||||
/// <summary>
|
||||
/// 如果是已登录,返回token
|
||||
/// </summary>
|
||||
public string? Token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 刷新token
|
||||
/// </summary>
|
||||
public string? RefreshToken { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums.Fuwuhao;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Fuwuhao;
|
||||
|
||||
public class SceneCacheDto
|
||||
{
|
||||
public SceneResultEnum SceneResult { get; set; } = SceneResultEnum.Wait;
|
||||
|
||||
public SceneTypeEnum SceneType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 如果是绑定类型,需要用户id
|
||||
/// </summary>
|
||||
public Guid? UserId { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class MessageDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public Guid SessionId { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Role { get; set; }
|
||||
public string ModelId { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class MessageGetListInput:PagedAllResultRequestDto
|
||||
{
|
||||
[Required]
|
||||
public Guid SessionId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Model;
|
||||
|
||||
/// <summary>
|
||||
/// API类型选项
|
||||
/// </summary>
|
||||
public class ModelApiTypeOption
|
||||
{
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举值
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Extensions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 模型库展示数据
|
||||
/// </summary>
|
||||
public class ModelLibraryDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型描述
|
||||
/// </summary>
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型
|
||||
/// </summary>
|
||||
public ModelTypeEnum ModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型名称
|
||||
/// </summary>
|
||||
public string ModelTypeName => ModelType.GetDescription();
|
||||
|
||||
/// <summary>
|
||||
/// 模型支持的API类型
|
||||
/// </summary>
|
||||
public List<ModelApiTypeOutput> ModelApiTypes { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 模型显示倍率
|
||||
/// </summary>
|
||||
public decimal MultiplierShow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 供应商分组名称
|
||||
/// </summary>
|
||||
public string? ProviderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型图标URL
|
||||
/// </summary>
|
||||
public string? IconUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为尊享模型(PremiumChat类型)
|
||||
/// </summary>
|
||||
public bool IsPremium { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int OrderNum { get; set; }
|
||||
}
|
||||
|
||||
public class ModelApiTypeOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型类型
|
||||
/// </summary>
|
||||
public ModelApiTypeEnum ModelApiType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型名称
|
||||
/// </summary>
|
||||
public string ModelApiTypeName => ModelApiType.GetDescription();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 获取模型库列表查询参数
|
||||
/// </summary>
|
||||
public class ModelLibraryGetListInput : PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 搜索关键词(搜索模型名称、模型ID)
|
||||
/// </summary>
|
||||
public string? SearchKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 供应商名称筛选
|
||||
/// </summary>
|
||||
public List<string>? ProviderNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型筛选
|
||||
/// </summary>
|
||||
public List<ModelTypeEnum>? ModelTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// API类型筛选
|
||||
/// </summary>
|
||||
public List<ModelApiTypeEnum>? ModelApiTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否只显示尊享模型
|
||||
/// </summary>
|
||||
public bool? IsPremiumOnly { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 模型类型选项
|
||||
/// </summary>
|
||||
public class ModelTypeOption
|
||||
{
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
public string Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举值
|
||||
/// </summary>
|
||||
public int Value { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class ModelGetListOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型id
|
||||
/// </summary>
|
||||
public string ModelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
public string ModelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型描述
|
||||
/// </summary>
|
||||
public string? ModelDescribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注信息
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为尊享包
|
||||
/// </summary>
|
||||
public bool IsPremiumPackage { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单输入DTO
|
||||
/// </summary>
|
||||
public class CreateOrderInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public GoodsTypeEnum GoodsType { get; set; }
|
||||
|
||||
public string? ReturnUrl{ get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单输出DTO
|
||||
/// </summary>
|
||||
public class CreateOrderOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单ID
|
||||
/// </summary>
|
||||
public Guid OrderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家订单号
|
||||
/// </summary>
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付页面HTML内容
|
||||
/// </summary>
|
||||
public object PaymentPageHtml { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 获取商品列表输入DTO
|
||||
/// </summary>
|
||||
public class GetGoodsListInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品类别(可选)
|
||||
/// 如果不传,则返回所有商品
|
||||
/// 如果传了,则只返回指定类别的商品(VIP服务或尊享包)
|
||||
/// </summary>
|
||||
public GoodsCategoryType? GoodsCategoryType { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 商品列表输出DTO
|
||||
/// </summary>
|
||||
public class GoodsListOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商品名称
|
||||
/// </summary>
|
||||
public string GoodsName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品原价
|
||||
/// </summary>
|
||||
public decimal OriginalPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品参考价格
|
||||
/// </summary>
|
||||
public decimal ReferencePrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品实际价格(折扣后的价格)
|
||||
/// </summary>
|
||||
public decimal GoodsPrice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 折扣金额(仅尊享包)
|
||||
/// </summary>
|
||||
public decimal? DiscountAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品类别
|
||||
/// </summary>
|
||||
public string GoodsCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 折扣说明(仅尊享包)
|
||||
/// </summary>
|
||||
public string? DiscountDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
public GoodsTypeEnum GoodsType { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 查询订单状态输入DTO
|
||||
/// </summary>
|
||||
public class QueryOrderStatusInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 商家订单号
|
||||
/// </summary>
|
||||
public string OutTradeNo { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
/// <summary>
|
||||
/// 查询订单状态输出DTO
|
||||
/// </summary>
|
||||
public class QueryOrderStatusOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单ID
|
||||
/// </summary>
|
||||
public Guid OrderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家订单号
|
||||
/// </summary>
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付宝交易号
|
||||
/// </summary>
|
||||
public string? TradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易状态
|
||||
/// </summary>
|
||||
public TradeStatusEnum TradeStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易状态描述
|
||||
/// </summary>
|
||||
public string TradeStatusDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单金额
|
||||
/// </summary>
|
||||
public decimal TotalAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品名称
|
||||
/// </summary>
|
||||
public string GoodsName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品类型
|
||||
/// </summary>
|
||||
public GoodsTypeEnum GoodsType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后修改时间
|
||||
/// </summary>
|
||||
public DateTime? LastModificationTime { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Recharge;
|
||||
|
||||
public class RechargeCreateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 充值金额
|
||||
/// </summary>
|
||||
[Required]
|
||||
[Range(0.01, double.MaxValue, ErrorMessage = "充值金额必须大于0")]
|
||||
public decimal RechargeAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 充值内容
|
||||
/// </summary>
|
||||
[Required]
|
||||
[StringLength(500, ErrorMessage = "充值内容不能超过500个字符")]
|
||||
public string Content { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// VIP月数(为空或0表示永久VIP,1个月按31天计算)
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "月数必须大于等于0")]
|
||||
public int? Months { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VIP天数(为空或0表示不使用天数充值)
|
||||
/// </summary>
|
||||
[Range(0, int.MaxValue, ErrorMessage = "天数必须大于等于0")]
|
||||
public int? Days { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
[StringLength(1000, ErrorMessage = "备注不能超过1000个字符")]
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 联系方式
|
||||
/// </summary>
|
||||
[StringLength(200, ErrorMessage = "联系方式不能超过200个字符")]
|
||||
public string? ContactInfo { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Recharge;
|
||||
|
||||
public class RechargeGetListOutput
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 充值金额
|
||||
/// </summary>
|
||||
public decimal RechargeAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户
|
||||
/// </summary>
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 充值内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 到期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpireDateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 联系方式
|
||||
/// </summary>
|
||||
public string? ContactInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SendMessageInput
|
||||
{
|
||||
public List<Message> Messages { get; set; }
|
||||
public string Model { get; set; }
|
||||
|
||||
public Guid? SessionId{ get; set; }
|
||||
}
|
||||
|
||||
public class Message
|
||||
{
|
||||
public string Role { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SendMessageStreamOutputDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 唯一标识符
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对象类型
|
||||
/// </summary>
|
||||
public string Object { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间,Unix时间戳格式
|
||||
/// </summary>
|
||||
public long Created { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型名称
|
||||
/// </summary>
|
||||
public string Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择项列表
|
||||
/// </summary>
|
||||
public List<Choice> Choices { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统指纹(可能为空)
|
||||
/// </summary>
|
||||
public string SystemFingerprint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用情况信息
|
||||
/// </summary>
|
||||
public Usage Usage { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择项类,表示模型返回的一个选择
|
||||
/// </summary>
|
||||
public class Choice
|
||||
{
|
||||
/// <summary>
|
||||
/// 选择索引
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变化内容,包括内容字符串和角色
|
||||
/// </summary>
|
||||
public Delta Delta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结束原因,可能为空
|
||||
/// </summary>
|
||||
public string? FinishReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 内容过滤结果
|
||||
/// </summary>
|
||||
public ContentFilterResults ContentFilterResults { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 变化内容
|
||||
/// </summary>
|
||||
public class Delta
|
||||
{
|
||||
/// <summary>
|
||||
/// 内容文本
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色,例如"assistant"
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内容过滤结果
|
||||
/// </summary>
|
||||
public class ContentFilterResults
|
||||
{
|
||||
public FilterStatus Hate { get; set; }
|
||||
public FilterStatus SelfHarm { get; set; }
|
||||
public FilterStatus Sexual { get; set; }
|
||||
public FilterStatus Violence { get; set; }
|
||||
public FilterStatus Jailbreak { get; set; }
|
||||
public FilterStatus Profanity { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 过滤状态,表示是否经过过滤以及检测是否命中
|
||||
/// </summary>
|
||||
public class FilterStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否被过滤
|
||||
/// </summary>
|
||||
public bool Filtered { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否检测到该类型(例如 Jailbreak 中存在此字段)
|
||||
/// </summary>
|
||||
public bool? Detected { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用情况,记录 token 数量等信息
|
||||
/// </summary>
|
||||
public class Usage
|
||||
{
|
||||
/// <summary>
|
||||
/// 提示词数量
|
||||
/// </summary>
|
||||
public int PromptTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 补全词数量
|
||||
/// </summary>
|
||||
public int CompletionTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总的 Token 数量
|
||||
/// </summary>
|
||||
public int TotalTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词详细信息
|
||||
/// </summary>
|
||||
public PromptTokensDetails PromptTokensDetails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 补全文字详细信息
|
||||
/// </summary>
|
||||
public CompletionTokensDetails CompletionTokensDetails { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提示词相关 token 详细信息
|
||||
/// </summary>
|
||||
public class PromptTokensDetails
|
||||
{
|
||||
public int AudioTokens { get; set; }
|
||||
public int CachedTokens { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 补全相关 token 详细信息
|
||||
/// </summary>
|
||||
public class CompletionTokensDetails
|
||||
{
|
||||
public int AudioTokens { get; set; }
|
||||
|
||||
public int ReasoningTokens { get; set; }
|
||||
|
||||
public int AcceptedPredictionTokens { get; set; }
|
||||
|
||||
public int RejectedPredictionTokens { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionCreateAndUpdateInput
|
||||
{
|
||||
public string SessionTitle { get; set; }
|
||||
public string SessionContent { get; set; }
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public string SessionTitle { get; set; }
|
||||
public string SessionContent { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionGetListInput:PagedAllResultRequestDto
|
||||
{
|
||||
public string? SessionTitle { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Token;
|
||||
|
||||
/// <summary>
|
||||
/// 创建Token输入
|
||||
/// </summary>
|
||||
public class TokenCreateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称(同一用户不能重复)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "名称不能为空")]
|
||||
[StringLength(100, ErrorMessage = "名称长度不能超过100个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期时间(空为永不过期)
|
||||
/// </summary>
|
||||
public DateTime? ExpireTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 尊享包额度限制(空为不限制)
|
||||
/// </summary>
|
||||
public long? PremiumQuotaLimit { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Token;
|
||||
|
||||
/// <summary>
|
||||
/// Token列表输出
|
||||
/// </summary>
|
||||
public class TokenGetListOutputDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Token Id
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token密钥
|
||||
/// </summary>
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期时间(空为永不过期)
|
||||
/// </summary>
|
||||
public DateTime? ExpireTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 尊享包额度限制(空为不限制)
|
||||
/// </summary>
|
||||
public long? PremiumQuotaLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 尊享包已使用额度
|
||||
/// </summary>
|
||||
public long PremiumUsedQuota { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否禁用
|
||||
/// </summary>
|
||||
public bool IsDisabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Token;
|
||||
|
||||
public class TokenOutput
|
||||
{
|
||||
public string? ApiKey { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Token;
|
||||
|
||||
public class TokenSelectListOutputDto
|
||||
{
|
||||
public Guid TokenId { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool IsDisabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.Token;
|
||||
|
||||
/// <summary>
|
||||
/// 编辑Token输入
|
||||
/// </summary>
|
||||
public class TokenUpdateInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Token Id
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Id不能为空")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 名称(同一用户不能重复)
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "名称不能为空")]
|
||||
[StringLength(100, ErrorMessage = "名称长度不能超过100个字符")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期时间(空为永不过期)
|
||||
/// </summary>
|
||||
public DateTime? ExpireTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 尊享包额度限制(空为不限制)
|
||||
/// </summary>
|
||||
public long? PremiumQuotaLimit { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
/// <summary>
|
||||
/// 每日Token使用量统计DTO
|
||||
/// </summary>
|
||||
public class DailyTokenUsageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 日期
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token消耗量
|
||||
/// </summary>
|
||||
public long Tokens { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
/// <summary>
|
||||
/// 模型Token使用量统计DTO
|
||||
/// </summary>
|
||||
public class ModelTokenUsageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 模型ID
|
||||
/// </summary>
|
||||
public string Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总消耗量
|
||||
/// </summary>
|
||||
public long Tokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 占比(百分比)
|
||||
/// </summary>
|
||||
public decimal Percentage { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
/// <summary>
|
||||
/// 尊享服务Token用量统计DTO
|
||||
/// </summary>
|
||||
public class PremiumTokenUsageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 总Token数
|
||||
/// </summary>
|
||||
public long PremiumTotalTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已使用Token数
|
||||
/// </summary>
|
||||
public long PremiumUsedTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余Token数
|
||||
/// </summary>
|
||||
public long PremiumRemainingTokens { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
public class PremiumTokenUsageGetListInput : PagedAllResultRequestDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否免费
|
||||
/// </summary>
|
||||
public bool? IsFree { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
public class PremiumTokenUsageGetListOutput : CreationAuditedEntityDto
|
||||
{
|
||||
/// <summary>
|
||||
/// id
|
||||
/// </summary>
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包名称
|
||||
/// </summary>
|
||||
public string PackageName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总用量(总token数)
|
||||
/// </summary>
|
||||
public long TotalTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 剩余用量(剩余token数)
|
||||
/// </summary>
|
||||
public long RemainingTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 已使用token数
|
||||
/// </summary>
|
||||
public long UsedTokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 到期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpireDateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否激活
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 购买金额
|
||||
/// </summary>
|
||||
public decimal PurchaseAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
/// <summary>
|
||||
/// 尊享包不同Token用量占比DTO(饼图)
|
||||
/// </summary>
|
||||
public class TokenPremiumUsageDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Token Id
|
||||
/// </summary>
|
||||
public Guid TokenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token名称
|
||||
/// </summary>
|
||||
public string TokenName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token消耗量
|
||||
/// </summary>
|
||||
public long Tokens { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 占比(百分比)
|
||||
/// </summary>
|
||||
public decimal Percentage { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
public class UsageStatisticsGetInput
|
||||
{
|
||||
/// <summary>
|
||||
/// tokenId
|
||||
/// </summary>
|
||||
public Guid? TokenId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 激活码服务接口
|
||||
/// </summary>
|
||||
public interface IActivationCodeService : IApplicationService
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量生成激活码
|
||||
/// </summary>
|
||||
Task<ActivationCodeCreateListOutput> CreateBatchAsync(ActivationCodeCreateListInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 兑换激活码
|
||||
/// </summary>
|
||||
Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 公告服务接口
|
||||
/// </summary>
|
||||
public interface IAnnouncementService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取公告信息
|
||||
/// </summary>
|
||||
/// <returns>公告信息</returns>
|
||||
Task<List<AnnouncementLogDto>> GetAsync();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌服务接口
|
||||
/// </summary>
|
||||
public interface ICardFlipService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取本周翻牌任务状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<CardFlipStatusOutput> GetWeeklyTaskStatusAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌
|
||||
/// </summary>
|
||||
/// <param name="input">翻牌输入</param>
|
||||
/// <returns></returns>
|
||||
Task<FlipCardOutput> FlipCardAsync(FlipCardInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 使用邀请码解锁翻牌次数
|
||||
/// </summary>
|
||||
/// <param name="input">邀请码输入</param>
|
||||
/// <returns></returns>
|
||||
Task UseInviteCodeAsync(UseInviteCodeInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取我的邀请码信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<InviteCodeOutput> GetMyInviteCodeAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 生成我的邀请码(如果没有)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<string> GenerateMyInviteCodeAsync();
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Channel;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 渠道商管理服务接口
|
||||
/// </summary>
|
||||
public interface IChannelService
|
||||
{
|
||||
#region AI应用管理
|
||||
|
||||
/// <summary>
|
||||
/// 获取AI应用列表
|
||||
/// </summary>
|
||||
/// <param name="input">查询参数</param>
|
||||
/// <returns>分页应用列表</returns>
|
||||
Task<PagedResultDto<AiAppDto>> GetAppListAsync(AiAppGetListInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取AI应用
|
||||
/// </summary>
|
||||
/// <param name="id">应用ID</param>
|
||||
/// <returns>应用详情</returns>
|
||||
Task<AiAppDto> GetAppByIdAsync(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// 创建AI应用
|
||||
/// </summary>
|
||||
/// <param name="input">创建输入</param>
|
||||
/// <returns>创建的应用</returns>
|
||||
Task<AiAppDto> CreateAppAsync(AiAppCreateInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 更新AI应用
|
||||
/// </summary>
|
||||
/// <param name="input">更新输入</param>
|
||||
/// <returns>更新后的应用</returns>
|
||||
Task<AiAppDto> UpdateAppAsync(AiAppUpdateInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 删除AI应用
|
||||
/// </summary>
|
||||
/// <param name="id">应用ID</param>
|
||||
Task DeleteAppAsync(Guid id);
|
||||
|
||||
#endregion
|
||||
|
||||
#region AI模型管理
|
||||
|
||||
/// <summary>
|
||||
/// 获取AI模型列表
|
||||
/// </summary>
|
||||
/// <param name="input">查询参数</param>
|
||||
/// <returns>分页模型列表</returns>
|
||||
Task<PagedResultDto<AiModelDto>> GetModelListAsync(AiModelGetListInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取AI模型
|
||||
/// </summary>
|
||||
/// <param name="id">模型ID</param>
|
||||
/// <returns>模型详情</returns>
|
||||
Task<AiModelDto> GetModelByIdAsync(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// 创建AI模型
|
||||
/// </summary>
|
||||
/// <param name="input">创建输入</param>
|
||||
/// <returns>创建的模型</returns>
|
||||
Task<AiModelDto> CreateModelAsync(AiModelCreateInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 更新AI模型
|
||||
/// </summary>
|
||||
/// <param name="input">更新输入</param>
|
||||
/// <returns>更新后的模型</returns>
|
||||
Task<AiModelDto> UpdateModelAsync(AiModelUpdateInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 删除AI模型(软删除)
|
||||
/// </summary>
|
||||
/// <param name="id">模型ID</param>
|
||||
Task DeleteModelAsync(Guid id);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Model;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 模型服务接口
|
||||
/// </summary>
|
||||
public interface IModelService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取模型库列表(公开接口,无需登录)
|
||||
/// </summary>
|
||||
/// <param name="input">查询参数</param>
|
||||
/// <returns>分页模型列表</returns>
|
||||
Task<PagedResultDto<ModelLibraryDto>> GetListAsync(ModelLibraryGetListInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取供应商列表(公开接口,无需登录)
|
||||
/// </summary>
|
||||
/// <returns>供应商列表</returns>
|
||||
Task<List<string>> GetProviderListAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 获取模型类型选项列表(公开接口,无需登录)
|
||||
/// </summary>
|
||||
/// <returns>模型类型选项</returns>
|
||||
Task<List<ModelTypeOption>> GetModelTypeOptionsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 获取API类型选项列表(公开接口,无需登录)
|
||||
/// </summary>
|
||||
/// <returns>API类型选项</returns>
|
||||
Task<List<ModelApiTypeOption>> GetApiTypeOptionsAsync();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Pay;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 支付服务接口
|
||||
/// </summary>
|
||||
public interface IPayService : IApplicationService
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建订单并发起支付
|
||||
/// </summary>
|
||||
/// <param name="input">创建订单输入</param>
|
||||
/// <returns>订单创建结果</returns>
|
||||
Task<CreateOrderOutput> CreateOrderAsync(CreateOrderInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 支付宝异步通知处理
|
||||
/// </summary>
|
||||
/// <param name="form">表单数据</param>
|
||||
/// <returns></returns>
|
||||
Task<string> AlipayNotifyAsync([FromForm] IFormCollection form);
|
||||
|
||||
/// <summary>
|
||||
/// 查询订单状态
|
||||
/// </summary>
|
||||
/// <param name="input">查询订单状态输入</param>
|
||||
/// <returns>订单状态信息</returns>
|
||||
Task<QueryOrderStatusOutput> QueryOrderStatusAsync([FromQuery] QueryOrderStatusInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取商品列表
|
||||
/// </summary>
|
||||
/// <param name="input">获取商品列表输入</param>
|
||||
/// <returns>商品列表</returns>
|
||||
Task<List<GoodsListOutput>> GetGoodsListAsync([FromQuery] GetGoodsListInput input);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Recharge;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
public interface IRechargeService
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除用户vip及角色
|
||||
/// </summary>
|
||||
Task RemoveVipRoleByExpireAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 给用户充值VIP
|
||||
/// </summary>
|
||||
/// <param name="input">充值输入参数</param>
|
||||
/// <returns></returns>
|
||||
Task RechargeVipAsync(RechargeCreateInput input);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.UsageStatistics;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
|
||||
/// <summary>
|
||||
/// 使用量统计服务接口
|
||||
/// </summary>
|
||||
public interface IUsageStatisticsService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前用户近7天的Token消耗统计
|
||||
/// </summary>
|
||||
/// <returns>每日Token使用量列表</returns>
|
||||
Task<List<DailyTokenUsageDto>> GetLast7DaysTokenUsageAsync(UsageStatisticsGetInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户各个模型的Token消耗量及占比
|
||||
/// </summary>
|
||||
/// <returns>模型Token使用量列表</returns>
|
||||
Task<List<ModelTokenUsageDto>> GetModelTokenUsageAsync(UsageStatisticsGetInput input);
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前用户尊享服务Token用量统计
|
||||
/// </summary>
|
||||
/// <returns>尊享服务Token用量统计</returns>
|
||||
Task<PremiumTokenUsageDto> GetPremiumTokenUsageAsync();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.Ddd.Application.Contracts\Yi.Framework.Ddd.Application.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\rbac\Yi.Framework.Rbac.Application.Contracts\Yi.Framework.Rbac.Application.Contracts.csproj" />
|
||||
<ProjectReference Include="..\Yi.Framework.AiHub.Domain.Shared\Yi.Framework.AiHub.Domain.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Yi.Framework.AiHub.Domain.Shared;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
using Yi.Framework.Rbac.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts
|
||||
{
|
||||
[DependsOn(
|
||||
typeof(YiFrameworkAiHubDomainSharedModule),
|
||||
typeof(YiFrameworkDddApplicationContractsModule),
|
||||
|
||||
typeof(YiFrameworkRbacApplicationContractsModule)
|
||||
)]
|
||||
public class YiFrameworkAiHubApplicationContractsModule : AbpModule
|
||||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var build = context.Services.GetConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Volo.Abp.BackgroundJobs;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Yi.Framework.AiHub.Domain.Entities.Chat;
|
||||
using Yi.Framework.AiHub.Domain.Managers;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 图片生成后台任务
|
||||
/// </summary>
|
||||
public class ImageGenerationJob : AsyncBackgroundJob<ImageGenerationJobArgs>, ITransientDependency
|
||||
{
|
||||
private readonly ILogger<ImageGenerationJob> _logger;
|
||||
private readonly AiGateWayManager _aiGateWayManager;
|
||||
private readonly ISqlSugarRepository<ImageStoreTaskAggregateRoot> _imageStoreTaskRepository;
|
||||
|
||||
public ImageGenerationJob(
|
||||
ILogger<ImageGenerationJob> logger,
|
||||
AiGateWayManager aiGateWayManager,
|
||||
ISqlSugarRepository<ImageStoreTaskAggregateRoot> imageStoreTaskRepository)
|
||||
{
|
||||
_logger = logger;
|
||||
_aiGateWayManager = aiGateWayManager;
|
||||
_imageStoreTaskRepository = imageStoreTaskRepository;
|
||||
}
|
||||
|
||||
public override async Task ExecuteAsync(ImageGenerationJobArgs args)
|
||||
{
|
||||
var task = await _imageStoreTaskRepository.GetFirstAsync(x => x.Id == args.TaskId);
|
||||
if (task is null)
|
||||
{
|
||||
throw new UserFriendlyException($"{args.TaskId} 图片生成任务不存在");
|
||||
}
|
||||
|
||||
_logger.LogInformation("开始执行图片生成任务,TaskId: {TaskId}, ModelId: {ModelId}, UserId: {UserId}",
|
||||
task.Id, task.ModelId, task.UserId);
|
||||
try
|
||||
{
|
||||
// 构建 Gemini API 请求对象
|
||||
var parts = new List<object>
|
||||
{
|
||||
new { text = task.Prompt }
|
||||
};
|
||||
|
||||
// 添加参考图(如果有)
|
||||
foreach (var prefixBase64 in task.ReferenceImagesPrefixBase64)
|
||||
{
|
||||
var (mimeType, base64Data) = ParsePrefixBase64(prefixBase64);
|
||||
parts.Add(new
|
||||
{
|
||||
inline_data = new
|
||||
{
|
||||
mime_type = mimeType,
|
||||
data = base64Data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var requestObj = new
|
||||
{
|
||||
contents = new[]
|
||||
{
|
||||
new { role = "user", parts }
|
||||
}
|
||||
};
|
||||
|
||||
var request = JsonSerializer.Deserialize<JsonElement>(
|
||||
JsonSerializer.Serialize(requestObj));
|
||||
|
||||
//里面生成成功已经包含扣款了
|
||||
await _aiGateWayManager.GeminiGenerateContentImageForStatisticsAsync(
|
||||
task.Id,
|
||||
task.ModelId,
|
||||
request,
|
||||
task.UserId,
|
||||
tokenId: task.TokenId);
|
||||
|
||||
|
||||
_logger.LogInformation("图片生成任务完成,TaskId: {TaskId}", args.TaskId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = $"图片任务失败,TaskId: {args.TaskId},错误信息: {ex.Message},错误堆栈:{ex.StackTrace}";
|
||||
_logger.LogError(ex, error);
|
||||
|
||||
task.TaskStatus = TaskStatusEnum.Fail;
|
||||
task.ErrorInfo = error;
|
||||
|
||||
await _imageStoreTaskRepository.UpdateAsync(task);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析带前缀的 Base64 字符串,提取 mimeType 和纯 base64 数据
|
||||
/// </summary>
|
||||
private static (string mimeType, string base64Data) ParsePrefixBase64(string prefixBase64)
|
||||
{
|
||||
// 默认值
|
||||
var mimeType = "image/png";
|
||||
var base64Data = prefixBase64;
|
||||
|
||||
if (prefixBase64.Contains(","))
|
||||
{
|
||||
var parts = prefixBase64.Split(',');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var header = parts[0];
|
||||
if (header.Contains(":") && header.Contains(";"))
|
||||
{
|
||||
mimeType = header.Split(':')[1].Split(';')[0];
|
||||
}
|
||||
|
||||
base64Data = parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return (mimeType, base64Data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Yi.Framework.AiHub.Application.Jobs;
|
||||
|
||||
/// <summary>
|
||||
/// 图片生成后台任务参数
|
||||
/// </summary>
|
||||
public class ImageGenerationJobArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 图片任务ID
|
||||
/// </summary>
|
||||
public Guid TaskId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Medallion.Threading;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.ActivationCode;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Recharge;
|
||||
using Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
using Yi.Framework.AiHub.Domain.Managers;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Enums;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 激活码服务
|
||||
/// </summary>
|
||||
public class ActivationCodeService : ApplicationService, IActivationCodeService
|
||||
{
|
||||
private readonly ActivationCodeManager _activationCodeManager;
|
||||
private readonly IRechargeService _rechargeService;
|
||||
private readonly PremiumPackageManager _premiumPackageManager;
|
||||
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||
public ActivationCodeService(
|
||||
ActivationCodeManager activationCodeManager,
|
||||
IRechargeService rechargeService,
|
||||
PremiumPackageManager premiumPackageManager)
|
||||
{
|
||||
_activationCodeManager = activationCodeManager;
|
||||
_rechargeService = rechargeService;
|
||||
_premiumPackageManager = premiumPackageManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量生成激活码
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpPost("activationCode/Batch")]
|
||||
public async Task<ActivationCodeCreateListOutput> CreateBatchAsync(ActivationCodeCreateListInput input)
|
||||
{
|
||||
if (input.Items == null || input.Items.Count == 0)
|
||||
{
|
||||
throw new UserFriendlyException("生成列表不能为空");
|
||||
}
|
||||
|
||||
var entities = await _activationCodeManager.CreateBatchAsync(
|
||||
input.Items.Select(x => (x.GoodsType, x.Count)).ToList());
|
||||
|
||||
var outputs = entities
|
||||
.GroupBy(x => x.GoodsType)
|
||||
.Select(group => new ActivationCodeCreateOutput
|
||||
{
|
||||
GoodsType = group.Key,
|
||||
Count = group.Count(),
|
||||
Codes = group.Select(x => x.Code).ToList()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return new ActivationCodeCreateListOutput
|
||||
{
|
||||
Items = outputs
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 兑换激活码
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpPost("activationCode/Redeem")]
|
||||
public async Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input)
|
||||
{
|
||||
//自旋等待,防抖
|
||||
await using var handle =
|
||||
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ActivationCodeLock:{input.Code}");
|
||||
|
||||
var userId = CurrentUser.GetId();
|
||||
var redeemContext = await _activationCodeManager.RedeemAsync(userId, input.Code);
|
||||
var goodsType = redeemContext.ActivationCode.GoodsType;
|
||||
var goods = redeemContext.Goods;
|
||||
var packageName = redeemContext.PackageName;
|
||||
var totalAmount = goods.Price;
|
||||
|
||||
if (goods.TokenAmount > 0)
|
||||
{
|
||||
await _premiumPackageManager.CreatePremiumPackageAsync(
|
||||
userId,
|
||||
goods.TokenAmount,
|
||||
packageName,
|
||||
totalAmount,
|
||||
"激活码兑换",
|
||||
expireMonths: null,
|
||||
isCreateRechargeRecord: !goods.IsCombo);
|
||||
}
|
||||
|
||||
if (goods.VipMonths > 0 || goods.VipDays > 0)
|
||||
{
|
||||
await _rechargeService.RechargeVipAsync(new RechargeCreateInput
|
||||
{
|
||||
UserId = userId,
|
||||
RechargeAmount = totalAmount,
|
||||
Content = packageName,
|
||||
Months = goods.VipMonths,
|
||||
Days = goods.VipDays,
|
||||
Remark = "激活码兑换",
|
||||
ContactInfo = null
|
||||
});
|
||||
}
|
||||
|
||||
return new ActivationCodeRedeemOutput
|
||||
{
|
||||
GoodsType = goodsType,
|
||||
PackageName = packageName,
|
||||
Content = packageName
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.CardFlip;
|
||||
using Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.AiHub.Domain.Extensions;
|
||||
using Yi.Framework.AiHub.Domain.Managers;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌服务 - 应用层组合服务
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
public class CardFlipService : ApplicationService, ICardFlipService
|
||||
{
|
||||
private readonly CardFlipManager _cardFlipManager;
|
||||
private readonly InviteCodeManager _inviteCodeManager;
|
||||
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||
private readonly ILogger<CardFlipService> _logger;
|
||||
|
||||
public CardFlipService(
|
||||
CardFlipManager cardFlipManager,
|
||||
InviteCodeManager inviteCodeManager,
|
||||
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
|
||||
ILogger<CardFlipService> logger)
|
||||
{
|
||||
_cardFlipManager = cardFlipManager;
|
||||
_inviteCodeManager = inviteCodeManager;
|
||||
_premiumPackageRepository = premiumPackageRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本周翻牌任务状态
|
||||
/// </summary>
|
||||
public async Task<CardFlipStatusOutput> GetWeeklyTaskStatusAsync()
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);
|
||||
|
||||
// 获取本周任务
|
||||
var task = await _cardFlipManager.GetOrCreateWeeklyTaskAsync(userId, weekStart, createIfNotExists: false);
|
||||
|
||||
// 获取邀请码信息
|
||||
var inviteCode = await _inviteCodeManager.GetUserInviteCodeAsync(userId);
|
||||
|
||||
// 统计本周邀请人数
|
||||
var invitedCount = await _inviteCodeManager.GetWeeklyInvitationCountAsync(userId, weekStart);
|
||||
|
||||
//当前用户是否已填写过邀请码
|
||||
var isFilledInviteCode = await _inviteCodeManager.IsFilledInviteCodeAsync(userId);
|
||||
var output = new CardFlipStatusOutput
|
||||
{
|
||||
TotalFlips = task?.TotalFlips ?? 0,
|
||||
RemainingFreeFlips = CardFlipManager.MAX_FREE_FLIPS - (task?.FreeFlipsUsed ?? 0),
|
||||
RemainingBonusFlips = 0, // 已废弃
|
||||
RemainingInviteFlips = CardFlipManager.MAX_INVITE_FLIPS - (task?.InviteFlipsUsed ?? 0),
|
||||
CanFlip = _cardFlipManager.CanFlipCard(task),
|
||||
MyInviteCode = inviteCode?.Code,
|
||||
InvitedCount = invitedCount,
|
||||
FlipRecords = BuildFlipRecords(task),
|
||||
IsFilledInviteCode = isFilledInviteCode
|
||||
};
|
||||
|
||||
// 生成提示信息
|
||||
output.NextFlipTip = GenerateNextFlipTip(output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 翻牌
|
||||
/// </summary>
|
||||
public async Task<FlipCardOutput> FlipCardAsync(FlipCardInput input)
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);
|
||||
|
||||
// 执行翻牌逻辑(由Manager处理验证和翻牌)
|
||||
var result = await _cardFlipManager.ExecuteFlipAsync(userId, input.FlipNumber, weekStart);
|
||||
|
||||
// 如果中奖,发放奖励
|
||||
if (result.IsWin)
|
||||
{
|
||||
await GrantRewardAsync(userId, result.RewardAmount, $"翻牌活动-序号{input.FlipNumber}中奖");
|
||||
}
|
||||
|
||||
// 构建输出
|
||||
var output = new FlipCardOutput
|
||||
{
|
||||
FlipNumber = result.FlipNumber,
|
||||
IsWin = result.IsWin,
|
||||
RewardAmount = result.RewardAmount,
|
||||
RewardDesc = result.RewardDesc,
|
||||
RemainingFlips = CardFlipManager.TOTAL_MAX_FLIPS - input.FlipNumber
|
||||
};
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用邀请码解锁翻牌次数
|
||||
/// </summary>
|
||||
public async Task UseInviteCodeAsync(UseInviteCodeInput input)
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);
|
||||
|
||||
// 获取本周任务
|
||||
var task = await _cardFlipManager.GetOrCreateWeeklyTaskAsync(userId, weekStart, createIfNotExists: true);
|
||||
|
||||
// 验证是否已经使用了所有邀请解锁次数
|
||||
if (task.InviteFlipsUsed >= CardFlipManager.MAX_INVITE_FLIPS)
|
||||
{
|
||||
throw new UserFriendlyException("本周邀请解锁次数已用完");
|
||||
}
|
||||
|
||||
// 使用邀请码(由Manager处理验证和邀请逻辑)
|
||||
await _inviteCodeManager.UseInviteCodeAsync(userId, input.InviteCode);
|
||||
|
||||
_logger.LogInformation($"用户 {userId} 使用邀请码 {input.InviteCode} 解锁翻牌次数成功");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取我的邀请码信息
|
||||
/// </summary>
|
||||
public async Task<InviteCodeOutput> GetMyInviteCodeAsync()
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var weekStart = CardFlipManager.GetWeekStartDate(DateTime.Now);
|
||||
|
||||
// 获取我的邀请码
|
||||
var inviteCode = await _inviteCodeManager.GetUserInviteCodeAsync(userId);
|
||||
|
||||
// 统计本周邀请人数
|
||||
var invitedCount = await _inviteCodeManager.GetWeeklyInvitationCountAsync(userId, weekStart);
|
||||
|
||||
// 获取邀请历史
|
||||
var invitationHistory = await _inviteCodeManager.GetInvitationHistoryAsync(userId, 10);
|
||||
|
||||
return new InviteCodeOutput
|
||||
{
|
||||
MyInviteCode = inviteCode?.Code,
|
||||
InvitedCount = invitedCount,
|
||||
InvitationHistory = invitationHistory.Select(x => new InvitationHistoryItem
|
||||
{
|
||||
InvitedUserName = x.InvitedUserName,
|
||||
InvitationTime = x.InvitationTime,
|
||||
WeekDescription = GetWeekDescription(x.InvitationTime)
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成我的邀请码
|
||||
/// </summary>
|
||||
public async Task<string> GenerateMyInviteCodeAsync()
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
|
||||
// 生成邀请码(由Manager处理)
|
||||
var code = await _inviteCodeManager.GenerateInviteCodeForUserAsync(userId);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
#region 私有辅助方法
|
||||
|
||||
/// <summary>
|
||||
/// 构建翻牌记录列表
|
||||
/// </summary>
|
||||
private List<CardFlipRecord> BuildFlipRecords(CardFlipTaskAggregateRoot? task)
|
||||
{
|
||||
var records = new List<CardFlipRecord>();
|
||||
|
||||
// 获取已翻牌的顺序
|
||||
var flippedOrder = task != null ? _cardFlipManager.GetFlippedOrder(task) : new List<int>();
|
||||
var flippedNumbers = new HashSet<int>(flippedOrder);
|
||||
|
||||
// 获取中奖记录
|
||||
var winRecords = task?.WinRecords ?? new Dictionary<int, long>();
|
||||
|
||||
// 构建记录,按照原始序号1-10排列
|
||||
for (int i = 1; i <= CardFlipManager.TOTAL_MAX_FLIPS; i++)
|
||||
{
|
||||
var record = new CardFlipRecord
|
||||
{
|
||||
FlipNumber = i,
|
||||
IsFlipped = flippedNumbers.Contains(i),
|
||||
IsWin = false,
|
||||
FlipTypeDesc = CardFlipManager.GetFlipTypeDesc(i),
|
||||
// 设置在翻牌顺序中的位置(0表示未翻,>0表示第几个翻的)
|
||||
FlipOrderIndex = flippedOrder.IndexOf(i) >= 0 ? flippedOrder.IndexOf(i) + 1 : 0
|
||||
};
|
||||
|
||||
// 设置中奖信息
|
||||
// 判断这张卡是第几次翻的
|
||||
if (task != null && flippedNumbers.Contains(i))
|
||||
{
|
||||
var flipOrderIndex = flippedOrder.IndexOf(i) + 1; // 第几次翻的(1-based)
|
||||
|
||||
// 检查这次翻牌是否中奖
|
||||
if (winRecords.TryGetValue(flipOrderIndex, out var rewardAmount))
|
||||
{
|
||||
record.IsWin = true;
|
||||
record.RewardAmount = rewardAmount;
|
||||
}
|
||||
}
|
||||
|
||||
records.Add(record);
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成下次翻牌提示
|
||||
/// </summary>
|
||||
private string GenerateNextFlipTip(CardFlipStatusOutput status)
|
||||
{
|
||||
if (status.TotalFlips >= CardFlipManager.TOTAL_MAX_FLIPS)
|
||||
{
|
||||
return "本周翻牌次数已用完,请下周再来!";
|
||||
}
|
||||
|
||||
if (status.RemainingFreeFlips > 0)
|
||||
{
|
||||
return $"本周您还有{status.RemainingFreeFlips}次免费翻牌机会";
|
||||
}
|
||||
else if (status.RemainingInviteFlips > 0)
|
||||
{
|
||||
if (status.TotalFlips >= 7)
|
||||
{
|
||||
return $"本周使用他人邀请码或他人使用你的邀请码,可解锁{status.RemainingInviteFlips}次翻牌,且必中大奖!每次中奖最大额度将翻倍!";
|
||||
}
|
||||
|
||||
return $"本周使用他人邀请码或他人使用你的邀请码,可解锁{status.RemainingInviteFlips}次翻牌,必中大奖!每次中奖最大额度将翻倍!";
|
||||
}
|
||||
|
||||
return "继续加油!";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发放奖励
|
||||
/// </summary>
|
||||
private async Task GrantRewardAsync(Guid userId, long amount, string description)
|
||||
{
|
||||
var premiumPackage = new PremiumPackageAggregateRoot(userId, amount, description)
|
||||
{
|
||||
PurchaseAmount = 0, // 奖励不需要付费
|
||||
Remark = $"翻牌活动奖励:{amount / 10000}w tokens"
|
||||
};
|
||||
|
||||
await _premiumPackageRepository.InsertAsync(premiumPackage);
|
||||
|
||||
_logger.LogInformation($"用户 {userId} 获得翻牌奖励 {amount / 10000}w tokens");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取周描述
|
||||
/// </summary>
|
||||
private string GetWeekDescription(DateTime date)
|
||||
{
|
||||
var weekStart = CardFlipManager.GetWeekStartDate(date);
|
||||
var weekEnd = weekStart.AddDays(6);
|
||||
|
||||
return $"{weekStart:MM-dd} 至 {weekEnd:MM-dd}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using Medallion.Threading;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.DailyTask;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.AiHub.Domain.Entities.Chat;
|
||||
using Yi.Framework.AiHub.Domain.Entities.Model;
|
||||
using Yi.Framework.AiHub.Domain.Extensions;
|
||||
using Yi.Framework.AiHub.Domain.Managers;
|
||||
using Yi.Framework.AiHub.Domain.Shared.Consts;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 每日任务服务
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
public class DailyTaskService : ApplicationService
|
||||
{
|
||||
private readonly ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> _dailyTaskRepository;
|
||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||
private readonly ILogger<DailyTaskService> _logger;
|
||||
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||
private readonly ISqlSugarRepository<AiModelEntity> _aiModelRepository;
|
||||
// 任务配置
|
||||
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
||||
_taskConfigs = new()
|
||||
{
|
||||
{ 1, (10000000, 1000000, "尊享包1000w token任务", "累积使用尊享包 1000w token") }, // 1000w消耗 -> 100w奖励
|
||||
{ 2, (30000000, 2000000, "尊享包3000w token任务", "累积使用尊享包 3000w token") } // 3000w消耗 -> 200w奖励
|
||||
};
|
||||
|
||||
public DailyTaskService(
|
||||
ISqlSugarRepository<DailyTaskRewardRecordAggregateRoot> dailyTaskRepository,
|
||||
ISqlSugarRepository<MessageAggregateRoot> messageRepository,
|
||||
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository,
|
||||
ILogger<DailyTaskService> logger, ISqlSugarRepository<AiModelEntity> aiModelRepository)
|
||||
{
|
||||
_dailyTaskRepository = dailyTaskRepository;
|
||||
_messageRepository = messageRepository;
|
||||
_premiumPackageRepository = premiumPackageRepository;
|
||||
_logger = logger;
|
||||
_aiModelRepository = aiModelRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取今日任务状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<DailyTaskStatusOutput> GetTodayTaskStatusAsync()
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var today = DateTime.Today;
|
||||
|
||||
// 1. 统计今日尊享包Token消耗量
|
||||
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
||||
|
||||
// 2. 查询今日已领取的任务
|
||||
var claimedTasks = await _dailyTaskRepository._DbQueryable
|
||||
.Where(x => x.UserId == userId && x.TaskDate == today)
|
||||
.Select(x => new { x.TaskLevel, x.IsRewarded })
|
||||
.ToListAsync();
|
||||
|
||||
// 3. 构建任务列表
|
||||
var tasks = new List<DailyTaskItem>();
|
||||
foreach (var (level, config) in _taskConfigs)
|
||||
{
|
||||
var claimed = claimedTasks.FirstOrDefault(x => x.TaskLevel == level);
|
||||
int status;
|
||||
|
||||
if (claimed != null && claimed.IsRewarded)
|
||||
{
|
||||
status = 2; // 已领取
|
||||
}
|
||||
else if (todayConsumed >= config.RequiredTokens)
|
||||
{
|
||||
status = 1; // 可领取
|
||||
}
|
||||
else
|
||||
{
|
||||
status = 0; // 未完成
|
||||
}
|
||||
|
||||
var progress = todayConsumed >= config.RequiredTokens
|
||||
? 100
|
||||
: Math.Round((decimal)todayConsumed / config.RequiredTokens * 100, 2);
|
||||
|
||||
tasks.Add(new DailyTaskItem
|
||||
{
|
||||
Level = level,
|
||||
Name = config.Name,
|
||||
Description = config.Description,
|
||||
RequiredTokens = config.RequiredTokens,
|
||||
RewardTokens = config.RewardTokens,
|
||||
Status = status,
|
||||
Progress = progress
|
||||
});
|
||||
}
|
||||
|
||||
return new DailyTaskStatusOutput
|
||||
{
|
||||
TodayConsumedTokens = todayConsumed,
|
||||
Tasks = tasks
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 领取任务奖励
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task ClaimTaskRewardAsync(ClaimTaskRewardInput input)
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
//自旋等待,防抖
|
||||
await using var handle =
|
||||
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ClaimTaskRewardLock:{userId}");
|
||||
|
||||
|
||||
var today = DateTime.Today;
|
||||
|
||||
// 1. 验证任务等级
|
||||
if (!_taskConfigs.TryGetValue(input.TaskLevel, out var taskConfig))
|
||||
{
|
||||
throw new UserFriendlyException($"无效的任务等级: {input.TaskLevel}");
|
||||
}
|
||||
|
||||
// 2. 检查是否已领取
|
||||
var existingRecord = await _dailyTaskRepository._DbQueryable
|
||||
.Where(x => x.UserId == userId && x.TaskDate == today && x.TaskLevel == input.TaskLevel)
|
||||
.FirstAsync();
|
||||
|
||||
if (existingRecord != null)
|
||||
{
|
||||
throw new UserFriendlyException("今日该任务奖励已领取,请明天再来!");
|
||||
}
|
||||
|
||||
// 3. 验证今日Token消耗是否达标
|
||||
var todayConsumed = await GetTodayPremiumTokenConsumptionAsync(userId, today);
|
||||
if (todayConsumed < taskConfig.RequiredTokens)
|
||||
{
|
||||
throw new UserFriendlyException(
|
||||
$"Token消耗未达标!需要 {taskConfig.RequiredTokens / 10000}w,当前 {todayConsumed / 10000}w");
|
||||
}
|
||||
|
||||
// 4. 创建奖励包(使用 PremiumPackageManager)
|
||||
|
||||
var premiumPackage =
|
||||
new PremiumPackageAggregateRoot(userId, taskConfig.RewardTokens, $"每日任务:{taskConfig.Name}")
|
||||
{
|
||||
PurchaseAmount = 0, // 奖励不需要付费
|
||||
Remark = $"{today:yyyy-MM-dd} 每日任务奖励"
|
||||
};
|
||||
|
||||
await _premiumPackageRepository.InsertAsync(premiumPackage);
|
||||
|
||||
// 5. 记录领取记录
|
||||
var record = new DailyTaskRewardRecordAggregateRoot(userId, input.TaskLevel, today, taskConfig.RewardTokens)
|
||||
{
|
||||
Remark = $"完成任务{input.TaskLevel},名称:{taskConfig.Name},消耗 {todayConsumed / 10000}w token"
|
||||
};
|
||||
|
||||
await _dailyTaskRepository.InsertAsync(record);
|
||||
|
||||
_logger.LogInformation(
|
||||
$"用户 {userId} 领取每日任务 {input.TaskLevel} 奖励成功,获得 {taskConfig.RewardTokens / 10000}w tokens");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取今日尊享包Token消耗量
|
||||
/// </summary>
|
||||
/// <param name="userId">用户ID</param>
|
||||
/// <param name="today">今日日期</param>
|
||||
/// <returns>消耗的Token总数</returns>
|
||||
private async Task<long> GetTodayPremiumTokenConsumptionAsync(Guid userId, DateTime today)
|
||||
{
|
||||
var tomorrow = today.AddDays(1);
|
||||
|
||||
// 查询今日所有使用尊享包模型的消息(role=system 表示消耗)
|
||||
// 先获取所有尊享模型的ModelId列表
|
||||
var premiumModelIds = await _aiModelRepository._DbQueryable
|
||||
.Where(x => x.IsPremium)
|
||||
.Select(x => x.ModelId)
|
||||
.ToListAsync();
|
||||
|
||||
var totalTokens = await _messageRepository._DbQueryable
|
||||
.Where(x => x.UserId == userId)
|
||||
.Where(x => x.Role == "system") // system角色表示实际消耗
|
||||
.Where(x => premiumModelIds.Contains(x.ModelId)) // 尊享包模型
|
||||
.Where(x => x.CreationTime >= today && x.CreationTime < tomorrow)
|
||||
.SumAsync(x => x.TokenUsage.TotalTokenCount);
|
||||
|
||||
return totalTokens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.AiHub.Domain.Entities.Chat;
|
||||
using Yi.Framework.Rbac.Application.Contracts.IServices;
|
||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
using Yi.Framework.AiHub.Domain.Extensions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
public class AiAccountService : ApplicationService
|
||||
{
|
||||
private IAccountService _accountService;
|
||||
private ISqlSugarRepository<AiUserExtraInfoEntity> _userRepository;
|
||||
private ISqlSugarRepository<AiRechargeAggregateRoot> _rechargeRepository;
|
||||
private ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||
private ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||
public AiAccountService(
|
||||
IAccountService accountService,
|
||||
ISqlSugarRepository<AiUserExtraInfoEntity> userRepository,
|
||||
ISqlSugarRepository<AiRechargeAggregateRoot> rechargeRepository,
|
||||
ISqlSugarRepository<PremiumPackageAggregateRoot> premiumPackageRepository, ISqlSugarRepository<MessageAggregateRoot> messageRepository)
|
||||
{
|
||||
_accountService = accountService;
|
||||
_userRepository = userRepository;
|
||||
_rechargeRepository = rechargeRepository;
|
||||
_premiumPackageRepository = premiumPackageRepository;
|
||||
_messageRepository = messageRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取ai用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
[HttpGet("account/ai")]
|
||||
public async Task<AiUserRoleMenuDto> GetAsync()
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
var userAccount = await _accountService.GetAsync(null, null, userId: CurrentUser.GetId());
|
||||
var output = userAccount.Adapt<AiUserRoleMenuDto>();
|
||||
|
||||
// 是否绑定服务号
|
||||
output.IsBindFuwuhao = await _userRepository.IsAnyAsync(x => userId == x.UserId);
|
||||
|
||||
// 是否为VIP用户
|
||||
output.IsVip = CurrentUser.IsAiVip();
|
||||
|
||||
// 获取VIP到期时间
|
||||
if (output.IsVip)
|
||||
{
|
||||
var recharges = await _rechargeRepository._DbQueryable
|
||||
.Where(x => x.UserId == userId)
|
||||
.ToListAsync();
|
||||
|
||||
if (recharges.Any())
|
||||
{
|
||||
// 如果有任何一个充值记录的过期时间为null,说明是永久VIP
|
||||
if (recharges.Any(x => !x.ExpireDateTime.HasValue))
|
||||
{
|
||||
output.VipExpireTime = null; // 永久VIP
|
||||
}
|
||||
else
|
||||
{
|
||||
// 取最大的过期时间
|
||||
output.VipExpireTime = recharges
|
||||
.Where(x => x.ExpireDateTime.HasValue)
|
||||
.Max(x => x.ExpireDateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取利润统计数据
|
||||
/// </summary>
|
||||
/// <param name="currentCost">当前成本(RMB)</param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
[HttpGet("account/profit-statistics")]
|
||||
public async Task<string> GetProfitStatisticsAsync([FromQuery] decimal currentCost)
|
||||
{
|
||||
if (CurrentUser.UserName != "Guo" && CurrentUser.UserName != "cc")
|
||||
{
|
||||
throw new UserFriendlyException("您暂无权限访问");
|
||||
}
|
||||
|
||||
// 1. 获取尊享包总消耗和剩余库存
|
||||
var premiumPackages = await _premiumPackageRepository._DbQueryable.ToListAsync();
|
||||
long totalUsedTokens = premiumPackages.Sum(p => p.UsedTokens);
|
||||
long totalRemainingTokens = premiumPackages.Sum(p => p.RemainingTokens);
|
||||
|
||||
// 2. 计算1亿Token成本
|
||||
decimal costPerHundredMillion = totalUsedTokens > 0
|
||||
? currentCost / (totalUsedTokens / 100000000m)
|
||||
: 0;
|
||||
|
||||
// 3. 计算总成本(剩余+已使用的总成本)
|
||||
long totalTokens = totalUsedTokens + totalRemainingTokens;
|
||||
decimal totalCost = totalTokens > 0
|
||||
? (totalTokens / 100000000m) * costPerHundredMillion
|
||||
: 0;
|
||||
|
||||
// 4. 获取总收益(RechargeType=PremiumPackage的充值金额总和)
|
||||
decimal totalRevenue = await _rechargeRepository._DbQueryable
|
||||
.Where(x => x.RechargeType == Domain.Shared.Enums.RechargeTypeEnum.PremiumPackage)
|
||||
.SumAsync(x => x.RechargeAmount);
|
||||
|
||||
// 5. 计算利润率
|
||||
decimal profitRate = totalCost > 0
|
||||
? (totalRevenue / totalCost - 1) * 100
|
||||
: 0;
|
||||
|
||||
// 6. 按200售价计算成本
|
||||
decimal costAt200Price = totalRevenue > 0
|
||||
? (totalCost / totalRevenue) * 200
|
||||
: 0;
|
||||
|
||||
// 7. 格式化输出
|
||||
var today = DateTime.Now;
|
||||
string dayOfWeek = today.ToString("dddd", new System.Globalization.CultureInfo("zh-CN"));
|
||||
string weekDay = dayOfWeek switch
|
||||
{
|
||||
"星期一" => "周1",
|
||||
"星期二" => "周2",
|
||||
"星期三" => "周3",
|
||||
"星期四" => "周4",
|
||||
"星期五" => "周5",
|
||||
"星期六" => "周6",
|
||||
"星期日" => "周日",
|
||||
_ => dayOfWeek
|
||||
};
|
||||
|
||||
var result = $@"{today:M月d日} {weekDay}
|
||||
尊享包已消耗({totalUsedTokens / 100000000m:F2}亿){totalUsedTokens}
|
||||
尊享包剩余库存({totalRemainingTokens / 100000000m:F2}亿){totalRemainingTokens}
|
||||
当前成本:{currentCost:F2}RMB
|
||||
1亿Token成本:{costPerHundredMillion:F2} RMB=1亿 Token
|
||||
总成本:{totalCost:F2} RMB
|
||||
总收益:{totalRevenue:F2}RMB
|
||||
利润率: {profitRate:F1}%
|
||||
按200售价来算,成本在{costAt200Price:F2}";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public class TokenStatisticsInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定日期(当天零点)
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 模型Id -> 1亿Token成本(RMB)
|
||||
/// </summary>
|
||||
public Dictionary<string, decimal> ModelCosts { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期各模型Token统计
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[HttpPost("account/token-statistics")]
|
||||
public async Task<string> GetTokenStatisticsAsync([FromBody] TokenStatisticsInput input)
|
||||
{
|
||||
if (CurrentUser.UserName != "Guo" && CurrentUser.UserName != "cc")
|
||||
{
|
||||
throw new UserFriendlyException("您暂无权限访问");
|
||||
}
|
||||
|
||||
if (input.ModelCosts is null || input.ModelCosts.Count == 0)
|
||||
{
|
||||
throw new UserFriendlyException("请提供模型成本配置");
|
||||
}
|
||||
|
||||
var day = input.Date.Date;
|
||||
var nextDay = day.AddDays(1);
|
||||
var modelIds = input.ModelCosts.Keys.ToList();
|
||||
|
||||
var modelStats = await _messageRepository._DbQueryable
|
||||
.Where(x => modelIds.Contains(x.ModelId))
|
||||
.Where(x => x.CreationTime >= day && x.CreationTime < nextDay)
|
||||
.Where(x => x.Role == "system")
|
||||
.GroupBy(x => x.ModelId)
|
||||
.Select(x => new
|
||||
{
|
||||
ModelId = x.ModelId,
|
||||
Tokens = SqlFunc.AggregateSum(x.TokenUsage.TotalTokenCount),
|
||||
Count = SqlFunc.AggregateCount(x.Id)
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
var modelStatDict = modelStats.ToDictionary(x => x.ModelId, x => x);
|
||||
|
||||
string weekDay = day.ToString("dddd", new CultureInfo("zh-CN")) switch
|
||||
{
|
||||
"星期一" => "周1",
|
||||
"星期二" => "周2",
|
||||
"星期三" => "周3",
|
||||
"星期四" => "周4",
|
||||
"星期五" => "周5",
|
||||
"星期六" => "周6",
|
||||
"星期日" => "周日",
|
||||
_ => day.ToString("dddd", new CultureInfo("zh-CN"))
|
||||
};
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"{day:M月d日} {weekDay}");
|
||||
|
||||
foreach (var kvp in input.ModelCosts)
|
||||
{
|
||||
var modelId = kvp.Key;
|
||||
var cost = kvp.Value;
|
||||
|
||||
modelStatDict.TryGetValue(modelId, out var stat);
|
||||
long tokens = stat?.Tokens ?? 0;
|
||||
long count = stat?.Count ?? 0;
|
||||
|
||||
decimal costPerHundredMillion = tokens > 0
|
||||
? cost / (tokens / 100000000m)
|
||||
: 0;
|
||||
|
||||
decimal tokensInWan = tokens / 10000m;
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"{modelId} 成本:【{cost:F2}RMB】 次数:【{count}次】 token:【{tokensInWan:F0}w】 1亿token成本:【{costPerHundredMillion:F2}RMB】");
|
||||
}
|
||||
|
||||
return sb.ToString().TrimEnd();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Mapster;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Caching;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos.Announcement;
|
||||
using Yi.Framework.AiHub.Application.Contracts.IServices;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 公告服务
|
||||
/// </summary>
|
||||
public class AnnouncementService : ApplicationService, IAnnouncementService
|
||||
{
|
||||
private readonly ISqlSugarRepository<AnnouncementAggregateRoot> _announcementRepository;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IDistributedCache<AnnouncementCacheDto> _announcementCache;
|
||||
private const string AnnouncementCacheKey = "AiHub:Announcement";
|
||||
|
||||
public AnnouncementService(
|
||||
ISqlSugarRepository<AnnouncementAggregateRoot> announcementRepository,
|
||||
IConfiguration configuration,
|
||||
IDistributedCache<AnnouncementCacheDto> announcementCache)
|
||||
{
|
||||
_announcementRepository = announcementRepository;
|
||||
_configuration = configuration;
|
||||
_announcementCache = announcementCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取公告信息
|
||||
/// </summary>
|
||||
public async Task<List<AnnouncementLogDto>> GetAsync()
|
||||
{
|
||||
// 使用 GetOrAddAsync 从缓存获取或添加数据,缓存1小时
|
||||
var cacheData = await _announcementCache.GetOrAddAsync(
|
||||
AnnouncementCacheKey,
|
||||
async () => await LoadAnnouncementDataAsync(),
|
||||
() => new DistributedCacheEntryOptions
|
||||
{
|
||||
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
|
||||
}
|
||||
);
|
||||
|
||||
return cacheData?.Logs ?? new List<AnnouncementLogDto>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从数据库加载公告数据
|
||||
/// </summary>
|
||||
private async Task<AnnouncementCacheDto> LoadAnnouncementDataAsync()
|
||||
{
|
||||
// 查询所有公告日志,按日期降序排列
|
||||
var logs = await _announcementRepository._DbQueryable
|
||||
.OrderByDescending(x => x.StartTime)
|
||||
.ToListAsync();
|
||||
|
||||
// 转换为 DTO
|
||||
var logDtos = logs.Adapt<List<AnnouncementLogDto>>();
|
||||
return new AnnouncementCacheDto
|
||||
{
|
||||
Logs = logDtos
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user