zant-admin 2.0.2 → 2.0.4

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 (69) hide show
  1. package/.editorconfig +6 -0
  2. package/.env.development +3 -0
  3. package/.env.production +1 -0
  4. package/.env.test +1 -0
  5. package/.gitignore +36 -0
  6. package/.prettierrc.json +9 -0
  7. package/README.en.md +461 -272
  8. package/README.md +4 -3
  9. package/bin/cli.js +1 -1
  10. package/eslint.config.js +30 -0
  11. package/index.html +13 -0
  12. package/jsconfig.json +8 -0
  13. package/package.json +11 -3
  14. package/src/App.vue +16 -16
  15. package/src/api/methods/logError.js +8 -8
  16. package/src/api/methods/logOperation.js +8 -8
  17. package/src/api/methods/login.js +6 -6
  18. package/src/api/methods/quartz.js +36 -36
  19. package/src/api/methods/region.js +16 -16
  20. package/src/api/methods/sysAccount.js +29 -29
  21. package/src/api/methods/sysDict.js +29 -29
  22. package/src/api/methods/sysDictItem.js +26 -26
  23. package/src/api/methods/sysMenu.js +42 -42
  24. package/src/api/methods/sysRole.js +35 -35
  25. package/src/api/methods/sysUser.js +25 -25
  26. package/src/api/methods/system.js +15 -15
  27. package/src/api/request.js +225 -225
  28. package/src/assets/css/zcui.css +1023 -1023
  29. package/src/components/IconPicker.vue +351 -351
  30. package/src/components/MainPage.vue +838 -838
  31. package/src/components/details/logErrorDetails.vue +58 -58
  32. package/src/components/details/logOperationDetails.vue +76 -76
  33. package/src/components/edit/QuartzEdit.vue +221 -221
  34. package/src/components/edit/SysAccountEdit.vue +185 -185
  35. package/src/components/edit/SysDictEdit.vue +116 -116
  36. package/src/components/edit/SysDictItemEdit.vue +136 -136
  37. package/src/components/edit/SysRoleEdit.vue +111 -111
  38. package/src/config/index.js +74 -74
  39. package/src/directives/permission.js +49 -49
  40. package/src/main.js +37 -37
  41. package/src/stores/config.js +43 -43
  42. package/src/stores/dict.js +33 -33
  43. package/src/stores/menu.js +81 -81
  44. package/src/stores/user.js +21 -21
  45. package/src/utils/baseEcharts.js +661 -661
  46. package/src/utils/dictTemplate.js +26 -26
  47. package/src/utils/regionUtils.js +173 -173
  48. package/src/utils/useFormCRUD.js +59 -59
  49. package/src/views/baiscstatis/center.vue +474 -474
  50. package/src/views/baiscstatis/iframePage.vue +29 -29
  51. package/src/views/baiscstatis/notFound.vue +192 -192
  52. package/src/views/console.vue +821 -821
  53. package/src/views/demo/button.vue +269 -269
  54. package/src/views/demo/importexport.vue +119 -119
  55. package/src/views/demo/region.vue +322 -322
  56. package/src/views/demo/statistics.vue +214 -214
  57. package/src/views/home.vue +6 -6
  58. package/src/views/operations/log/logError.vue +78 -78
  59. package/src/views/operations/log/logLogin.vue +66 -66
  60. package/src/views/operations/log/logOperation.vue +103 -103
  61. package/src/views/operations/log/logQuartz.vue +56 -56
  62. package/src/views/operations/quartz.vue +179 -179
  63. package/src/views/operations/serviceMonitoring.vue +134 -134
  64. package/src/views/system/sysAccount.vue +128 -128
  65. package/src/views/system/sysDict.vue +159 -159
  66. package/src/views/system/sysDictItem.vue +118 -118
  67. package/src/views/system/sysMenu.vue +225 -225
  68. package/src/views/system/sysRole.vue +207 -207
  69. package/vite.config.js +33 -0
@@ -1,322 +1,322 @@
1
- <template>
2
- <div class="region-container" >
3
- <!-- 数据来源说明 -->
4
- <a-card title="数据来源" class="margin-bottom-10">
5
- <div class="data-source-content">
6
- <a-alert
7
- message="数据来源:中华人民共和国国家统计局"
8
- description="本页面提供的省市区数据来源于中华人民共和国国家统计局发布的2023年统计用区划代码和城乡划分代码,确保数据的准确性和权威性。"
9
- type="info"
10
- show-icon
11
- :closable="false"
12
- />
13
- <!-- <div class="source-details">
14
- <div class="source-item">
15
- <strong>发布机构:</strong>中华人民共和国国家统计局
16
- </div>
17
- <div class="source-item">
18
- <strong>数据版本:</strong>2023年统计用区划代码和城乡划分代码
19
- </div>
20
- <div class="source-item">
21
- <strong>数据说明:</strong>全国省、市、区/县三级行政区划标准数据,支持省市区三级联动选择功能
22
- </div>
23
- </div> -->
24
- </div>
25
- </a-card>
26
-
27
- <a-card title="省市区联动选择" class="region-card">
28
- <div class="region-selector">
29
- <a-form layout="inline">
30
- <a-form-item label="省份">
31
- <a-select
32
- v-model:value="selectedProvince"
33
- placeholder="请选择省份"
34
- style="width: 150px"
35
- @change="handleProvinceChange"
36
- :options="provinceOptions"
37
- :filter-option="filterOption"
38
- show-search
39
- />
40
- </a-form-item>
41
- <a-form-item label="城市">
42
- <a-select
43
- v-model:value="selectedCity"
44
- placeholder="请选择城市"
45
- style="width: 150px"
46
- @change="handleCityChange"
47
- :options="cityOptions"
48
- :disabled="!selectedProvince"
49
- :filter-option="filterOption"
50
- show-search
51
- />
52
- </a-form-item>
53
- <a-form-item label="区县">
54
- <a-select
55
- v-model:value="selectedArea"
56
- placeholder="请选择区县"
57
- style="width: 150px"
58
- @change="handleAreaChange"
59
- :options="areaOptions"
60
- :disabled="!selectedCity"
61
- :filter-option="filterOption"
62
- show-search
63
- />
64
- </a-form-item>
65
- </a-form>
66
- <div class="selected-result" v-if="selectedAddress">
67
- <a-alert :message="selectedAddress" type="success" show-icon />
68
- <div
69
- class="code-display"
70
- v-if="selectedProvince || selectedCity || selectedArea"
71
- >
72
- <a-descriptions title="区域代码" :column="3" size="small">
73
- <a-descriptions-item label="省份代码">{{
74
- selectedProvince || '-'
75
- }}</a-descriptions-item>
76
- <a-descriptions-item label="城市代码">{{
77
- selectedCity || '-'
78
- }}</a-descriptions-item>
79
- <a-descriptions-item label="区县代码">{{
80
- selectedArea || '-'
81
- }}</a-descriptions-item>
82
- </a-descriptions>
83
- </div>
84
- </div>
85
- </div>
86
- </a-card>
87
-
88
- <a-card title="省市区组合选择" class="region-card">
89
- <div class="region-cascader">
90
- <a-form layout="inline">
91
- <a-form-item label="地区选择">
92
- <a-cascader
93
- v-model:value="cascaderValue"
94
- :options="cascaderOptions"
95
- placeholder="请选择地区"
96
- style="width: 300px"
97
- @change="handleCascaderChange"
98
- :filter-option="filterCascaderOption"
99
- show-search
100
- />
101
- </a-form-item>
102
- </a-form>
103
- <div class="cascader-result" v-if="cascaderAddress">
104
- <a-alert :message="cascaderAddress" type="info" show-icon />
105
- <div
106
- class="code-display"
107
- v-if="cascaderValue && cascaderValue.length > 0"
108
- >
109
- <a-descriptions title="区域代码" :column="3" size="small">
110
- <a-descriptions-item label="省份代码">{{
111
- cascaderValue[0] || '-'
112
- }}</a-descriptions-item>
113
- <a-descriptions-item label="城市代码">{{
114
- cascaderValue[1] || '-'
115
- }}</a-descriptions-item>
116
- <a-descriptions-item label="区县代码">{{
117
- cascaderValue[2] || '-'
118
- }}</a-descriptions-item>
119
- </a-descriptions>
120
- </div>
121
- </div>
122
- </div>
123
- </a-card>
124
-
125
-
126
- </div>
127
- </template>
128
-
129
- <script setup>
130
- import { ref, onMounted, computed } from 'vue'
131
- import regionUtils from '@/utils/regionUtils'
132
-
133
- // 省市区联动选择相关数据
134
- const selectedProvince = ref('')
135
- const selectedCity = ref('')
136
- const selectedArea = ref('')
137
- const provinceOptions = ref([])
138
- const cityOptions = ref([])
139
- const areaOptions = ref([])
140
-
141
- // 组合框相关数据
142
- const cascaderValue = ref([])
143
- const cascaderOptions = ref([])
144
-
145
- // 计算属性:获取选中的完整地址
146
- const selectedAddress = computed(() => {
147
- return regionUtils.getFullAddressName(
148
- selectedProvince.value,
149
- selectedCity.value,
150
- selectedArea.value,
151
- )
152
- })
153
-
154
- // 计算属性:获取组合框选中的完整地址
155
- const cascaderAddress = computed(() => {
156
- if (!cascaderValue.value || cascaderValue.value.length === 0) return ''
157
- const [provinceCode, cityCode, areaCode] = cascaderValue.value
158
- return regionUtils.getFullAddressName(provinceCode, cityCode, areaCode)
159
- })
160
-
161
- /**
162
- * 处理省份选择变化
163
- * @param {string} value - 选中的省份代码
164
- */
165
- const handleProvinceChange = value => {
166
- // 重置城市和区县选择
167
- selectedCity.value = ''
168
- selectedArea.value = ''
169
-
170
- // 获取该省份下的城市列表
171
- cityOptions.value = regionUtils.getCitiesByProvinceCode(value)
172
- areaOptions.value = []
173
- }
174
-
175
- /**
176
- * 处理城市选择变化
177
- * @param {string} value - 选中的城市代码
178
- */
179
- const handleCityChange = value => {
180
- // 重置区县选择
181
- selectedArea.value = ''
182
-
183
- // 获取该城市下的区县列表
184
- areaOptions.value = regionUtils.getAreasByCityCode(value)
185
- }
186
-
187
- /**
188
- * 处理区县选择变化
189
- * @param {string} value - 选中的区县代码
190
- */
191
- const handleAreaChange = value => {
192
- // 这里可以添加区县选择后的处理逻辑
193
- console.log('选中的区县代码:', value)
194
- }
195
-
196
- /**
197
- * 处理组合框选择变化
198
- * @param {Array} value - 选中的值数组 [省份代码, 城市代码, 区县代码]
199
- */
200
- const handleCascaderChange = value => {
201
- console.log('组合框选中的值:', value)
202
- }
203
-
204
- /**
205
- * 搜索过滤函数
206
- * @param {string} input - 输入的搜索关键词
207
- * @param {Object} option - 选项对象
208
- * @returns {boolean} 是否匹配
209
- */
210
- const filterOption = (input, option) => {
211
- return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
212
- }
213
-
214
- /**
215
- * 级联选择器搜索过滤函数
216
- * @param {string} inputValue - 输入的搜索关键词
217
- * @param {Object} pathNode - 路径节点
218
- * @returns {boolean} 是否匹配
219
- */
220
- const filterCascaderOption = (inputValue, pathNode) => {
221
- return pathNode.some(
222
- option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0,
223
- )
224
- }
225
-
226
- /**
227
- * 构建级联选择器的选项数据
228
- * @param {Array} provinces - 省份数据
229
- * @returns {Array} 级联选择器选项数据
230
- */
231
- const buildCascaderOptions = provinces => {
232
- return provinces.map(province => {
233
- // 获取省份下的所有城市
234
- const cities = regionUtils.getCitiesByProvinceCode(province.value)
235
-
236
- return {
237
- label: province.label,
238
- value: province.value,
239
- children: cities.map(city => {
240
- // 获取城市下的所有区县
241
- const areas = regionUtils.getAreasByCityCode(city.value)
242
-
243
- return {
244
- label: city.label,
245
- value: city.value,
246
- children: areas.length > 0 ? areas : undefined,
247
- }
248
- }),
249
- }
250
- })
251
- }
252
-
253
- // 组件挂载时初始化数据
254
- onMounted(async () => {
255
- try {
256
- // 获取所有省市区数据
257
- await regionUtils.fetchAllAddressData()
258
-
259
- // 设置省份数据
260
- provinceOptions.value = regionUtils.getAllProvinces()
261
-
262
- // 构建级联选择器数据
263
- cascaderOptions.value = buildCascaderOptions(provinceOptions.value)
264
- } catch (error) {
265
- console.error('初始化省市区数据失败:', error)
266
- }
267
- })
268
- </script>
269
-
270
- <style scoped>
271
- .region-card {
272
- margin-bottom: 20px;
273
- }
274
-
275
- .region-selector,
276
- .region-cascader {
277
- padding: 20px 0;
278
- }
279
-
280
- .selected-result,
281
- .cascader-result {
282
- margin-top: 20px;
283
- }
284
-
285
- .code-display {
286
- margin-top: 15px;
287
- padding: 10px;
288
- background-color: #f5f5f5;
289
- border-radius: 6px;
290
- }
291
-
292
- .data-source-card {
293
- margin-top: 20px;
294
- background-color: #fafafa;
295
- }
296
-
297
- .data-source-content {
298
- padding: 10px 0;
299
- }
300
-
301
- .source-details {
302
- margin-top: 15px;
303
- padding: 15px;
304
- background-color: #ffffff;
305
- border-radius: 6px;
306
- border: 1px solid #d9d9d9;
307
- }
308
-
309
- .source-item {
310
- margin-bottom: 8px;
311
- line-height: 1.5;
312
- }
313
-
314
- .source-item:last-child {
315
- margin-bottom: 0;
316
- }
317
-
318
- .source-item strong {
319
- color: #1890ff;
320
- font-weight: 600;
321
- }
322
- </style>
1
+ <template>
2
+ <div class="region-container" >
3
+ <!-- 数据来源说明 -->
4
+ <a-card title="数据来源" class="margin-bottom-10">
5
+ <div class="data-source-content">
6
+ <a-alert
7
+ message="数据来源:中华人民共和国国家统计局"
8
+ description="本页面提供的省市区数据来源于中华人民共和国国家统计局发布的2023年统计用区划代码和城乡划分代码,确保数据的准确性和权威性。"
9
+ type="info"
10
+ show-icon
11
+ :closable="false"
12
+ />
13
+ <!-- <div class="source-details">
14
+ <div class="source-item">
15
+ <strong>发布机构:</strong>中华人民共和国国家统计局
16
+ </div>
17
+ <div class="source-item">
18
+ <strong>数据版本:</strong>2023年统计用区划代码和城乡划分代码
19
+ </div>
20
+ <div class="source-item">
21
+ <strong>数据说明:</strong>全国省、市、区/县三级行政区划标准数据,支持省市区三级联动选择功能
22
+ </div>
23
+ </div> -->
24
+ </div>
25
+ </a-card>
26
+
27
+ <a-card title="省市区联动选择" class="region-card">
28
+ <div class="region-selector">
29
+ <a-form layout="inline">
30
+ <a-form-item label="省份">
31
+ <a-select
32
+ v-model:value="selectedProvince"
33
+ placeholder="请选择省份"
34
+ style="width: 150px"
35
+ @change="handleProvinceChange"
36
+ :options="provinceOptions"
37
+ :filter-option="filterOption"
38
+ show-search
39
+ />
40
+ </a-form-item>
41
+ <a-form-item label="城市">
42
+ <a-select
43
+ v-model:value="selectedCity"
44
+ placeholder="请选择城市"
45
+ style="width: 150px"
46
+ @change="handleCityChange"
47
+ :options="cityOptions"
48
+ :disabled="!selectedProvince"
49
+ :filter-option="filterOption"
50
+ show-search
51
+ />
52
+ </a-form-item>
53
+ <a-form-item label="区县">
54
+ <a-select
55
+ v-model:value="selectedArea"
56
+ placeholder="请选择区县"
57
+ style="width: 150px"
58
+ @change="handleAreaChange"
59
+ :options="areaOptions"
60
+ :disabled="!selectedCity"
61
+ :filter-option="filterOption"
62
+ show-search
63
+ />
64
+ </a-form-item>
65
+ </a-form>
66
+ <div class="selected-result" v-if="selectedAddress">
67
+ <a-alert :message="selectedAddress" type="success" show-icon />
68
+ <div
69
+ class="code-display"
70
+ v-if="selectedProvince || selectedCity || selectedArea"
71
+ >
72
+ <a-descriptions title="区域代码" :column="3" size="small">
73
+ <a-descriptions-item label="省份代码">{{
74
+ selectedProvince || '-'
75
+ }}</a-descriptions-item>
76
+ <a-descriptions-item label="城市代码">{{
77
+ selectedCity || '-'
78
+ }}</a-descriptions-item>
79
+ <a-descriptions-item label="区县代码">{{
80
+ selectedArea || '-'
81
+ }}</a-descriptions-item>
82
+ </a-descriptions>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </a-card>
87
+
88
+ <a-card title="省市区组合选择" class="region-card">
89
+ <div class="region-cascader">
90
+ <a-form layout="inline">
91
+ <a-form-item label="地区选择">
92
+ <a-cascader
93
+ v-model:value="cascaderValue"
94
+ :options="cascaderOptions"
95
+ placeholder="请选择地区"
96
+ style="width: 300px"
97
+ @change="handleCascaderChange"
98
+ :filter-option="filterCascaderOption"
99
+ show-search
100
+ />
101
+ </a-form-item>
102
+ </a-form>
103
+ <div class="cascader-result" v-if="cascaderAddress">
104
+ <a-alert :message="cascaderAddress" type="info" show-icon />
105
+ <div
106
+ class="code-display"
107
+ v-if="cascaderValue && cascaderValue.length > 0"
108
+ >
109
+ <a-descriptions title="区域代码" :column="3" size="small">
110
+ <a-descriptions-item label="省份代码">{{
111
+ cascaderValue[0] || '-'
112
+ }}</a-descriptions-item>
113
+ <a-descriptions-item label="城市代码">{{
114
+ cascaderValue[1] || '-'
115
+ }}</a-descriptions-item>
116
+ <a-descriptions-item label="区县代码">{{
117
+ cascaderValue[2] || '-'
118
+ }}</a-descriptions-item>
119
+ </a-descriptions>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </a-card>
124
+
125
+
126
+ </div>
127
+ </template>
128
+
129
+ <script setup>
130
+ import { ref, onMounted, computed } from 'vue'
131
+ import regionUtils from '@/utils/regionUtils'
132
+
133
+ // 省市区联动选择相关数据
134
+ const selectedProvince = ref('')
135
+ const selectedCity = ref('')
136
+ const selectedArea = ref('')
137
+ const provinceOptions = ref([])
138
+ const cityOptions = ref([])
139
+ const areaOptions = ref([])
140
+
141
+ // 组合框相关数据
142
+ const cascaderValue = ref([])
143
+ const cascaderOptions = ref([])
144
+
145
+ // 计算属性:获取选中的完整地址
146
+ const selectedAddress = computed(() => {
147
+ return regionUtils.getFullAddressName(
148
+ selectedProvince.value,
149
+ selectedCity.value,
150
+ selectedArea.value,
151
+ )
152
+ })
153
+
154
+ // 计算属性:获取组合框选中的完整地址
155
+ const cascaderAddress = computed(() => {
156
+ if (!cascaderValue.value || cascaderValue.value.length === 0) return ''
157
+ const [provinceCode, cityCode, areaCode] = cascaderValue.value
158
+ return regionUtils.getFullAddressName(provinceCode, cityCode, areaCode)
159
+ })
160
+
161
+ /**
162
+ * 处理省份选择变化
163
+ * @param {string} value - 选中的省份代码
164
+ */
165
+ const handleProvinceChange = value => {
166
+ // 重置城市和区县选择
167
+ selectedCity.value = ''
168
+ selectedArea.value = ''
169
+
170
+ // 获取该省份下的城市列表
171
+ cityOptions.value = regionUtils.getCitiesByProvinceCode(value)
172
+ areaOptions.value = []
173
+ }
174
+
175
+ /**
176
+ * 处理城市选择变化
177
+ * @param {string} value - 选中的城市代码
178
+ */
179
+ const handleCityChange = value => {
180
+ // 重置区县选择
181
+ selectedArea.value = ''
182
+
183
+ // 获取该城市下的区县列表
184
+ areaOptions.value = regionUtils.getAreasByCityCode(value)
185
+ }
186
+
187
+ /**
188
+ * 处理区县选择变化
189
+ * @param {string} value - 选中的区县代码
190
+ */
191
+ const handleAreaChange = value => {
192
+ // 这里可以添加区县选择后的处理逻辑
193
+ console.log('选中的区县代码:', value)
194
+ }
195
+
196
+ /**
197
+ * 处理组合框选择变化
198
+ * @param {Array} value - 选中的值数组 [省份代码, 城市代码, 区县代码]
199
+ */
200
+ const handleCascaderChange = value => {
201
+ console.log('组合框选中的值:', value)
202
+ }
203
+
204
+ /**
205
+ * 搜索过滤函数
206
+ * @param {string} input - 输入的搜索关键词
207
+ * @param {Object} option - 选项对象
208
+ * @returns {boolean} 是否匹配
209
+ */
210
+ const filterOption = (input, option) => {
211
+ return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
212
+ }
213
+
214
+ /**
215
+ * 级联选择器搜索过滤函数
216
+ * @param {string} inputValue - 输入的搜索关键词
217
+ * @param {Object} pathNode - 路径节点
218
+ * @returns {boolean} 是否匹配
219
+ */
220
+ const filterCascaderOption = (inputValue, pathNode) => {
221
+ return pathNode.some(
222
+ option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0,
223
+ )
224
+ }
225
+
226
+ /**
227
+ * 构建级联选择器的选项数据
228
+ * @param {Array} provinces - 省份数据
229
+ * @returns {Array} 级联选择器选项数据
230
+ */
231
+ const buildCascaderOptions = provinces => {
232
+ return provinces.map(province => {
233
+ // 获取省份下的所有城市
234
+ const cities = regionUtils.getCitiesByProvinceCode(province.value)
235
+
236
+ return {
237
+ label: province.label,
238
+ value: province.value,
239
+ children: cities.map(city => {
240
+ // 获取城市下的所有区县
241
+ const areas = regionUtils.getAreasByCityCode(city.value)
242
+
243
+ return {
244
+ label: city.label,
245
+ value: city.value,
246
+ children: areas.length > 0 ? areas : undefined,
247
+ }
248
+ }),
249
+ }
250
+ })
251
+ }
252
+
253
+ // 组件挂载时初始化数据
254
+ onMounted(async () => {
255
+ try {
256
+ // 获取所有省市区数据
257
+ await regionUtils.fetchAllAddressData()
258
+
259
+ // 设置省份数据
260
+ provinceOptions.value = regionUtils.getAllProvinces()
261
+
262
+ // 构建级联选择器数据
263
+ cascaderOptions.value = buildCascaderOptions(provinceOptions.value)
264
+ } catch (error) {
265
+ console.error('初始化省市区数据失败:', error)
266
+ }
267
+ })
268
+ </script>
269
+
270
+ <style scoped>
271
+ .region-card {
272
+ margin-bottom: 20px;
273
+ }
274
+
275
+ .region-selector,
276
+ .region-cascader {
277
+ padding: 20px 0;
278
+ }
279
+
280
+ .selected-result,
281
+ .cascader-result {
282
+ margin-top: 20px;
283
+ }
284
+
285
+ .code-display {
286
+ margin-top: 15px;
287
+ padding: 10px;
288
+ background-color: #f5f5f5;
289
+ border-radius: 6px;
290
+ }
291
+
292
+ .data-source-card {
293
+ margin-top: 20px;
294
+ background-color: #fafafa;
295
+ }
296
+
297
+ .data-source-content {
298
+ padding: 10px 0;
299
+ }
300
+
301
+ .source-details {
302
+ margin-top: 15px;
303
+ padding: 15px;
304
+ background-color: #ffffff;
305
+ border-radius: 6px;
306
+ border: 1px solid #d9d9d9;
307
+ }
308
+
309
+ .source-item {
310
+ margin-bottom: 8px;
311
+ line-height: 1.5;
312
+ }
313
+
314
+ .source-item:last-child {
315
+ margin-bottom: 0;
316
+ }
317
+
318
+ .source-item strong {
319
+ color: #1890ff;
320
+ font-weight: 600;
321
+ }
322
+ </style>