fdb2 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/.dockerignore +21 -21
  2. package/.editorconfig +11 -11
  3. package/.eslintrc.cjs +14 -14
  4. package/.eslintrc.json +7 -7
  5. package/.prettierrc.js +3 -3
  6. package/.tpl.env +21 -21
  7. package/.vscodeignore +45 -45
  8. package/README.md +312 -312
  9. package/bin/build.sh +28 -28
  10. package/bin/deploy.sh +8 -8
  11. package/bin/dev.sh +10 -10
  12. package/bin/docker/dev-docker-compose.yml +43 -43
  13. package/bin/docker/dev.Dockerfile +24 -24
  14. package/bin/docker/prod-docker-compose.yml +17 -17
  15. package/bin/docker/prod.Dockerfile +29 -29
  16. package/bin/fdb2.js +220 -220
  17. package/dist/package.json +29 -29
  18. package/dist/pnpm-lock.yaml +1042 -354
  19. package/dist/public/explorer.css +1464 -1437
  20. package/dist/public/explorer.js +764 -226
  21. package/dist/public/index.css +1026 -1026
  22. package/dist/public/index.js +15 -9
  23. package/dist/public/layout.css +221 -221
  24. package/dist/public/layout.js +1 -1
  25. package/dist/public/vue.js +8 -2
  26. package/dist/scripts/preinstall.js +112 -112
  27. package/dist/server/index.d.ts.map +1 -1
  28. package/dist/server/index.js +8 -0
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/index.ts +680 -671
  31. package/dist/server/model/connection.entity.ts +65 -65
  32. package/dist/server/model/database.entity.ts +245 -245
  33. package/dist/server/service/connection.service.d.ts +6 -1
  34. package/dist/server/service/connection.service.d.ts.map +1 -1
  35. package/dist/server/service/connection.service.js +15 -0
  36. package/dist/server/service/connection.service.js.map +1 -1
  37. package/dist/server/service/connection.service.ts +356 -341
  38. package/dist/server/service/database/base.service.d.ts +27 -0
  39. package/dist/server/service/database/base.service.d.ts.map +1 -1
  40. package/dist/server/service/database/base.service.js +17 -0
  41. package/dist/server/service/database/base.service.js.map +1 -1
  42. package/dist/server/service/database/base.service.ts +406 -367
  43. package/dist/server/service/database/cockroachdb.service.d.ts +16 -0
  44. package/dist/server/service/database/cockroachdb.service.d.ts.map +1 -1
  45. package/dist/server/service/database/cockroachdb.service.js +220 -154
  46. package/dist/server/service/database/cockroachdb.service.js.map +1 -1
  47. package/dist/server/service/database/cockroachdb.service.ts +871 -782
  48. package/dist/server/service/database/database.service.d.ts +4 -0
  49. package/dist/server/service/database/database.service.d.ts.map +1 -1
  50. package/dist/server/service/database/database.service.js +123 -0
  51. package/dist/server/service/database/database.service.js.map +1 -1
  52. package/dist/server/service/database/database.service.ts +775 -638
  53. package/dist/server/service/database/index.ts +6 -6
  54. package/dist/server/service/database/mongodb.service.d.ts +16 -0
  55. package/dist/server/service/database/mongodb.service.d.ts.map +1 -1
  56. package/dist/server/service/database/mongodb.service.js +35 -0
  57. package/dist/server/service/database/mongodb.service.js.map +1 -1
  58. package/dist/server/service/database/mongodb.service.ts +39 -1
  59. package/dist/server/service/database/mssql.service.d.ts +16 -0
  60. package/dist/server/service/database/mssql.service.d.ts.map +1 -1
  61. package/dist/server/service/database/mssql.service.js +168 -96
  62. package/dist/server/service/database/mssql.service.js.map +1 -1
  63. package/dist/server/service/database/mssql.service.ts +931 -840
  64. package/dist/server/service/database/mysql.service.d.ts +16 -0
  65. package/dist/server/service/database/mysql.service.d.ts.map +1 -1
  66. package/dist/server/service/database/mysql.service.js +189 -80
  67. package/dist/server/service/database/mysql.service.js.map +1 -1
  68. package/dist/server/service/database/mysql.service.ts +1025 -890
  69. package/dist/server/service/database/oracle.service.d.ts +16 -0
  70. package/dist/server/service/database/oracle.service.d.ts.map +1 -1
  71. package/dist/server/service/database/oracle.service.js +182 -120
  72. package/dist/server/service/database/oracle.service.js.map +1 -1
  73. package/dist/server/service/database/oracle.service.ts +1035 -959
  74. package/dist/server/service/database/postgres.service.d.ts +16 -0
  75. package/dist/server/service/database/postgres.service.d.ts.map +1 -1
  76. package/dist/server/service/database/postgres.service.js +154 -88
  77. package/dist/server/service/database/postgres.service.js.map +1 -1
  78. package/dist/server/service/database/postgres.service.ts +960 -871
  79. package/dist/server/service/database/sap.service.d.ts +16 -0
  80. package/dist/server/service/database/sap.service.d.ts.map +1 -1
  81. package/dist/server/service/database/sap.service.js +66 -0
  82. package/dist/server/service/database/sap.service.js.map +1 -1
  83. package/dist/server/service/database/sap.service.ts +89 -0
  84. package/dist/server/service/database/sqlite.service.d.ts +16 -0
  85. package/dist/server/service/database/sqlite.service.d.ts.map +1 -1
  86. package/dist/server/service/database/sqlite.service.js +77 -18
  87. package/dist/server/service/database/sqlite.service.js.map +1 -1
  88. package/dist/server/service/database/sqlite.service.ts +787 -708
  89. package/dist/server/service/session.service.ts +158 -158
  90. package/dist/view/index.html +38 -38
  91. package/env.d.ts +1 -1
  92. package/package.json +1 -1
  93. package/packages/vscode/.vscodeignore +44 -44
  94. package/packages/vscode/README.md +62 -62
  95. package/packages/vscode/out/database-services/cockroachdb.service.js +154 -154
  96. package/packages/vscode/out/database-services/mssql.service.js +96 -96
  97. package/packages/vscode/out/database-services/mysql.service.js +80 -80
  98. package/packages/vscode/out/database-services/oracle.service.js +120 -120
  99. package/packages/vscode/out/database-services/postgres.service.js +88 -88
  100. package/packages/vscode/out/database-services/sqlite.service.js +18 -18
  101. package/packages/vscode/out/provider/WebViewProvider.js +32 -32
  102. package/packages/vscode/package.json +142 -142
  103. package/packages/vscode/resources/icon.svg +5 -5
  104. package/packages/vscode/resources/webview/connection.css +41 -41
  105. package/packages/vscode/resources/webview/database.css +163 -163
  106. package/packages/vscode/resources/webview/index.html +9 -9
  107. package/packages/vscode/resources/webview/modules/header.tpl +13 -13
  108. package/packages/vscode/resources/webview/modules/initial_state.tpl +54 -54
  109. package/packages/vscode/resources/webview/query.css +104 -104
  110. package/packages/vscode/src/database-services/base.service.ts +362 -362
  111. package/packages/vscode/src/database-services/cockroachdb.service.ts +659 -659
  112. package/packages/vscode/src/database-services/connection.service.ts +340 -340
  113. package/packages/vscode/src/database-services/database.service.ts +629 -629
  114. package/packages/vscode/src/database-services/index.ts +6 -6
  115. package/packages/vscode/src/database-services/model/connection.entity.ts +65 -65
  116. package/packages/vscode/src/database-services/model/database.entity.ts +245 -245
  117. package/packages/vscode/src/database-services/mssql.service.ts +722 -722
  118. package/packages/vscode/src/database-services/mysql.service.ts +760 -760
  119. package/packages/vscode/src/database-services/oracle.service.ts +831 -831
  120. package/packages/vscode/src/database-services/postgres.service.ts +740 -740
  121. package/packages/vscode/src/database-services/sqlite.service.ts +558 -558
  122. package/packages/vscode/src/extension.ts +76 -76
  123. package/packages/vscode/src/provider/DatabaseTreeProvider.ts +167 -167
  124. package/packages/vscode/src/provider/WebViewProvider.ts +277 -277
  125. package/packages/vscode/src/service/DatabaseServiceBridge.ts +414 -414
  126. package/packages/vscode/src/typings/connection.ts +90 -90
  127. package/packages/vscode/tsconfig.json +21 -21
  128. package/public/index.html +9 -9
  129. package/public/modules/header.tpl +13 -13
  130. package/public/modules/initial_state.tpl +54 -54
  131. package/scripts/preinstall.js +112 -112
  132. package/server/index.ts +680 -671
  133. package/server/model/connection.entity.ts +65 -65
  134. package/server/model/database.entity.ts +245 -245
  135. package/server/service/connection.service.ts +356 -341
  136. package/server/service/database/base.service.ts +406 -367
  137. package/server/service/database/cockroachdb.service.ts +871 -782
  138. package/server/service/database/database.service.ts +775 -638
  139. package/server/service/database/index.ts +6 -6
  140. package/server/service/database/mongodb.service.ts +39 -1
  141. package/server/service/database/mssql.service.ts +931 -840
  142. package/server/service/database/mysql.service.ts +1025 -890
  143. package/server/service/database/oracle.service.ts +1035 -959
  144. package/server/service/database/postgres.service.ts +960 -871
  145. package/server/service/database/sap.service.ts +89 -0
  146. package/server/service/database/sqlite.service.ts +787 -708
  147. package/server/service/session.service.ts +158 -158
  148. package/server/tsconfig.json +20 -20
  149. package/server.js +149 -149
  150. package/server.pid +1 -0
  151. package/src/adapter/ajax.ts +135 -135
  152. package/src/assets/base.css +1 -1
  153. package/src/assets/database.css +949 -949
  154. package/src/assets/images/svg/illustrations/illustration-1.svg +1 -1
  155. package/src/assets/images/svg/illustrations/illustration-2.svg +2 -2
  156. package/src/assets/images/svg/illustrations/illustration-3.svg +50 -50
  157. package/src/assets/images/svg/illustrations/illustration-4.svg +1 -1
  158. package/src/assets/images/svg/illustrations/illustration-5.svg +73 -73
  159. package/src/assets/images/svg/illustrations/illustration-6.svg +89 -89
  160. package/src/assets/images/svg/illustrations/illustration-7.svg +39 -39
  161. package/src/assets/images/svg/separators/curve-2.svg +3 -3
  162. package/src/assets/images/svg/separators/curve.svg +3 -3
  163. package/src/assets/images/svg/separators/line.svg +3 -3
  164. package/src/assets/logo.svg +73 -73
  165. package/src/assets/main.css +1 -1
  166. package/src/base/config.ts +20 -20
  167. package/src/base/detect.ts +134 -134
  168. package/src/base/entity.ts +92 -92
  169. package/src/base/eventBus.ts +36 -36
  170. package/src/components/connection-editor/index.vue +588 -588
  171. package/src/components/dataGrid/index.vue +104 -104
  172. package/src/components/dataGrid/pagination.vue +105 -105
  173. package/src/components/loading/index.vue +42 -42
  174. package/src/components/modal/index.ts +180 -180
  175. package/src/components/modal/index.vue +560 -560
  176. package/src/components/toast/index.ts +43 -43
  177. package/src/components/toast/toast.vue +57 -57
  178. package/src/components/user/name.vue +103 -103
  179. package/src/components/user/selector.vue +416 -416
  180. package/src/domain/SysConfig.ts +74 -74
  181. package/src/platform/App.vue +7 -7
  182. package/src/platform/database/components/connection-detail.vue +1153 -1154
  183. package/src/platform/database/components/data-editor.vue +477 -477
  184. package/src/platform/database/components/database-detail.vue +1173 -1172
  185. package/src/platform/database/components/database-monitor.vue +1085 -1085
  186. package/src/platform/database/components/db-tools.vue +1264 -816
  187. package/src/platform/database/components/query-history.vue +1348 -1348
  188. package/src/platform/database/components/sql-executor.vue +737 -737
  189. package/src/platform/database/components/sql-query-editor.vue +1045 -1045
  190. package/src/platform/database/components/table-detail.vue +1375 -1376
  191. package/src/platform/database/components/table-editor.vue +916 -916
  192. package/src/platform/database/explorer.vue +1839 -1839
  193. package/src/platform/database/index.vue +1192 -1192
  194. package/src/platform/database/layout.vue +366 -366
  195. package/src/platform/database/router.ts +36 -36
  196. package/src/platform/database/styles/common.scss +601 -601
  197. package/src/platform/database/types/common.ts +444 -444
  198. package/src/platform/database/utils/export.ts +231 -231
  199. package/src/platform/database/utils/helpers.ts +436 -436
  200. package/src/platform/index.ts +32 -32
  201. package/src/platform/router.ts +40 -40
  202. package/src/platform/vscode/bridge.ts +121 -121
  203. package/src/platform/vscode/components/ConnectionPanel.vue +272 -272
  204. package/src/platform/vscode/components/DatabasePanel.vue +532 -532
  205. package/src/platform/vscode/components/QueryPanel.vue +371 -371
  206. package/src/platform/vscode/entry/connection.ts +13 -13
  207. package/src/platform/vscode/entry/database.ts +13 -13
  208. package/src/platform/vscode/entry/query.ts +13 -13
  209. package/src/platform/vscode/index.ts +5 -5
  210. package/src/service/base.ts +133 -127
  211. package/src/service/database.ts +505 -495
  212. package/src/service/login.ts +120 -120
  213. package/src/shims-vue.d.ts +6 -6
  214. package/src/stores/connection.ts +266 -266
  215. package/src/stores/session.ts +87 -87
  216. package/src/typings/database-types.ts +412 -412
  217. package/src/typings/database.ts +363 -363
  218. package/src/typings/global.d.ts +58 -58
  219. package/src/typings/pinia.d.ts +7 -7
  220. package/src/utils/clipboard.ts +29 -29
  221. package/src/utils/database-types.ts +242 -242
  222. package/src/utils/modal.ts +123 -123
  223. package/src/utils/request.ts +55 -55
  224. package/src/utils/sleep.ts +3 -3
  225. package/src/utils/toast.ts +73 -73
  226. package/src/utils/util.ts +171 -171
  227. package/src/utils/xlsx.ts +228 -228
  228. package/tsconfig.json +33 -33
  229. package/view/index.html +9 -9
  230. package/view/modules/header.tpl +13 -13
  231. package/view/modules/initial_state.tpl +19 -19
  232. package/vite.config.ts +424 -424
  233. package/vite.config.vscode.ts +47 -47
  234. package/server/backups/db_ai_breakout_2026-03-11T08-38-48-677Z.sql +0 -0
@@ -1,602 +1,602 @@
1
- // 数据库平台公共样式
2
-
3
- // 颜色变量
4
- :root {
5
- --primary-color: #667eea;
6
- --primary-dark: #5a67d8;
7
- --secondary-color: #764ba2;
8
- --success-color: #10b981;
9
- --warning-color: #f59e0b;
10
- --error-color: #ef4444;
11
- --info-color: #3b82f6;
12
-
13
- --text-primary: #1e293b;
14
- --text-secondary: #64748b;
15
- --text-muted: #94a3b8;
16
-
17
- --bg-primary: #ffffff;
18
- --bg-secondary: #f8fafc;
19
- --bg-tertiary: #f1f5f9;
20
-
21
- --border-color: #e5e7eb;
22
- --border-hover: #d1d5db;
23
- --border-focus: #667eea;
24
-
25
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
26
- --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
27
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
28
- --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
29
-
30
- --radius-sm: 4px;
31
- --radius-md: 8px;
32
- --radius-lg: 12px;
33
- --radius-xl: 16px;
34
- }
35
-
36
- // 通用渐变背景
37
- .gradient-primary {
38
- background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
39
- }
40
-
41
- .gradient-secondary {
42
- background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%);
43
- }
44
-
45
- .gradient-success {
46
- background: linear-gradient(135deg, var(--success-color) 0%, #059669 100%);
47
- }
48
-
49
- .gradient-warning {
50
- background: linear-gradient(135deg, var(--warning-color) 0%, #d97706 100%);
51
- }
52
-
53
- .gradient-error {
54
- background: linear-gradient(135deg, var(--error-color) 0%, #dc2626 100%);
55
- }
56
-
57
- .gradient-info {
58
- background: linear-gradient(135deg, var(--info-color) 0%, #2563eb 100%);
59
- }
60
-
61
- // 通用按钮样式
62
- .btn {
63
- display: inline-flex;
64
- align-items: center;
65
- justify-content: center;
66
- gap: 0.5rem;
67
- padding: 0.75rem 1.5rem;
68
- border: 1px solid var(--border-color);
69
- border-radius: var(--radius-md);
70
- font-size: 0.875rem;
71
- font-weight: 500;
72
- cursor: pointer;
73
- transition: all 0.2s ease;
74
- text-decoration: none;
75
- outline: none;
76
- user-select: none;
77
-
78
- &:hover:not(:disabled) {
79
- transform: translateY(-1px);
80
- box-shadow: var(--shadow-md);
81
- }
82
-
83
- &:active {
84
- transform: translateY(0);
85
- }
86
-
87
- &:disabled {
88
- opacity: 0.5;
89
- cursor: not-allowed;
90
- }
91
-
92
- &.btn-primary {
93
- @extend .gradient-primary;
94
- color: white;
95
- border: none;
96
-
97
- &:hover:not(:disabled) {
98
- background: linear-gradient(135deg, var(--primary-dark) 0%, var(--secondary-color) 100%);
99
- }
100
- }
101
-
102
- &.btn-success {
103
- @extend .gradient-success;
104
- color: white;
105
- border: none;
106
- }
107
-
108
- &.btn-warning {
109
- @extend .gradient-warning;
110
- color: white;
111
- border: none;
112
- }
113
-
114
- &.btn-danger {
115
- @extend .gradient-error;
116
- color: white;
117
- border: none;
118
- }
119
-
120
- &.btn-info {
121
- @extend .gradient-info;
122
- color: white;
123
- border: none;
124
- }
125
-
126
- &.btn-outline {
127
- background: transparent;
128
- color: var(--primary-color);
129
- border-color: var(--primary-color);
130
-
131
- &:hover:not(:disabled) {
132
- background: var(--primary-color);
133
- color: white;
134
- }
135
- }
136
-
137
- &.btn-ghost {
138
- background: transparent;
139
- color: var(--text-secondary);
140
-
141
- &:hover:not(:disabled) {
142
- background: var(--bg-secondary);
143
- color: var(--text-primary);
144
- }
145
- }
146
-
147
- &.btn-sm {
148
- padding: 0.5rem 1rem;
149
- font-size: 0.75rem;
150
- }
151
-
152
- &.btn-lg {
153
- padding: 1rem 2rem;
154
- font-size: 1rem;
155
- }
156
- }
157
-
158
- // 通用卡片样式
159
- .card {
160
- background: var(--bg-primary);
161
- border: 1px solid var(--border-color);
162
- border-radius: var(--radius-lg);
163
- box-shadow: var(--shadow-sm);
164
- overflow: hidden;
165
- transition: all 0.2s ease;
166
-
167
- &:hover {
168
- box-shadow: var(--shadow-md);
169
- transform: translateY(-2px);
170
- }
171
-
172
- &.card-flat {
173
- box-shadow: none;
174
-
175
- &:hover {
176
- box-shadow: var(--shadow-sm);
177
- transform: none;
178
- }
179
- }
180
-
181
- .card-header {
182
- padding: 1rem 1.5rem;
183
- border-bottom: 1px solid var(--border-color);
184
- background: var(--bg-secondary);
185
-
186
- .card-title {
187
- font-size: 1.125rem;
188
- font-weight: 600;
189
- color: var(--text-primary);
190
- margin: 0;
191
- }
192
- }
193
-
194
- .card-body {
195
- padding: 1.5rem;
196
- }
197
-
198
- .card-footer {
199
- padding: 1rem 1.5rem;
200
- border-top: 1px solid var(--border-color);
201
- background: var(--bg-secondary);
202
- }
203
- }
204
-
205
- // 通用表单样式
206
- .form-group {
207
- margin-bottom: 1rem;
208
-
209
- label {
210
- display: block;
211
- margin-bottom: 0.5rem;
212
- font-weight: 500;
213
- color: var(--text-primary);
214
- font-size: 0.875rem;
215
- }
216
- }
217
-
218
- .form-input,
219
- .form-textarea,
220
- .form-select {
221
- width: 100%;
222
- padding: 0.75rem;
223
- border: 1px solid var(--border-color);
224
- border-radius: var(--radius-md);
225
- font-size: 0.875rem;
226
- transition: all 0.2s ease;
227
- background: var(--bg-primary);
228
-
229
- &:focus {
230
- outline: none;
231
- border-color: var(--border-focus);
232
- box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
233
- }
234
-
235
- &.is-invalid {
236
- border-color: var(--error-color);
237
-
238
- &:focus {
239
- box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
240
- }
241
- }
242
- }
243
-
244
- .form-textarea {
245
- resize: vertical;
246
- min-height: 100px;
247
- }
248
-
249
- // 通用表格样式
250
- .table {
251
- width: 100%;
252
- border-collapse: collapse;
253
- font-size: 0.875rem;
254
-
255
- th {
256
- background: var(--bg-secondary);
257
- padding: 0.75rem;
258
- text-align: left;
259
- font-weight: 600;
260
- color: var(--text-primary);
261
- border-bottom: 2px solid var(--border-color);
262
-
263
- &.sortable {
264
- cursor: pointer;
265
- user-select: none;
266
-
267
- &:hover {
268
- background: var(--bg-tertiary);
269
- }
270
- }
271
- }
272
-
273
- td {
274
- padding: 0.75rem;
275
- border-bottom: 1px solid var(--border-color);
276
- max-width: 200px;
277
- overflow: hidden;
278
- text-overflow: ellipsis;
279
- white-space: nowrap;
280
- }
281
-
282
- tr:hover {
283
- background: var(--bg-secondary);
284
- }
285
-
286
- &.table-sm {
287
- font-size: 0.75rem;
288
-
289
- th,
290
- td {
291
- padding: 0.5rem;
292
- }
293
- }
294
-
295
- &.table-hover {
296
- tbody tr {
297
- transition: background-color 0.2s ease;
298
- }
299
- }
300
-
301
- &.table-striped {
302
- tbody tr:nth-child(even) {
303
- background: var(--bg-secondary);
304
- }
305
- }
306
- }
307
-
308
- // 通用徽章样式
309
- .badge {
310
- display: inline-flex;
311
- align-items: center;
312
- padding: 0.25rem 0.75rem;
313
- border-radius: 20px;
314
- font-size: 0.75rem;
315
- font-weight: 600;
316
- text-transform: uppercase;
317
- letter-spacing: 0.05em;
318
-
319
- &.badge-primary {
320
- background: rgba(102, 126, 234, 0.1);
321
- color: var(--primary-color);
322
- }
323
-
324
- &.badge-success {
325
- background: rgba(16, 185, 129, 0.1);
326
- color: var(--success-color);
327
- }
328
-
329
- &.badge-warning {
330
- background: rgba(245, 158, 11, 0.1);
331
- color: var(--warning-color);
332
- }
333
-
334
- &.badge-error {
335
- background: rgba(239, 68, 68, 0.1);
336
- color: var(--error-color);
337
- }
338
-
339
- &.badge-info {
340
- background: rgba(59, 130, 246, 0.1);
341
- color: var(--info-color);
342
- }
343
- }
344
-
345
- // 通用状态指示器
346
- .status-indicator {
347
- display: inline-flex;
348
- align-items: center;
349
- gap: 0.5rem;
350
- font-size: 0.875rem;
351
-
352
- .status-dot {
353
- width: 8px;
354
- height: 8px;
355
- border-radius: 50%;
356
-
357
- &.online {
358
- background: var(--success-color);
359
- box-shadow: 0 0 8px rgba(16, 185, 129, 0.5);
360
- }
361
-
362
- &.offline {
363
- background: var(--text-muted);
364
- }
365
-
366
- &.warning {
367
- background: var(--warning-color);
368
- box-shadow: 0 0 8px rgba(245, 158, 11, 0.5);
369
- }
370
-
371
- &.error {
372
- background: var(--error-color);
373
- box-shadow: 0 0 8px rgba(239, 68, 68, 0.5);
374
- }
375
- }
376
- }
377
-
378
- // 通用加载动画
379
- .loading {
380
- display: inline-flex;
381
- align-items: center;
382
- gap: 0.5rem;
383
-
384
- .spinner {
385
- width: 16px;
386
- height: 16px;
387
- border: 2px solid var(--border-color);
388
- border-top-color: var(--primary-color);
389
- border-radius: 50%;
390
- animation: spin 1s linear infinite;
391
- }
392
- }
393
-
394
- @keyframes spin {
395
- from {
396
- transform: rotate(0deg);
397
- }
398
- to {
399
- transform: rotate(360deg);
400
- }
401
- }
402
-
403
- // 通用模态框样式
404
- .modal {
405
- position: fixed;
406
- top: 0;
407
- left: 0;
408
- right: 0;
409
- bottom: 0;
410
- background: rgba(0, 0, 0, 0.5);
411
- display: flex;
412
- justify-content: center;
413
- align-items: center;
414
- z-index: 1000;
415
- backdrop-filter: blur(4px);
416
-
417
- .modal-content {
418
- background: var(--bg-primary);
419
- border-radius: var(--radius-xl);
420
- box-shadow: var(--shadow-xl);
421
- max-width: 90vw;
422
- max-height: 90vh;
423
- overflow: hidden;
424
- display: flex;
425
- flex-direction: column;
426
-
427
- .modal-header {
428
- padding: 1.5rem;
429
- border-bottom: 1px solid var(--border-color);
430
- display: flex;
431
- justify-content: space-between;
432
- align-items: center;
433
-
434
- .modal-title {
435
- font-size: 1.25rem;
436
- font-weight: 600;
437
- color: var(--text-primary);
438
- margin: 0;
439
- }
440
-
441
- .modal-close {
442
- background: none;
443
- border: none;
444
- font-size: 1.5rem;
445
- cursor: pointer;
446
- color: var(--text-muted);
447
- padding: 0.25rem;
448
- border-radius: var(--radius-sm);
449
- transition: all 0.2s ease;
450
-
451
- &:hover {
452
- background: var(--bg-secondary);
453
- color: var(--text-primary);
454
- }
455
- }
456
- }
457
-
458
- .modal-body {
459
- padding: 1.5rem;
460
- flex: 1;
461
- overflow-y: auto;
462
- }
463
-
464
- .modal-footer {
465
- padding: 1.5rem;
466
- border-top: 1px solid var(--border-color);
467
- display: flex;
468
- justify-content: flex-end;
469
- gap: 0.5rem;
470
- }
471
- }
472
- }
473
-
474
- // 通用分页样式
475
- .pagination {
476
- display: flex;
477
- justify-content: center;
478
- align-items: center;
479
- gap: 0.5rem;
480
-
481
- .page-info {
482
- padding: 0.5rem 1rem;
483
- font-size: 0.875rem;
484
- color: var(--text-secondary);
485
- }
486
-
487
- .page-btn {
488
- padding: 0.5rem 0.75rem;
489
- border: 1px solid var(--border-color);
490
- border-radius: var(--radius-sm);
491
- background: var(--bg-primary);
492
- cursor: pointer;
493
- transition: all 0.2s ease;
494
-
495
- &:hover:not(:disabled) {
496
- background: var(--primary-color);
497
- color: white;
498
- border-color: var(--primary-color);
499
- }
500
-
501
- &:disabled {
502
- opacity: 0.5;
503
- cursor: not-allowed;
504
- }
505
-
506
- &.active {
507
- background: var(--primary-color);
508
- color: white;
509
- border-color: var(--primary-color);
510
- }
511
- }
512
- }
513
-
514
- // 通用工具类
515
- .text-center { text-align: center; }
516
- .text-left { text-align: left; }
517
- .text-right { text-align: right; }
518
-
519
- .text-primary { color: var(--text-primary); }
520
- .text-secondary { color: var(--text-secondary); }
521
- .text-muted { color: var(--text-muted); }
522
- .text-success { color: var(--success-color); }
523
- .text-warning { color: var(--warning-color); }
524
- .text-error { color: var(--error-color); }
525
- .text-info { color: var(--info-color); }
526
-
527
- .bg-primary { background: var(--bg-primary); }
528
- .bg-secondary { background: var(--bg-secondary); }
529
- .bg-tertiary { background: var(--bg-tertiary); }
530
-
531
- .border { border: 1px solid var(--border-color); }
532
- .border-top { border-top: 1px solid var(--border-color); }
533
- .border-bottom { border-bottom: 1px solid var(--border-color); }
534
- .border-left { border-left: 1px solid var(--border-color); }
535
- .border-right { border-right: 1px solid var(--border-color); }
536
-
537
- .rounded { border-radius: var(--radius-md); }
538
- .rounded-sm { border-radius: var(--radius-sm); }
539
- .rounded-lg { border-radius: var(--radius-lg); }
540
- .rounded-xl { border-radius: var(--radius-xl); }
541
-
542
- .shadow-sm { box-shadow: var(--shadow-sm); }
543
- .shadow-md { box-shadow: var(--shadow-md); }
544
- .shadow-lg { box-shadow: var(--shadow-lg); }
545
- .shadow-xl { box-shadow: var(--shadow-xl); }
546
-
547
- .p-0 { padding: 0; }
548
- .p-1 { padding: 0.25rem; }
549
- .p-2 { padding: 0.5rem; }
550
- .p-3 { padding: 0.75rem; }
551
- .p-4 { padding: 1rem; }
552
- .p-5 { padding: 1.5rem; }
553
-
554
- .m-0 { margin: 0; }
555
- .m-1 { margin: 0.25rem; }
556
- .m-2 { margin: 0.5rem; }
557
- .m-3 { margin: 0.75rem; }
558
- .m-4 { margin: 1rem; }
559
- .m-5 { margin: 1.5rem; }
560
-
561
- .d-none { display: none; }
562
- .d-block { display: block; }
563
- .d-flex { display: flex; }
564
- .d-inline { display: inline; }
565
- .d-inline-block { display: inline-block; }
566
-
567
- .flex-column { flex-direction: column; }
568
- .flex-row { flex-direction: row; }
569
- .justify-center { justify-content: center; }
570
- .justify-between { justify-content: space-between; }
571
- .align-center { align-items: center; }
572
- .flex-1 { flex: 1; }
573
-
574
- .w-100 { width: 100%; }
575
- .h-100 { height: 100%; }
576
-
577
- .overflow-hidden { overflow: hidden; }
578
- .overflow-auto { overflow: auto; }
579
- .overflow-scroll { overflow: scroll; }
580
-
581
- .position-relative { position: relative; }
582
- .position-absolute { position: absolute; }
583
- .position-fixed { position: fixed; }
584
-
585
- // 响应式工具类
586
- @media (max-width: 640px) {
587
- .d-sm-none { display: none; }
588
- .d-sm-block { display: block; }
589
- .d-sm-flex { display: flex; }
590
- }
591
-
592
- @media (max-width: 768px) {
593
- .d-md-none { display: none; }
594
- .d-md-block { display: block; }
595
- .d-md-flex { display: flex; }
596
- }
597
-
598
- @media (max-width: 1024px) {
599
- .d-lg-none { display: none; }
600
- .d-lg-block { display: block; }
601
- .d-lg-flex { display: flex; }
1
+ // 数据库平台公共样式
2
+
3
+ // 颜色变量
4
+ :root {
5
+ --primary-color: #667eea;
6
+ --primary-dark: #5a67d8;
7
+ --secondary-color: #764ba2;
8
+ --success-color: #10b981;
9
+ --warning-color: #f59e0b;
10
+ --error-color: #ef4444;
11
+ --info-color: #3b82f6;
12
+
13
+ --text-primary: #1e293b;
14
+ --text-secondary: #64748b;
15
+ --text-muted: #94a3b8;
16
+
17
+ --bg-primary: #ffffff;
18
+ --bg-secondary: #f8fafc;
19
+ --bg-tertiary: #f1f5f9;
20
+
21
+ --border-color: #e5e7eb;
22
+ --border-hover: #d1d5db;
23
+ --border-focus: #667eea;
24
+
25
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
26
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
27
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
28
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
29
+
30
+ --radius-sm: 4px;
31
+ --radius-md: 8px;
32
+ --radius-lg: 12px;
33
+ --radius-xl: 16px;
34
+ }
35
+
36
+ // 通用渐变背景
37
+ .gradient-primary {
38
+ background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
39
+ }
40
+
41
+ .gradient-secondary {
42
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%);
43
+ }
44
+
45
+ .gradient-success {
46
+ background: linear-gradient(135deg, var(--success-color) 0%, #059669 100%);
47
+ }
48
+
49
+ .gradient-warning {
50
+ background: linear-gradient(135deg, var(--warning-color) 0%, #d97706 100%);
51
+ }
52
+
53
+ .gradient-error {
54
+ background: linear-gradient(135deg, var(--error-color) 0%, #dc2626 100%);
55
+ }
56
+
57
+ .gradient-info {
58
+ background: linear-gradient(135deg, var(--info-color) 0%, #2563eb 100%);
59
+ }
60
+
61
+ // 通用按钮样式
62
+ .btn {
63
+ display: inline-flex;
64
+ align-items: center;
65
+ justify-content: center;
66
+ gap: 0.5rem;
67
+ padding: 0.75rem 1.5rem;
68
+ border: 1px solid var(--border-color);
69
+ border-radius: var(--radius-md);
70
+ font-size: 0.875rem;
71
+ font-weight: 500;
72
+ cursor: pointer;
73
+ transition: all 0.2s ease;
74
+ text-decoration: none;
75
+ outline: none;
76
+ user-select: none;
77
+
78
+ &:hover:not(:disabled) {
79
+ transform: translateY(-1px);
80
+ box-shadow: var(--shadow-md);
81
+ }
82
+
83
+ &:active {
84
+ transform: translateY(0);
85
+ }
86
+
87
+ &:disabled {
88
+ opacity: 0.5;
89
+ cursor: not-allowed;
90
+ }
91
+
92
+ &.btn-primary {
93
+ @extend .gradient-primary;
94
+ color: white;
95
+ border: none;
96
+
97
+ &:hover:not(:disabled) {
98
+ background: linear-gradient(135deg, var(--primary-dark) 0%, var(--secondary-color) 100%);
99
+ }
100
+ }
101
+
102
+ &.btn-success {
103
+ @extend .gradient-success;
104
+ color: white;
105
+ border: none;
106
+ }
107
+
108
+ &.btn-warning {
109
+ @extend .gradient-warning;
110
+ color: white;
111
+ border: none;
112
+ }
113
+
114
+ &.btn-danger {
115
+ @extend .gradient-error;
116
+ color: white;
117
+ border: none;
118
+ }
119
+
120
+ &.btn-info {
121
+ @extend .gradient-info;
122
+ color: white;
123
+ border: none;
124
+ }
125
+
126
+ &.btn-outline {
127
+ background: transparent;
128
+ color: var(--primary-color);
129
+ border-color: var(--primary-color);
130
+
131
+ &:hover:not(:disabled) {
132
+ background: var(--primary-color);
133
+ color: white;
134
+ }
135
+ }
136
+
137
+ &.btn-ghost {
138
+ background: transparent;
139
+ color: var(--text-secondary);
140
+
141
+ &:hover:not(:disabled) {
142
+ background: var(--bg-secondary);
143
+ color: var(--text-primary);
144
+ }
145
+ }
146
+
147
+ &.btn-sm {
148
+ padding: 0.5rem 1rem;
149
+ font-size: 0.75rem;
150
+ }
151
+
152
+ &.btn-lg {
153
+ padding: 1rem 2rem;
154
+ font-size: 1rem;
155
+ }
156
+ }
157
+
158
+ // 通用卡片样式
159
+ .card {
160
+ background: var(--bg-primary);
161
+ border: 1px solid var(--border-color);
162
+ border-radius: var(--radius-lg);
163
+ box-shadow: var(--shadow-sm);
164
+ overflow: hidden;
165
+ transition: all 0.2s ease;
166
+
167
+ &:hover {
168
+ box-shadow: var(--shadow-md);
169
+ transform: translateY(-2px);
170
+ }
171
+
172
+ &.card-flat {
173
+ box-shadow: none;
174
+
175
+ &:hover {
176
+ box-shadow: var(--shadow-sm);
177
+ transform: none;
178
+ }
179
+ }
180
+
181
+ .card-header {
182
+ padding: 1rem 1.5rem;
183
+ border-bottom: 1px solid var(--border-color);
184
+ background: var(--bg-secondary);
185
+
186
+ .card-title {
187
+ font-size: 1.125rem;
188
+ font-weight: 600;
189
+ color: var(--text-primary);
190
+ margin: 0;
191
+ }
192
+ }
193
+
194
+ .card-body {
195
+ padding: 1.5rem;
196
+ }
197
+
198
+ .card-footer {
199
+ padding: 1rem 1.5rem;
200
+ border-top: 1px solid var(--border-color);
201
+ background: var(--bg-secondary);
202
+ }
203
+ }
204
+
205
+ // 通用表单样式
206
+ .form-group {
207
+ margin-bottom: 1rem;
208
+
209
+ label {
210
+ display: block;
211
+ margin-bottom: 0.5rem;
212
+ font-weight: 500;
213
+ color: var(--text-primary);
214
+ font-size: 0.875rem;
215
+ }
216
+ }
217
+
218
+ .form-input,
219
+ .form-textarea,
220
+ .form-select {
221
+ width: 100%;
222
+ padding: 0.75rem;
223
+ border: 1px solid var(--border-color);
224
+ border-radius: var(--radius-md);
225
+ font-size: 0.875rem;
226
+ transition: all 0.2s ease;
227
+ background: var(--bg-primary);
228
+
229
+ &:focus {
230
+ outline: none;
231
+ border-color: var(--border-focus);
232
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
233
+ }
234
+
235
+ &.is-invalid {
236
+ border-color: var(--error-color);
237
+
238
+ &:focus {
239
+ box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1);
240
+ }
241
+ }
242
+ }
243
+
244
+ .form-textarea {
245
+ resize: vertical;
246
+ min-height: 100px;
247
+ }
248
+
249
+ // 通用表格样式
250
+ .table {
251
+ width: 100%;
252
+ border-collapse: collapse;
253
+ font-size: 0.875rem;
254
+
255
+ th {
256
+ background: var(--bg-secondary);
257
+ padding: 0.75rem;
258
+ text-align: left;
259
+ font-weight: 600;
260
+ color: var(--text-primary);
261
+ border-bottom: 2px solid var(--border-color);
262
+
263
+ &.sortable {
264
+ cursor: pointer;
265
+ user-select: none;
266
+
267
+ &:hover {
268
+ background: var(--bg-tertiary);
269
+ }
270
+ }
271
+ }
272
+
273
+ td {
274
+ padding: 0.75rem;
275
+ border-bottom: 1px solid var(--border-color);
276
+ max-width: 200px;
277
+ overflow: hidden;
278
+ text-overflow: ellipsis;
279
+ white-space: nowrap;
280
+ }
281
+
282
+ tr:hover {
283
+ background: var(--bg-secondary);
284
+ }
285
+
286
+ &.table-sm {
287
+ font-size: 0.75rem;
288
+
289
+ th,
290
+ td {
291
+ padding: 0.5rem;
292
+ }
293
+ }
294
+
295
+ &.table-hover {
296
+ tbody tr {
297
+ transition: background-color 0.2s ease;
298
+ }
299
+ }
300
+
301
+ &.table-striped {
302
+ tbody tr:nth-child(even) {
303
+ background: var(--bg-secondary);
304
+ }
305
+ }
306
+ }
307
+
308
+ // 通用徽章样式
309
+ .badge {
310
+ display: inline-flex;
311
+ align-items: center;
312
+ padding: 0.25rem 0.75rem;
313
+ border-radius: 20px;
314
+ font-size: 0.75rem;
315
+ font-weight: 600;
316
+ text-transform: uppercase;
317
+ letter-spacing: 0.05em;
318
+
319
+ &.badge-primary {
320
+ background: rgba(102, 126, 234, 0.1);
321
+ color: var(--primary-color);
322
+ }
323
+
324
+ &.badge-success {
325
+ background: rgba(16, 185, 129, 0.1);
326
+ color: var(--success-color);
327
+ }
328
+
329
+ &.badge-warning {
330
+ background: rgba(245, 158, 11, 0.1);
331
+ color: var(--warning-color);
332
+ }
333
+
334
+ &.badge-error {
335
+ background: rgba(239, 68, 68, 0.1);
336
+ color: var(--error-color);
337
+ }
338
+
339
+ &.badge-info {
340
+ background: rgba(59, 130, 246, 0.1);
341
+ color: var(--info-color);
342
+ }
343
+ }
344
+
345
+ // 通用状态指示器
346
+ .status-indicator {
347
+ display: inline-flex;
348
+ align-items: center;
349
+ gap: 0.5rem;
350
+ font-size: 0.875rem;
351
+
352
+ .status-dot {
353
+ width: 8px;
354
+ height: 8px;
355
+ border-radius: 50%;
356
+
357
+ &.online {
358
+ background: var(--success-color);
359
+ box-shadow: 0 0 8px rgba(16, 185, 129, 0.5);
360
+ }
361
+
362
+ &.offline {
363
+ background: var(--text-muted);
364
+ }
365
+
366
+ &.warning {
367
+ background: var(--warning-color);
368
+ box-shadow: 0 0 8px rgba(245, 158, 11, 0.5);
369
+ }
370
+
371
+ &.error {
372
+ background: var(--error-color);
373
+ box-shadow: 0 0 8px rgba(239, 68, 68, 0.5);
374
+ }
375
+ }
376
+ }
377
+
378
+ // 通用加载动画
379
+ .loading {
380
+ display: inline-flex;
381
+ align-items: center;
382
+ gap: 0.5rem;
383
+
384
+ .spinner {
385
+ width: 16px;
386
+ height: 16px;
387
+ border: 2px solid var(--border-color);
388
+ border-top-color: var(--primary-color);
389
+ border-radius: 50%;
390
+ animation: spin 1s linear infinite;
391
+ }
392
+ }
393
+
394
+ @keyframes spin {
395
+ from {
396
+ transform: rotate(0deg);
397
+ }
398
+ to {
399
+ transform: rotate(360deg);
400
+ }
401
+ }
402
+
403
+ // 通用模态框样式
404
+ .modal {
405
+ position: fixed;
406
+ top: 0;
407
+ left: 0;
408
+ right: 0;
409
+ bottom: 0;
410
+ background: rgba(0, 0, 0, 0.5);
411
+ display: flex;
412
+ justify-content: center;
413
+ align-items: center;
414
+ z-index: 1000;
415
+ backdrop-filter: blur(4px);
416
+
417
+ .modal-content {
418
+ background: var(--bg-primary);
419
+ border-radius: var(--radius-xl);
420
+ box-shadow: var(--shadow-xl);
421
+ max-width: 90vw;
422
+ max-height: 90vh;
423
+ overflow: hidden;
424
+ display: flex;
425
+ flex-direction: column;
426
+
427
+ .modal-header {
428
+ padding: 1.5rem;
429
+ border-bottom: 1px solid var(--border-color);
430
+ display: flex;
431
+ justify-content: space-between;
432
+ align-items: center;
433
+
434
+ .modal-title {
435
+ font-size: 1.25rem;
436
+ font-weight: 600;
437
+ color: var(--text-primary);
438
+ margin: 0;
439
+ }
440
+
441
+ .modal-close {
442
+ background: none;
443
+ border: none;
444
+ font-size: 1.5rem;
445
+ cursor: pointer;
446
+ color: var(--text-muted);
447
+ padding: 0.25rem;
448
+ border-radius: var(--radius-sm);
449
+ transition: all 0.2s ease;
450
+
451
+ &:hover {
452
+ background: var(--bg-secondary);
453
+ color: var(--text-primary);
454
+ }
455
+ }
456
+ }
457
+
458
+ .modal-body {
459
+ padding: 1.5rem;
460
+ flex: 1;
461
+ overflow-y: auto;
462
+ }
463
+
464
+ .modal-footer {
465
+ padding: 1.5rem;
466
+ border-top: 1px solid var(--border-color);
467
+ display: flex;
468
+ justify-content: flex-end;
469
+ gap: 0.5rem;
470
+ }
471
+ }
472
+ }
473
+
474
+ // 通用分页样式
475
+ .pagination {
476
+ display: flex;
477
+ justify-content: center;
478
+ align-items: center;
479
+ gap: 0.5rem;
480
+
481
+ .page-info {
482
+ padding: 0.5rem 1rem;
483
+ font-size: 0.875rem;
484
+ color: var(--text-secondary);
485
+ }
486
+
487
+ .page-btn {
488
+ padding: 0.5rem 0.75rem;
489
+ border: 1px solid var(--border-color);
490
+ border-radius: var(--radius-sm);
491
+ background: var(--bg-primary);
492
+ cursor: pointer;
493
+ transition: all 0.2s ease;
494
+
495
+ &:hover:not(:disabled) {
496
+ background: var(--primary-color);
497
+ color: white;
498
+ border-color: var(--primary-color);
499
+ }
500
+
501
+ &:disabled {
502
+ opacity: 0.5;
503
+ cursor: not-allowed;
504
+ }
505
+
506
+ &.active {
507
+ background: var(--primary-color);
508
+ color: white;
509
+ border-color: var(--primary-color);
510
+ }
511
+ }
512
+ }
513
+
514
+ // 通用工具类
515
+ .text-center { text-align: center; }
516
+ .text-left { text-align: left; }
517
+ .text-right { text-align: right; }
518
+
519
+ .text-primary { color: var(--text-primary); }
520
+ .text-secondary { color: var(--text-secondary); }
521
+ .text-muted { color: var(--text-muted); }
522
+ .text-success { color: var(--success-color); }
523
+ .text-warning { color: var(--warning-color); }
524
+ .text-error { color: var(--error-color); }
525
+ .text-info { color: var(--info-color); }
526
+
527
+ .bg-primary { background: var(--bg-primary); }
528
+ .bg-secondary { background: var(--bg-secondary); }
529
+ .bg-tertiary { background: var(--bg-tertiary); }
530
+
531
+ .border { border: 1px solid var(--border-color); }
532
+ .border-top { border-top: 1px solid var(--border-color); }
533
+ .border-bottom { border-bottom: 1px solid var(--border-color); }
534
+ .border-left { border-left: 1px solid var(--border-color); }
535
+ .border-right { border-right: 1px solid var(--border-color); }
536
+
537
+ .rounded { border-radius: var(--radius-md); }
538
+ .rounded-sm { border-radius: var(--radius-sm); }
539
+ .rounded-lg { border-radius: var(--radius-lg); }
540
+ .rounded-xl { border-radius: var(--radius-xl); }
541
+
542
+ .shadow-sm { box-shadow: var(--shadow-sm); }
543
+ .shadow-md { box-shadow: var(--shadow-md); }
544
+ .shadow-lg { box-shadow: var(--shadow-lg); }
545
+ .shadow-xl { box-shadow: var(--shadow-xl); }
546
+
547
+ .p-0 { padding: 0; }
548
+ .p-1 { padding: 0.25rem; }
549
+ .p-2 { padding: 0.5rem; }
550
+ .p-3 { padding: 0.75rem; }
551
+ .p-4 { padding: 1rem; }
552
+ .p-5 { padding: 1.5rem; }
553
+
554
+ .m-0 { margin: 0; }
555
+ .m-1 { margin: 0.25rem; }
556
+ .m-2 { margin: 0.5rem; }
557
+ .m-3 { margin: 0.75rem; }
558
+ .m-4 { margin: 1rem; }
559
+ .m-5 { margin: 1.5rem; }
560
+
561
+ .d-none { display: none; }
562
+ .d-block { display: block; }
563
+ .d-flex { display: flex; }
564
+ .d-inline { display: inline; }
565
+ .d-inline-block { display: inline-block; }
566
+
567
+ .flex-column { flex-direction: column; }
568
+ .flex-row { flex-direction: row; }
569
+ .justify-center { justify-content: center; }
570
+ .justify-between { justify-content: space-between; }
571
+ .align-center { align-items: center; }
572
+ .flex-1 { flex: 1; }
573
+
574
+ .w-100 { width: 100%; }
575
+ .h-100 { height: 100%; }
576
+
577
+ .overflow-hidden { overflow: hidden; }
578
+ .overflow-auto { overflow: auto; }
579
+ .overflow-scroll { overflow: scroll; }
580
+
581
+ .position-relative { position: relative; }
582
+ .position-absolute { position: absolute; }
583
+ .position-fixed { position: fixed; }
584
+
585
+ // 响应式工具类
586
+ @media (max-width: 640px) {
587
+ .d-sm-none { display: none; }
588
+ .d-sm-block { display: block; }
589
+ .d-sm-flex { display: flex; }
590
+ }
591
+
592
+ @media (max-width: 768px) {
593
+ .d-md-none { display: none; }
594
+ .d-md-block { display: block; }
595
+ .d-md-flex { display: flex; }
596
+ }
597
+
598
+ @media (max-width: 1024px) {
599
+ .d-lg-none { display: none; }
600
+ .d-lg-block { display: block; }
601
+ .d-lg-flex { display: flex; }
602
602
  }