Explorar o código

系统管理ui迁移 系统监控

ys hai 2 semanas
pai
achega
0d94b16623
Modificáronse 36 ficheiros con 3926 adicións e 1975 borrados
  1. 62 48
      yushu-uivue3/src/components/Crontab/day.vue
  2. 39 31
      yushu-uivue3/src/components/Crontab/hour.vue
  3. 95 77
      yushu-uivue3/src/components/Crontab/index.vue
  4. 39 31
      yushu-uivue3/src/components/Crontab/min.vue
  5. 40 32
      yushu-uivue3/src/components/Crontab/month.vue
  6. 39 31
      yushu-uivue3/src/components/Crontab/second.vue
  7. 75 65
      yushu-uivue3/src/components/Crontab/week.vue
  8. 47 38
      yushu-uivue3/src/components/Crontab/year.vue
  9. 46 26
      yushu-uivue3/src/components/Pagination/index.vue
  10. 110 62
      yushu-uivue3/src/views/monitor/cache/index.vue
  11. 224 157
      yushu-uivue3/src/views/monitor/cache/list.vue
  12. 253 158
      yushu-uivue3/src/views/monitor/errorLog/index.vue
  13. 61 67
      yushu-uivue3/src/views/monitor/errorLog/test.vue
  14. 281 236
      yushu-uivue3/src/views/monitor/job/index.vue
  15. 212 109
      yushu-uivue3/src/views/monitor/logininfor/index.vue
  16. 72 43
      yushu-uivue3/src/views/monitor/online/index.vue
  17. 260 161
      yushu-uivue3/src/views/monitor/operlog/index.vue
  18. 328 169
      yushu-uivue3/src/views/monitor/server/index.vue
  19. 122 11
      yushu-uivue3/src/views/system/dept/index.vue
  20. 115 19
      yushu-uivue3/src/views/system/dict/data.vue
  21. 116 21
      yushu-uivue3/src/views/system/dict/index.vue
  22. 27 1
      yushu-uivue3/src/views/system/icon/index.vue
  23. 9 24
      yushu-uivue3/src/views/system/mail/inbox/index.vue
  24. 119 24
      yushu-uivue3/src/views/system/mail/log/index.vue
  25. 120 11
      yushu-uivue3/src/views/system/menu/index.vue
  26. 119 25
      yushu-uivue3/src/views/system/message/index.vue
  27. 109 13
      yushu-uivue3/src/views/system/notice/index.vue
  28. 121 25
      yushu-uivue3/src/views/system/notification/index.vue
  29. 117 21
      yushu-uivue3/src/views/system/param/index.vue
  30. 112 16
      yushu-uivue3/src/views/system/post/index.vue
  31. 113 18
      yushu-uivue3/src/views/system/role/index.vue
  32. 50 36
      yushu-uivue3/src/views/system/user/index.vue
  33. 19 15
      yushu-uivue3/src/views/tool/build/index.vue
  34. 5 5
      yushu-uivue3/src/views/tool/gen/createTable.vue
  35. 70 35
      yushu-uivue3/src/views/tool/gen/importTable.vue
  36. 180 114
      yushu-uivue3/src/views/tool/gen/index.vue

+ 62 - 48
yushu-uivue3/src/components/Crontab/day.vue

@@ -1,55 +1,69 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                日,允许的通配符[, - * ? / L W]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    日,允许的通配符[, - * ? / L W]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                不指定
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    不指定
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                周期从
-                <el-input-number v-model='cycle01' :min="1" :max="30" /> -
-                <el-input-number v-model='cycle02' :min="cycle01 + 1" :max="31" /> 日
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min="1" :max="30" style="margin: 0 0.2rem" /> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 + 1" :max="31" style="margin: 0 0.2rem" /> 日
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                从
-                <el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
-                <el-input-number v-model='average02' :min="1" :max="31 - average01" /> 日执行一次
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    从
+                    <a-input-number v-model:value='average01' :min="1" :max="30" style="margin: 0 0.2rem" /> 号开始,每
+                    <a-input-number v-model:value='average02' :min="1" :max="31 - average01" style="margin: 0 0.2rem" /> 日执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="5">
-                每月
-                <el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="5">
+                    每月
+                    <a-input-number v-model:value='workday' :min="1" :max="31" style="margin: 0 0.2rem" /> 号最近的那个工作日
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="6">
-                本月最后一天
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="6">
+                    本月最后一天
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="7">
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-                    <el-option v-for="item in 31" :key="item" :label="item" :value="item" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="7">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="10" style="width: 18.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in 31" :key="item" :value="item">{{ item }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 <script setup>
 const emit = defineEmits(['update'])
@@ -165,10 +179,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 18.8rem;
 }
-</style>
+</style>

+ 39 - 31
yushu-uivue3/src/components/Crontab/hour.vue

@@ -1,36 +1,44 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                小时,允许的通配符[, - * /]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    小时,允许的通配符[, - * /]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                周期从
-                <el-input-number v-model='cycle01' :min="0" :max="22" /> -
-                <el-input-number v-model='cycle02' :min="cycle01 + 1" :max="23" /> 时
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min="0" :max="22" style="margin: 0 0.2rem" /> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 + 1" :max="23" style="margin: 0 0.2rem" /> 时
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                从
-                <el-input-number v-model='average01' :min="0" :max="22" /> 时开始,每
-                <el-input-number v-model='average02' :min="1" :max="23 - average01" /> 小时执行一次
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    从
+                    <a-input-number v-model:value='average01' :min="0" :max="22" style="margin: 0 0.2rem" /> 时开始,每
+                    <a-input-number v-model:value='average02' :min="1" :max="23 - average01" style="margin: 0 0.2rem" /> 小时执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-                    <el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="10" style="width: 18.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in 24" :key="item" :value="item - 1">{{ item - 1 }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 
 <script setup>
@@ -124,10 +132,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 18.8rem;
 }
 </style>

+ 95 - 77
yushu-uivue3/src/components/Crontab/index.vue

@@ -1,69 +1,71 @@
 <template>
     <div>
-        <el-tabs type="border-card">
-            <el-tab-pane label="秒" v-if="shouldHide('second')">
-                <CrontabSecond
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronsecond"
-                />
-            </el-tab-pane>
+        <a-card>
+            <a-tabs>
+                <a-tab-pane key="second" tab="秒" v-if="shouldHide('second')">
+                    <CrontabSecond
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronsecond"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="分钟" v-if="shouldHide('min')">
-                <CrontabMin
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronmin"
-                />
-            </el-tab-pane>
+                <a-tab-pane key="min" tab="分钟" v-if="shouldHide('min')">
+                    <CrontabMin
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronmin"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="小时" v-if="shouldHide('hour')">
-                <CrontabHour
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronhour"
-                />
-            </el-tab-pane>
+                <a-tab-pane key="hour" tab="小时" v-if="shouldHide('hour')">
+                    <CrontabHour
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronhour"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="日" v-if="shouldHide('day')">
-                <CrontabDay
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronday"
-                />
-            </el-tab-pane>
+                <a-tab-pane key="day" tab="日" v-if="shouldHide('day')">
+                    <CrontabDay
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronday"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="月" v-if="shouldHide('month')">
-                <CrontabMonth
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronmonth"
-                />
-            </el-tab-pane>
+                <a-tab-pane key="month" tab="月" v-if="shouldHide('month')">
+                    <CrontabMonth
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronmonth"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="周" v-if="shouldHide('week')">
-                <CrontabWeek
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronweek"
-                />
-            </el-tab-pane>
+                <a-tab-pane key="week" tab="周" v-if="shouldHide('week')">
+                    <CrontabWeek
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronweek"
+                    />
+                </a-tab-pane>
 
-            <el-tab-pane label="年" v-if="shouldHide('year')">
-                <CrontabYear
-                    @update="updateCrontabValue"
-                    :check="checkNumber"
-                    :cron="crontabValueObj"
-                    ref="cronyear"
-                />
-            </el-tab-pane>
-        </el-tabs>
+                <a-tab-pane key="year" tab="年" v-if="shouldHide('year')">
+                    <CrontabYear
+                        @update="updateCrontabValue"
+                        :check="checkNumber"
+                        :cron="crontabValueObj"
+                        ref="cronyear"
+                    />
+                </a-tab-pane>
+            </a-tabs>
+        </a-card>
 
         <div class="popup-main">
             <div class="popup-result">
@@ -78,36 +80,52 @@
                     <tbody>
                         <tr>
                             <td>
-                                <span v-if="crontabValueObj.second.length < 10">{{crontabValueObj.second}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.second" placement="top"><span>{{crontabValueObj.second}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.second.length >= 10" :title="crontabValueObj.second" placement="top">
+                                    <span>{{crontabValueObj.second}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.second}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.min.length < 10">{{crontabValueObj.min}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.min" placement="top"><span>{{crontabValueObj.min}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.min.length >= 10" :title="crontabValueObj.min" placement="top">
+                                    <span>{{crontabValueObj.min}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.min}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.hour.length < 10">{{crontabValueObj.hour}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.hour" placement="top"><span>{{crontabValueObj.hour}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.hour.length >= 10" :title="crontabValueObj.hour" placement="top">
+                                    <span>{{crontabValueObj.hour}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.hour}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.day.length < 10">{{crontabValueObj.day}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.day" placement="top"><span>{{crontabValueObj.day}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.day.length >= 10" :title="crontabValueObj.day" placement="top">
+                                    <span>{{crontabValueObj.day}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.day}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.month.length < 10">{{crontabValueObj.month}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.month" placement="top"><span>{{crontabValueObj.month}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.month.length >= 10" :title="crontabValueObj.month" placement="top">
+                                    <span>{{crontabValueObj.month}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.month}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.week.length < 10">{{crontabValueObj.week}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.week" placement="top"><span>{{crontabValueObj.week}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.week.length >= 10" :title="crontabValueObj.week" placement="top">
+                                    <span>{{crontabValueObj.week}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.week}}</span>
                             </td>
                             <td>
-                                <span v-if="crontabValueObj.year.length < 10">{{crontabValueObj.year}}</span>
-                                <el-tooltip v-else :content="crontabValueObj.year" placement="top"><span>{{crontabValueObj.year}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueObj.year.length >= 10" :title="crontabValueObj.year" placement="top">
+                                    <span>{{crontabValueObj.year}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueObj.year}}</span>
                             </td>
                             <td class="result">
-                                <span v-if="crontabValueString.length < 90">{{crontabValueString}}</span>
-                                <el-tooltip v-else :content="crontabValueString" placement="top"><span>{{crontabValueString}}</span></el-tooltip>
+                                <a-tooltip v-if="crontabValueString.length >= 90" :title="crontabValueString" placement="top">
+                                    <span>{{crontabValueString}}</span>
+                                </a-tooltip>
+                                <span v-else>{{crontabValueString}}</span>
                             </td>
                         </tr>
                     </tbody>
@@ -116,9 +134,9 @@
             <CrontabResult :ex="crontabValueString"></CrontabResult>
 
             <div class="pop_btn">
-                <el-button type="primary" @click="submitFill">确定</el-button>
-                <el-button type="warning" @click="clearCron">重置</el-button>
-                <el-button @click="hidePopup">取消</el-button>
+                <a-button type="primary" @click="submitFill">确定</a-button>
+                <a-button @click="clearCron" style="margin-left: 8px">重置</a-button>
+                <a-button @click="hidePopup" style="margin-left: 8px">取消</a-button>
             </div>
         </div>
     </div>

+ 39 - 31
yushu-uivue3/src/components/Crontab/min.vue

@@ -1,36 +1,44 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                分钟,允许的通配符[, - * /]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    分钟,允许的通配符[, - * /]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                周期从
-                <el-input-number v-model='cycle01' :min="0" :max="58" /> -
-                <el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 分钟
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min="0" :max="58" style="margin: 0 0.2rem" /> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 + 1" :max="59" style="margin: 0 0.2rem" /> 分钟
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                从
-                <el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始, 每
-                <el-input-number v-model='average02' :min="1" :max="59 - average01" /> 分钟执行一次
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    从
+                    <a-input-number v-model:value='average01' :min="0" :max="58" style="margin: 0 0.2rem" /> 分钟开始, 每
+                    <a-input-number v-model:value='average02' :min="1" :max="59 - average01" style="margin: 0 0.2rem" /> 分钟执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-                    <el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="10" style="width: 19.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in 60" :key="item" :value="item - 1">{{ item - 1 }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 <script setup>
 const emit = defineEmits(['update'])
@@ -117,10 +125,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 19.8rem;
 }
 </style>

+ 40 - 32
yushu-uivue3/src/components/Crontab/month.vue

@@ -1,36 +1,44 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                月,允许的通配符[, - * /]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    月,允许的通配符[, - * /]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                周期从
-                <el-input-number v-model='cycle01' :min="1" :max="11" /> -
-                <el-input-number v-model='cycle02' :min="cycle01 + 1" :max="12" /> 月
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min="1" :max="11" style="margin: 0 0.2rem" /> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 + 1" :max="12" style="margin: 0 0.2rem" /> 月
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                从
-                <el-input-number v-model='average01' :min="1" :max="11" /> 月开始,每
-                <el-input-number v-model='average02' :min="1" :max="12 - average01" /> 月月执行一次
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    从
+                    <a-input-number v-model:value='average01' :min="1" :max="11" style="margin: 0 0.2rem" /> 月开始,每
+                    <a-input-number v-model:value='average02' :min="1" :max="12 - average01" style="margin: 0 0.2rem" /> 月月执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
-                    <el-option v-for="item in monthList" :key="item.key" :label="item.value" :value="item.key" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="8" style="width: 18.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in monthList" :key="item.key" :value="item.key">{{ item.value }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 
 <script setup>
@@ -132,10 +140,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 18.8rem;
 }
-</style>
+</style>

+ 39 - 31
yushu-uivue3/src/components/Crontab/second.vue

@@ -1,36 +1,44 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                秒,允许的通配符[, - * /]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    秒,允许的通配符[, - * /]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                周期从
-                <el-input-number v-model='cycle01' :min="0" :max="58" /> -
-                <el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 秒
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min="0" :max="58" style="margin: 0 0.2rem" /> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 + 1" :max="59" style="margin: 0 0.2rem" /> 秒
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                从
-                <el-input-number v-model='average01' :min="0" :max="58" /> 秒开始,每
-                <el-input-number v-model='average02' :min="1" :max="59 - average01" /> 秒执行一次
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    从
+                    <a-input-number v-model:value='average01' :min="0" :max="58" style="margin: 0 0.2rem" /> 秒开始,每
+                    <a-input-number v-model:value='average02' :min="1" :max="59 - average01" style="margin: 0 0.2rem" /> 秒执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-                    <el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="10" style="width: 18.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in 60" :key="item" :value="item - 1">{{ item - 1 }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 
 <script setup>
@@ -119,10 +127,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 18.8rem;
 }
 </style>

+ 75 - 65
yushu-uivue3/src/components/Crontab/week.vue

@@ -1,71 +1,81 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="1">
-                周,允许的通配符[, - * ? / L #]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    周,允许的通配符[, - * ? / L #]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="2">
-                不指定
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    不指定
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="3">
-                周期从
-                <el-select clearable v-model="cycle01">
-                    <el-option
-                        v-for="(item,index) of weekList"
-                        :key="index"
-                        :label="item.value"
-                        :value="item.key"
-                        :disabled="item.key === 7"
-                    >{{item.value}}</el-option>
-                </el-select>
-                -
-                <el-select clearable v-model="cycle02">
-                    <el-option
-                        v-for="(item,index) of weekList"
-                        :key="index"
-                        :label="item.value"
-                        :value="item.key"
-                        :disabled="item.key <= cycle01"
-                    >{{item.value}}</el-option>
-                </el-select>
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    周期从
+                    <a-select v-model:value="cycle01" style="width: 8rem; margin: 0 0.5rem">
+                        <a-select-option
+                            v-for="(item,index) of weekList"
+                            :key="index"
+                            :value="item.key"
+                            :disabled="item.key === 7"
+                        >{{item.value}}</a-select-option>
+                    </a-select>
+                    -
+                    <a-select v-model:value="cycle02" style="width: 8rem; margin: 0 0.5rem">
+                        <a-select-option
+                            v-for="(item,index) of weekList"
+                            :key="index"
+                            :value="item.key"
+                            :disabled="item.key <= cycle01"
+                        >{{item.value}}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="4">
-                第
-                <el-input-number v-model='average01' :min="1" :max="4" /> 周的
-                <el-select clearable v-model="average02">
-                    <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    第
+                    <a-input-number v-model:value='average01' :min="1" :max="4" style="margin: 0 0.5rem" /> 周的
+                    <a-select v-model:value="average02" style="width: 8rem; margin: 0 0.5rem">
+                        <a-select-option v-for="item in weekList" :key="item.key" :value="item.key">{{ item.value }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="5">
-                本月最后一个
-                <el-select clearable v-model="weekday">
-                    <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="5">
+                    本月最后一个
+                    <a-select v-model:value="weekday" style="width: 8rem; margin: 0 0.5rem">
+                        <a-select-option v-for="item in weekList" :key="item.key" :value="item.key">{{ item.value }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio v-model='radioValue' :value="6">
-                指定
-                <el-select class="multiselect" clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="6">
-                    <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="6">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="6" class="multiselect" style="width: 17.8rem; margin: 0 0.5rem">
+                        <a-select-option v-for="item in weekList" :key="item.key" :value="item.key">{{ item.value }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-    </el-form>
+    </a-form>
 </template>
 
 <script setup>
@@ -185,13 +195,13 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.5rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 8rem;
 }
-.el-select.multiselect, .el-select--small.multiselect {
+.ant-select.multiselect {
     width: 17.8rem;
 }
-</style>
+</style>

+ 47 - 38
yushu-uivue3/src/components/Crontab/year.vue

@@ -1,43 +1,52 @@
 <template>
-    <el-form>
-        <el-form-item>
-            <el-radio :value="1" v-model='radioValue'>
-                不填,允许的通配符[, - * /]
-            </el-radio>
-        </el-form-item>
+    <a-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="1">
+                    不填,允许的通配符[, - * /]
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio :value="2" v-model='radioValue'>
-                每年
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="2">
+                    每年
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio :value="3" v-model='radioValue'>
-                周期从
-                <el-input-number v-model='cycle01' :min='fullYear' :max="2098"/> -
-                <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099"/>
-            </el-radio>
-        </el-form-item>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="3">
+                    周期从
+                    <a-input-number v-model:value='cycle01' :min='fullYear' :max="2098" style="margin: 0 0.2rem"/> -
+                    <a-input-number v-model:value='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" style="margin: 0 0.2rem"/>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        <el-form-item>
-            <el-radio :value="4" v-model='radioValue'>
-                从
-                <el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始,每
-                <el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear"/> 年执行一次
-            </el-radio>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="4">
+                    从
+                    <a-input-number v-model:value='average01' :min='fullYear' :max="2098" style="margin: 0 0.2rem"/> 年开始,每
+                    <a-input-number v-model:value='average02' :min="1" :max="2099 - average01 || fullYear" style="margin: 0 0.2rem"/> 年执行一次
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
 
-        </el-form-item>
-
-        <el-form-item>
-            <el-radio :value="5" v-model='radioValue'>
-                指定
-                <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
-                    <el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
-                </el-select>
-            </el-radio>
-        </el-form-item>
-    </el-form>
+        <a-form-item>
+            <a-radio-group v-model:value='radioValue'>
+                <a-radio :value="5">
+                    指定
+                    <a-select v-model:value="checkboxList" placeholder="可多选" mode="multiple" :maxTagCount="8" style="width: 18.8rem; margin: 0 0.2rem">
+                        <a-select-option v-for="item in 9" :key="item" :value="item - 1 + fullYear">{{ item -1 + fullYear }}</a-select-option>
+                    </a-select>
+                </a-radio>
+            </a-radio-group>
+        </a-form-item>
+    </a-form>
 </template>
 
 <script setup>
@@ -134,10 +143,10 @@ function onRadioChange() {
 </script>
 
 <style lang="scss" scoped>
-.el-input-number--small, .el-select, .el-select--small {
+.ant-input-number, .ant-select {
     margin: 0 0.2rem;
 }
-.el-select, .el-select--small {
+.ant-select {
     width: 18.8rem;
 }
-</style>
+</style>

+ 46 - 26
yushu-uivue3/src/components/Pagination/index.vue

@@ -1,15 +1,15 @@
 <template>
   <div :class="{ 'hidden': hidden }" class="pagination-container">
-    <el-pagination
-      :background="background"
-      v-model:current-page="currentPage"
+    <a-pagination
+      v-model:current="currentPage"
       v-model:page-size="pageSize"
-      :layout="layout"
-      :page-sizes="pageSizes"
-      :pager-count="pagerCount"
       :total="total"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
+      :page-size-options="pageSizeOptions"
+      :show-size-changer="showSizeChanger"
+      :show-quick-jumper="showQuickJumper"
+      :show-total="showTotalFunc"
+      @change="handleChange"
+      @showSizeChange="handleSizeChange"
     />
   </div>
 </template>
@@ -36,19 +36,18 @@ const props = defineProps({
       return [10, 20, 30, 50]
     }
   },
-  // 移动端页码按钮的数量端默认值5
-  pagerCount: {
-    type: Number,
-    default: document.body.clientWidth < 992 ? 5 : 7
-  },
-  layout: {
-    type: String,
-    default: 'total, sizes, prev, pager, next, jumper'
+  showSizeChanger: {
+    type: Boolean,
+    default: true
   },
-  background: {
+  showQuickJumper: {
     type: Boolean,
     default: true
   },
+  showTotal: {
+    type: [Boolean, Function],
+    default: true
+  },
   autoScroll: {
     type: Boolean,
     default: true
@@ -59,7 +58,8 @@ const props = defineProps({
   }
 })
 
-const emit = defineEmits()
+const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
+
 const currentPage = computed({
   get() {
     return props.page
@@ -68,27 +68,44 @@ const currentPage = computed({
     emit('update:page', val)
   }
 })
+
 const pageSize = computed({
   get() {
     return props.limit
   },
-  set(val){
+  set(val) {
     emit('update:limit', val)
   }
 })
 
-function handleSizeChange(val) {
-  if (currentPage.value * val > props.total) {
-    currentPage.value = 1
+const pageSizeOptions = computed(() => {
+  return props.pageSizes.map(size => String(size))
+})
+
+// 处理 showTotal
+const showTotalFunc = computed(() => {
+  if (typeof props.showTotal === 'function') {
+    return props.showTotal
+  } else if (props.showTotal === true) {
+    return (total, range) => `共 ${total} 条`
+  } else {
+    return false
   }
-  emit('pagination', { page: currentPage.value, limit: val })
+})
+
+function handleChange(page, pageSize) {
+  emit('pagination', { page, limit: pageSize })
   if (props.autoScroll) {
     scrollTo(0, 800)
   }
 }
 
-function handleCurrentChange(val) {
-  emit('pagination', { page: val, limit: pageSize.value })
+function handleSizeChange(current, size) {
+  if (current * size > props.total) {
+    currentPage.value = 1
+  }
+  pageSize.value = size
+  emit('pagination', { page: currentPage.value, limit: size })
   if (props.autoScroll) {
     scrollTo(0, 800)
   }
@@ -98,8 +115,11 @@ function handleCurrentChange(val) {
 <style scoped>
 .pagination-container {
   background: #fff;
+  padding: 16px;
+  display: flex;
+  justify-content: flex-end;
 }
 .pagination-container.hidden {
   display: none;
 }
-</style>
+</style>

+ 110 - 62
yushu-uivue3/src/views/monitor/cache/index.vue

@@ -1,82 +1,112 @@
 <template>
   <div class="app-container">
-    <el-row :gutter="10">
-      <el-col :span="24" class="card-box">
-        <el-card>
-          <template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">基本信息</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%">
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">Redis版本</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">运行模式</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "单机" : "集群" }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">端口</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">客户端数</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">运行时间(天)</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">使用内存</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">使用CPU</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">内存配置</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">AOF是否开启</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "否" : "是" }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">RDB是否成功</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">Key数量</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">网络入口/出口</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
+    <a-row :gutter="10">
+      <a-col :span="24" class="card-box">
+        <a-card>
+          <template #title>
+            <MonitorOutlined style="margin-right: 8px" />
+            <span>基本信息</span>
+          </template>
+          <a-table 
+            :dataSource="basicInfoData" 
+            :columns="basicInfoColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="false"
+          />
+        </a-card>
+      </a-col>
 
-      <el-col :span="12" class="card-box">
-        <el-card>
-          <template #header><PieChart style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">命令统计</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <div ref="commandstats" style="height: 420px" />
-          </div>
-        </el-card>
-      </el-col>
+      <a-col :span="12" class="card-box">
+        <a-card>
+          <template #title>
+            <BarChartOutlined style="margin-right: 8px" />
+            <span>命令统计</span>
+          </template>
+          <div ref="commandstats" style="height: 420px" />
+        </a-card>
+      </a-col>
 
-      <el-col :span="12" class="card-box">
-        <el-card>
-          <template #header><Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存信息</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <div ref="usedmemory" style="height: 420px" />
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+      <a-col :span="12" class="card-box">
+        <a-card>
+          <template #title>
+            <AreaChartOutlined style="margin-right: 8px" />
+            <span>内存信息</span>
+          </template>
+          <div ref="usedmemory" style="height: 420px" />
+        </a-card>
+      </a-col>
+    </a-row>
   </div>
 </template>
 
 <script setup name="Cache">
 import { getCache } from '@/api/monitor/cache'
+import { MonitorOutlined, BarChartOutlined, AreaChartOutlined } from '@ant-design/icons-vue'
+import { message } from 'ant-design-vue'
 import * as echarts from 'echarts'
 
-const cache = ref([])
+const cache = ref({})
 const commandstats = ref(null)
 const usedmemory = ref(null)
 const { proxy } = getCurrentInstance()
 
+// 基本信息表格数据
+const basicInfoData = computed(() => {
+  if (!cache.value.info) return []
+  const info = cache.value.info
+  return [
+    {
+      key: '1',
+      label1: 'Redis版本',
+      value1: info.redis_version || '-',
+      label2: '运行模式',
+      value2: info.redis_mode == "standalone" ? "单机" : "集群",
+      label3: '端口',
+      value3: info.tcp_port || '-',
+      label4: '客户端数',
+      value4: info.connected_clients || '-'
+    },
+    {
+      key: '2',
+      label1: '运行时间(天)',
+      value1: info.uptime_in_days || '-',
+      label2: '使用内存',
+      value2: info.used_memory_human || '-',
+      label3: '使用CPU',
+      value3: parseFloat(info.used_cpu_user_children || 0).toFixed(2),
+      label4: '内存配置',
+      value4: info.maxmemory_human || '-'
+    },
+    {
+      key: '3',
+      label1: 'AOF是否开启',
+      value1: info.aof_enabled == "0" ? "否" : "是",
+      label2: 'RDB是否成功',
+      value2: info.rdb_last_bgsave_status || '-',
+      label3: 'Key数量',
+      value3: cache.value.dbSize || '-',
+      label4: '网络入口/出口',
+      value4: `${info.instantaneous_input_kbps || 0}kps/${info.instantaneous_output_kbps || 0}kps`
+    }
+  ]
+})
+
+const basicInfoColumns = [
+  { dataIndex: 'label1', key: 'label1', width: '12.5%' },
+  { dataIndex: 'value1', key: 'value1', width: '12.5%' },
+  { dataIndex: 'label2', key: 'label2', width: '12.5%' },
+  { dataIndex: 'value2', key: 'value2', width: '12.5%' },
+  { dataIndex: 'label3', key: 'label3', width: '12.5%' },
+  { dataIndex: 'value3', key: 'value3', width: '12.5%' },
+  { dataIndex: 'label4', key: 'label4', width: '12.5%' },
+  { dataIndex: 'value4', key: 'value4', width: '12.5%' }
+]
+
 function getList() {
-  proxy.$modal.loading("正在加载缓存监控数据,请稍候!")
+  const hide = message.loading("正在加载缓存监控数据,请稍候!", 0)
   getCache().then(response => {
-    proxy.$modal.closeLoading()
+    hide()
     cache.value = response.data
 
     const commandstatsIntance = echarts.init(commandstats.value, "macarons")
@@ -125,8 +155,26 @@ function getList() {
       commandstatsIntance.resize()
       usedmemoryInstance.resize()
     })
+  }).catch(() => {
+    hide()
   })
 }
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 16px;
+}
+
+.card-box {
+  margin-bottom: 16px;
+}
+
+:deep(.ant-table) {
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+</style>

+ 224 - 157
yushu-uivue3/src/views/monitor/cache/list.vue

@@ -1,161 +1,103 @@
 <template>
   <div class="app-container">
-    <el-row :gutter="10">
-      <el-col :span="8">
-        <el-card style="height: calc(100vh - 125px)">
-          <template #header>
-            <Collection style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存列表</span>
-            <el-button
-              style="float: right; padding: 3px 0"
-              link
-              type="primary"
-              icon="Refresh"
+    <a-row :gutter="10">
+      <a-col :span="8">
+        <a-card :bordered="false" style="height: calc(100vh - 125px)">
+          <template #title>
+            <DatabaseOutlined style="margin-right: 8px" />
+            <span>缓存列表</span>
+            <a-button
+              type="link"
+              style="float: right; padding: 0"
               @click="refreshCacheNames()"
-            ></el-button>
-          </template>
-          <el-table
-            v-loading="loading"
-            :data="cacheNames"
-            :height="tableHeight"
-            highlight-current-row
-            @row-click="getCacheKeys"
-            style="width: 100%"
-          >
-            <el-table-column
-              label="序号"
-              width="60"
-              type="index"
-            ></el-table-column>
-
-            <el-table-column
-              label="缓存名称"
-              align="center"
-              prop="cacheName"
-              :show-overflow-tooltip="true"
-              :formatter="nameFormatter"
-            ></el-table-column>
-
-            <el-table-column
-              label="备注"
-              align="center"
-              prop="remark"
-              :show-overflow-tooltip="true"
-            />
-            <el-table-column
-              label="操作"
-              width="60"
-              align="center"
-              class-name="small-padding fixed-width"
             >
-              <template #default="scope">
-                <el-button
-                  link
-                  type="primary"
-                  icon="Delete"
-                  @click="handleClearCacheName(scope.row)"
-                ></el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-card>
-      </el-col>
-
-      <el-col :span="8">
-        <el-card style="height: calc(100vh - 125px)">
-          <template #header>
-            <Key style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">键名列表</span>
-            <el-button
-              style="float: right; padding: 3px 0"
-              link
-              type="primary"
-              icon="Refresh"
-              @click="refreshCacheKeys()"
-            ></el-button>
+              <template #icon><ReloadOutlined /></template>
+            </a-button>
           </template>
-          <el-table
-            v-loading="subLoading"
-            :data="cacheKeys"
-            :height="tableHeight"
-            highlight-current-row
-            @row-click="handleCacheValue"
-            style="width: 100%"
-          >
-            <el-table-column
-              label="序号"
-              width="60"
-              type="index"
-            ></el-table-column>
-            <el-table-column
-              label="缓存键名"
-              align="center"
-              :show-overflow-tooltip="true"
-              :formatter="keyFormatter"
-            >
-            </el-table-column>
-            <el-table-column
-              label="操作"
-              width="60"
-              align="center"
-              class-name="small-padding fixed-width"
+          <a-table
+            :loading="loading"
+            :dataSource="cacheNames"
+            :columns="cacheNameColumns"
+            :pagination="false"
+            :scroll="{ y: tableHeight }"
+            :row-selection="null"
+            :customRow="(record) => ({ onClick: () => getCacheKeys(record) })"
+            size="small"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="8">
+        <a-card :bordered="false" style="height: calc(100vh - 125px)">
+          <template #title>
+            <KeyOutlined style="margin-right: 8px" />
+            <span>键名列表</span>
+            <a-button
+              type="link"
+              style="float: right; padding: 0"
+              @click="refreshCacheKeys()"
             >
-              <template #default="scope">
-                <el-button
-                  link
-                  type="primary"
-                  icon="Delete"
-                  @click="handleClearCacheKey(scope.row)"
-                ></el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </el-card>
-      </el-col>
-
-      <el-col :span="8">
-        <el-card :bordered="false" style="height: calc(100vh - 125px)">
-          <template #header>
-            <Document style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">缓存内容</span>
-            <el-button
-              style="float: right; padding: 3px 0"
-              link
-              type="primary"
-              icon="Refresh"
+              <template #icon><ReloadOutlined /></template>
+            </a-button>
+          </template>
+          <a-table
+            :loading="subLoading"
+            :dataSource="cacheKeys"
+            :columns="cacheKeyColumns"
+            :pagination="false"
+            :scroll="{ y: tableHeight }"
+            :row-selection="null"
+            :customRow="(record) => ({ 
+              onClick: () => {
+                const cacheKey = record.cacheKey || record
+                handleCacheValue(cacheKey)
+              }
+            })"
+            size="small"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="8">
+        <a-card :bordered="false" style="height: calc(100vh - 125px)">
+          <template #title>
+            <FileTextOutlined style="margin-right: 8px" />
+            <span>缓存内容</span>
+            <a-button
+              type="link"
+              style="float: right; padding: 0"
               @click="handleClearCacheAll()"
-              >清理全部</el-button
             >
+              <template #icon><ReloadOutlined /></template>
+              清理全部
+            </a-button>
           </template>
-          <el-form :model="cacheForm">
-            <el-row :gutter="32">
-              <el-col :offset="1" :span="22">
-                <el-form-item label="缓存名称:" prop="cacheName">
-                  <el-input v-model="cacheForm.cacheName" :readOnly="true" />
-                </el-form-item>
-              </el-col>
-              <el-col :offset="1" :span="22">
-                <el-form-item label="缓存键名:" prop="cacheKey">
-                  <el-input v-model="cacheForm.cacheKey" :readOnly="true" />
-                </el-form-item>
-              </el-col>
-              <el-col :offset="1" :span="22">
-                <el-form-item label="缓存内容:" prop="cacheValue">
-                  <el-input
-                    v-model="cacheForm.cacheValue"
-                    type="textarea"
-                    :rows="8"
-                    :readOnly="true"
-                  />
-                </el-form-item>
-              </el-col>
-            </el-row>
-          </el-form>
-        </el-card>
-      </el-col>
-    </el-row>
+          <a-form :model="cacheForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+            <a-form-item label="缓存名称:" name="cacheName">
+              <a-input v-model:value="cacheForm.cacheName" :readonly="true" />
+            </a-form-item>
+            <a-form-item label="缓存键名:" name="cacheKey">
+              <a-input v-model:value="cacheForm.cacheKey" :readonly="true" />
+            </a-form-item>
+            <a-form-item label="缓存内容:" name="cacheValue">
+              <a-textarea
+                v-model:value="cacheForm.cacheValue"
+                :rows="8"
+                :readonly="true"
+              />
+            </a-form-item>
+          </a-form>
+        </a-card>
+      </a-col>
+    </a-row>
   </div>
 </template>
 
 <script setup name="CacheList">
+import { h } from 'vue'
 import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/monitor/cache"
+import { DatabaseOutlined, KeyOutlined, FileTextOutlined, ReloadOutlined, DeleteOutlined } from '@ant-design/icons-vue'
+import { Modal, message } from 'ant-design-vue'
 
 const { proxy } = getCurrentInstance()
 
@@ -167,6 +109,84 @@ const subLoading = ref(false)
 const nowCacheName = ref("")
 const tableHeight = ref(window.innerHeight - 200)
 
+// 缓存名称表格列
+const cacheNameColumns = [
+  {
+    title: '序号',
+    key: 'index',
+    width: 60,
+    customRender: ({ index }) => index + 1
+  },
+  {
+    title: '缓存名称',
+    dataIndex: 'cacheName',
+    key: 'cacheName',
+    align: 'center',
+    ellipsis: true,
+    customRender: ({ record }) => nameFormatter(record)
+  },
+  {
+    title: '备注',
+    dataIndex: 'remark',
+    key: 'remark',
+    align: 'center',
+    ellipsis: true
+  },
+  {
+    title: '操作',
+    key: 'action',
+    width: 60,
+    align: 'center',
+    customRender: ({ record }) => {
+      return h('a-button', {
+        type: 'link',
+        danger: true,
+        onClick: (e) => {
+          e.stopPropagation()
+          handleClearCacheName(record)
+        }
+      }, {
+        default: () => h(DeleteOutlined)
+      })
+    }
+  }
+]
+
+// 缓存键名表格列
+const cacheKeyColumns = [
+  {
+    title: '序号',
+    key: 'index',
+    width: 60,
+    customRender: ({ index }) => index + 1
+  },
+  {
+    title: '缓存键名',
+    key: 'cacheKey',
+    align: 'center',
+    ellipsis: true,
+    customRender: ({ record }) => keyFormatter(record)
+  },
+  {
+    title: '操作',
+    key: 'action',
+    width: 60,
+    align: 'center',
+    customRender: ({ record }) => {
+      return h('a-button', {
+        type: 'link',
+        danger: true,
+        onClick: (e) => {
+          e.stopPropagation()
+          handleClearCacheKey(record)
+        }
+      }, {
+        default: () => h(DeleteOutlined)
+      })
+    }
+  }
+]
+
 /** 查询缓存名称列表 */
 function getCacheNames() {
   loading.value = true
@@ -179,14 +199,20 @@ function getCacheNames() {
 /** 刷新缓存名称列表 */
 function refreshCacheNames() {
   getCacheNames()
-  proxy.$modal.msgSuccess("刷新缓存列表成功")
+  message.success("刷新缓存列表成功")
 }
 
 /** 清理指定名称缓存 */
 function handleClearCacheName(row) {
-  clearCacheName(row.cacheName).then(response => {
-    proxy.$modal.msgSuccess("清理缓存名称[" + row.cacheName + "]成功")
-    getCacheKeys()
+  Modal.confirm({
+    title: '提示',
+    content: `是否确认清理缓存名称"${row.cacheName}"?`,
+    onOk() {
+      return clearCacheName(row.cacheName).then(() => {
+        message.success("清理缓存名称[" + row.cacheName + "]成功")
+        getCacheKeys()
+      })
+    }
   })
 }
 
@@ -198,7 +224,11 @@ function getCacheKeys(row) {
   }
   subLoading.value = true
   listCacheKey(cacheName).then(response => {
-    cacheKeys.value = response.data
+    // 将字符串数组转换为对象数组,以便表格使用
+    cacheKeys.value = response.data.map((key, index) => ({
+      key: index,
+      cacheKey: key
+    }))
     subLoading.value = false
     nowCacheName.value = cacheName
   })
@@ -207,14 +237,21 @@ function getCacheKeys(row) {
 /** 刷新缓存键名列表 */
 function refreshCacheKeys() {
   getCacheKeys()
-  proxy.$modal.msgSuccess("刷新键名列表成功")
+  message.success("刷新键名列表成功")
 }
 
 /** 清理指定键名缓存 */
-function handleClearCacheKey(cacheKey) {
-  clearCacheKey(cacheKey).then(response => {
-    proxy.$modal.msgSuccess("清理缓存键名[" + cacheKey + "]成功")
-    getCacheKeys()
+function handleClearCacheKey(record) {
+  const cacheKey = typeof record === 'string' ? record : record.cacheKey || record
+  Modal.confirm({
+    title: '提示',
+    content: `是否确认清理缓存键名"${cacheKey}"?`,
+    onOk() {
+      return clearCacheKey(cacheKey).then(() => {
+        message.success("清理缓存键名[" + cacheKey + "]成功")
+        getCacheKeys()
+      })
+    }
   })
 }
 
@@ -224,7 +261,8 @@ function nameFormatter(row) {
 }
 
 /** 键名前缀去除 */
-function keyFormatter(cacheKey) {
+function keyFormatter(record) {
+  const cacheKey = record.cacheKey || record
   return cacheKey.replace(nowCacheName.value, "")
 }
 
@@ -237,10 +275,39 @@ function handleCacheValue(cacheKey) {
 
 /** 清理全部缓存 */
 function handleClearCacheAll() {
-  clearCacheAll().then(response => {
-    proxy.$modal.msgSuccess("清理全部缓存成功")
+  Modal.confirm({
+    title: '提示',
+    content: '是否确认清理全部缓存?',
+    onOk() {
+      return clearCacheAll().then(() => {
+        message.success("清理全部缓存成功")
+        getCacheNames()
+        cacheKeys.value = []
+        cacheForm.value = {}
+      })
+    }
   })
 }
 
 getCacheNames()
 </script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 16px;
+}
+
+:deep(.ant-table) {
+  .ant-table-tbody > tr {
+    cursor: pointer;
+    
+    &:hover {
+      background-color: #f5f5f5;
+    }
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+</style>

+ 253 - 158
yushu-uivue3/src/views/monitor/errorLog/index.vue

@@ -1,175 +1,169 @@
 <template>
   <div class="app-container">
     <!-- 搜索区域 -->
-    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" class="search-form">
-      <el-form-item label="错误类型" prop="errorType">
-        <el-select v-model="queryParams.errorType" placeholder="请选择" clearable style="width: 120px">
-          <el-option label="系统错误" value="SYSTEM" />
-          <el-option label="业务错误" value="BUSINESS" />
-          <el-option label="API错误" value="API" />
-          <el-option label="SQL错误" value="SQL" />
-          <el-option label="认证错误" value="AUTH" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="错误级别" prop="errorLevel">
-        <el-select v-model="queryParams.errorLevel" placeholder="请选择" clearable style="width: 100px">
-          <el-option label="ERROR" value="ERROR" />
-          <el-option label="WARN" value="WARN" />
-          <el-option label="FATAL" value="FATAL" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择" clearable style="width: 100px">
-          <el-option label="未处理" value="0" />
-          <el-option label="已处理" value="1" />
-          <el-option label="已忽略" value="2" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="错误信息" prop="errorMessage">
-        <el-input v-model="queryParams.errorMessage" placeholder="请输入" clearable @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item label="发生时间" style="width: 308px;">
-        <el-date-picker
-          v-model="dateRange"
+    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
+      <a-form-item label="错误类型" name="errorType">
+        <a-select v-model:value="queryParams.errorType" placeholder="请选择" allow-clear style="width: 120px">
+          <a-select-option value="SYSTEM">系统错误</a-select-option>
+          <a-select-option value="BUSINESS">业务错误</a-select-option>
+          <a-select-option value="API">API错误</a-select-option>
+          <a-select-option value="SQL">SQL错误</a-select-option>
+          <a-select-option value="AUTH">认证错误</a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="错误级别" name="errorLevel">
+        <a-select v-model:value="queryParams.errorLevel" placeholder="请选择" allow-clear style="width: 100px">
+          <a-select-option value="ERROR">ERROR</a-select-option>
+          <a-select-option value="WARN">WARN</a-select-option>
+          <a-select-option value="FATAL">FATAL</a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="状态" name="status">
+        <a-select v-model:value="queryParams.status" placeholder="请选择" allow-clear style="width: 100px">
+          <a-select-option value="0">未处理</a-select-option>
+          <a-select-option value="1">已处理</a-select-option>
+          <a-select-option value="2">已忽略</a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="错误信息" name="errorMessage">
+        <a-input v-model:value="queryParams.errorMessage" placeholder="请输入" allow-clear @pressEnter="handleQuery" />
+      </a-form-item>
+      <a-form-item label="发生时间">
+        <a-range-picker
+          v-model:value="dateRange"
           value-format="YYYY-MM-DD"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
+          format="YYYY-MM-DD"
+          style="width: 308px"
         />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
+      </a-form-item>
+      <a-form-item>
+        <a-button type="primary" @click="handleQuery"><SearchOutlined />搜索</a-button>
+        <a-button style="margin-left: 8px" @click="resetQuery"><ReloadOutlined />重置</a-button>
+      </a-form-item>
+    </a-form>
 
     <!-- 操作按钮 -->
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button type="success" plain icon="Check" :disabled="multiple" @click="handleBatchResolve('1')" v-hasPermi="['monitor:errorLog:resolve']">
-          批量处理
-        </el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="warning" plain icon="Close" :disabled="multiple" @click="handleBatchResolve('2')" v-hasPermi="['monitor:errorLog:resolve']">
-          批量忽略
-        </el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['monitor:errorLog:remove']">
-          删除
-        </el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="danger" plain icon="Delete" @click="handleClean" v-hasPermi="['monitor:errorLog:clean']">
-          清空
-        </el-button>
-      </el-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
-    </el-row>
+    <div class="button-toolbar">
+      <a-row :gutter="10">
+        <a-col :span="1.5">
+          <a-button type="primary" style="background-color: #52c41a; border-color: #52c41a" :disabled="multiple" @click="handleBatchResolve('1')" v-hasPermi="['monitor:errorLog:resolve']">
+            <CheckOutlined />批量处理
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button type="primary" style="background-color: #faad14; border-color: #faad14" :disabled="multiple" @click="handleBatchResolve('2')" v-hasPermi="['monitor:errorLog:resolve']">
+            <CloseOutlined />批量忽略
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['monitor:errorLog:remove']">
+            <DeleteOutlined />删除
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button danger @click="handleClean" v-hasPermi="['monitor:errorLog:clean']">
+            <DeleteOutlined />清空
+          </a-button>
+        </a-col>
+        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
+      </a-row>
+    </div>
 
     <!-- 数据表格 -->
-    <el-table v-loading="loading" :data="errorList" @selection-change="handleSelectionChange" row-key="errorId">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="错误类型" prop="errorType" width="100" align="center">
-        <template #default="scope">
-          <el-tag :type="getErrorTypeTag(scope.row.errorType)" size="small">{{ scope.row.errorType }}</el-tag>
+    <a-table
+      :loading="loading"
+      :data-source="errorList"
+      :columns="tableColumns"
+      :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+      :row-key="record => record.errorId"
+      :pagination="false"
+    >
+      <template #bodyCell="{ column, record }">
+        <template v-if="column.key === 'errorType'">
+          <a-tag :color="getErrorTypeColor(record.errorType)">{{ record.errorType }}</a-tag>
         </template>
-      </el-table-column>
-      <el-table-column label="级别" prop="errorLevel" width="80" align="center">
-        <template #default="scope">
-          <el-tag :type="getErrorLevelTag(scope.row.errorLevel)" size="small">{{ scope.row.errorLevel }}</el-tag>
+        <template v-else-if="column.key === 'errorLevel'">
+          <a-tag :color="getErrorLevelColor(record.errorLevel)">{{ record.errorLevel }}</a-tag>
         </template>
-      </el-table-column>
-      <el-table-column label="错误信息" prop="errorMessage" min-width="250" show-overflow-tooltip />
-      <el-table-column label="请求URL" prop="requestUrl" width="200" show-overflow-tooltip />
-      <el-table-column label="操作人" prop="userName" width="100" align="center" />
-      <el-table-column label="次数" prop="occurCount" width="70" align="center">
-        <template #default="scope">
-          <el-badge :value="scope.row.occurCount" :max="99" :type="scope.row.occurCount > 10 ? 'danger' : 'primary'" />
+        <template v-else-if="column.key === 'occurCount'">
+          <a-badge :count="record.occurCount" :number-style="{ backgroundColor: record.occurCount > 10 ? '#ff4d4f' : '#1890ff' }" />
         </template>
-      </el-table-column>
-      <el-table-column label="状态" prop="status" width="80" align="center">
-        <template #default="scope">
-          <el-tag :type="getStatusTag(scope.row.status)" size="small">{{ getStatusText(scope.row.status) }}</el-tag>
+        <template v-else-if="column.key === 'status'">
+          <a-tag :color="getStatusColor(record.status)">{{ getStatusText(record.status) }}</a-tag>
         </template>
-      </el-table-column>
-      <el-table-column label="发生时间" prop="createTime" width="160" align="center" />
-      <el-table-column label="操作" width="180" align="center" fixed="right">
-        <template #default="scope">
-          <el-button link type="primary" icon="View" @click="handleView(scope.row)">详情</el-button>
-          <el-button link type="success" icon="Check" @click="handleResolve(scope.row, '1')" v-if="scope.row.status === '0'" v-hasPermi="['monitor:errorLog:resolve']">处理</el-button>
-          <el-button link type="warning" icon="Close" @click="handleResolve(scope.row, '2')" v-if="scope.row.status === '0'" v-hasPermi="['monitor:errorLog:resolve']">忽略</el-button>
+        <template v-else-if="column.key === 'action'">
+          <a-button type="link" size="small" @click="handleView(record)"><EyeOutlined />详情</a-button>
+          <a-button type="link" size="small" @click="handleResolve(record, '1')" v-if="record.status === '0'" v-hasPermi="['monitor:errorLog:resolve']" style="color: #52c41a"><CheckOutlined />处理</a-button>
+          <a-button type="link" size="small" @click="handleResolve(record, '2')" v-if="record.status === '0'" v-hasPermi="['monitor:errorLog:resolve']" style="color: #faad14"><CloseOutlined />忽略</a-button>
         </template>
-      </el-table-column>
-    </el-table>
+      </template>
+    </a-table>
 
     <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
 
     <!-- 详情对话框 -->
-    <el-dialog title="错误详情" v-model="detailOpen" width="800px" append-to-body>
-      <el-descriptions :column="2" border label-width="100px">
-        <el-descriptions-item label="错误ID">{{ detail.errorId }}</el-descriptions-item>
-        <el-descriptions-item label="错误代码">{{ detail.errorCode }}</el-descriptions-item>
-        <el-descriptions-item label="错误类型">
-          <el-tag :type="getErrorTypeTag(detail.errorType)" size="small">{{ detail.errorType }}</el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="错误级别">
-          <el-tag :type="getErrorLevelTag(detail.errorLevel)" size="small">{{ detail.errorLevel }}</el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="请求URL" :span="2">{{ detail.requestUrl }}</el-descriptions-item>
-        <el-descriptions-item label="请求方法">{{ detail.requestMethod }}</el-descriptions-item>
-        <el-descriptions-item label="请求IP">{{ detail.requestIp }}</el-descriptions-item>
-        <el-descriptions-item label="请求参数" :span="2" v-if="detail.requestParams">{{ detail.requestParams }}</el-descriptions-item>
-        <el-descriptions-item label="操作人">{{ detail.userName }}</el-descriptions-item>
-        <el-descriptions-item label="发生次数">{{ detail.occurCount }}</el-descriptions-item>
-        <el-descriptions-item label="首次时间">{{ detail.firstTime }}</el-descriptions-item>
-        <el-descriptions-item label="最近时间">{{ detail.lastTime }}</el-descriptions-item>
-        <el-descriptions-item label="来源类" :span="2">{{ detail.sourceClass }}</el-descriptions-item>
-        <el-descriptions-item label="来源方法">{{ detail.sourceMethod }}</el-descriptions-item>
-        <el-descriptions-item label="行号">{{ detail.sourceLine }}</el-descriptions-item>
-        <el-descriptions-item label="状态">
-          <el-tag :type="getStatusTag(detail.status)" size="small">{{ getStatusText(detail.status) }}</el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="处理人">{{ detail.resolveBy || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="处理时间" :span="2">{{ detail.resolveTime || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="处理备注" :span="2">{{ detail.resolveRemark || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="错误消息" :span="2">{{ detail.errorMessage }}</el-descriptions-item>
-      </el-descriptions>
+    <a-modal title="错误详情" v-model:open="detailOpen" width="800px" :footer="null">
+      <a-descriptions :column="2" bordered>
+        <a-descriptions-item label="错误ID">{{ detail.errorId }}</a-descriptions-item>
+        <a-descriptions-item label="错误代码">{{ detail.errorCode }}</a-descriptions-item>
+        <a-descriptions-item label="错误类型">
+          <a-tag :color="getErrorTypeColor(detail.errorType)">{{ detail.errorType }}</a-tag>
+        </a-descriptions-item>
+        <a-descriptions-item label="错误级别">
+          <a-tag :color="getErrorLevelColor(detail.errorLevel)">{{ detail.errorLevel }}</a-tag>
+        </a-descriptions-item>
+        <a-descriptions-item label="请求URL" :span="2">{{ detail.requestUrl }}</a-descriptions-item>
+        <a-descriptions-item label="请求方法">{{ detail.requestMethod }}</a-descriptions-item>
+        <a-descriptions-item label="请求IP">{{ detail.requestIp }}</a-descriptions-item>
+        <a-descriptions-item label="请求参数" :span="2" v-if="detail.requestParams">{{ detail.requestParams }}</a-descriptions-item>
+        <a-descriptions-item label="操作人">{{ detail.userName }}</a-descriptions-item>
+        <a-descriptions-item label="发生次数">{{ detail.occurCount }}</a-descriptions-item>
+        <a-descriptions-item label="首次时间">{{ detail.firstTime }}</a-descriptions-item>
+        <a-descriptions-item label="最近时间">{{ detail.lastTime }}</a-descriptions-item>
+        <a-descriptions-item label="来源类" :span="2">{{ detail.sourceClass }}</a-descriptions-item>
+        <a-descriptions-item label="来源方法">{{ detail.sourceMethod }}</a-descriptions-item>
+        <a-descriptions-item label="行号">{{ detail.sourceLine }}</a-descriptions-item>
+        <a-descriptions-item label="状态">
+          <a-tag :color="getStatusColor(detail.status)">{{ getStatusText(detail.status) }}</a-tag>
+        </a-descriptions-item>
+        <a-descriptions-item label="处理人">{{ detail.resolveBy || '-' }}</a-descriptions-item>
+        <a-descriptions-item label="处理时间" :span="2">{{ detail.resolveTime || '-' }}</a-descriptions-item>
+        <a-descriptions-item label="处理备注" :span="2">{{ detail.resolveRemark || '-' }}</a-descriptions-item>
+        <a-descriptions-item label="错误消息" :span="2">{{ detail.errorMessage }}</a-descriptions-item>
+      </a-descriptions>
       
-      <el-divider content-position="left">堆栈信息</el-divider>
-      <el-input
-        v-model="detail.errorDetail"
-        type="textarea"
+      <a-divider orientation="left">堆栈信息</a-divider>
+      <a-textarea
+        v-model:value="detail.errorDetail"
         :rows="12"
         readonly
         class="stack-trace"
       />
       
       <template #footer v-if="detail.status === '0'">
-        <el-button @click="detailOpen = false">关闭</el-button>
-        <el-button type="warning" @click="handleResolveFromDetail('2')">忽略</el-button>
-        <el-button type="success" @click="handleResolveFromDetail('1')">标记已处理</el-button>
+        <a-button @click="detailOpen = false">关闭</a-button>
+        <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleResolveFromDetail('2')">忽略</a-button>
+        <a-button type="primary" style="background-color: #52c41a; border-color: #52c41a" @click="handleResolveFromDetail('1')">标记已处理</a-button>
       </template>
-    </el-dialog>
+    </a-modal>
 
     <!-- 处理备注对话框 -->
-    <el-dialog title="处理备注" v-model="resolveOpen" width="500px" append-to-body>
-      <el-form ref="resolveRef" :model="resolveForm" label-width="80px">
-        <el-form-item label="处理备注">
-          <el-input v-model="resolveForm.remark" type="textarea" :rows="3" placeholder="请输入处理备注(可选)" />
-        </el-form-item>
-      </el-form>
+    <a-modal title="处理备注" v-model:open="resolveOpen" width="500px">
+      <a-form ref="resolveRef" :model="resolveForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+        <a-form-item label="处理备注">
+          <a-textarea v-model:value="resolveForm.remark" :rows="3" placeholder="请输入处理备注(可选)" />
+        </a-form-item>
+      </a-form>
       <template #footer>
-        <el-button @click="resolveOpen = false">取消</el-button>
-        <el-button type="primary" @click="submitResolve">确定</el-button>
+        <a-button @click="resolveOpen = false">取消</a-button>
+        <a-button type="primary" @click="submitResolve">确定</a-button>
       </template>
-    </el-dialog>
+    </a-modal>
   </div>
 </template>
 
 <script setup name="ErrorLog">
+import { SearchOutlined, ReloadOutlined, DeleteOutlined, CheckOutlined, CloseOutlined, EyeOutlined } from '@ant-design/icons-vue'
 import { listErrorLog, getErrorLog, resolveError, batchResolve, delErrorLog, cleanErrorLog } from '@/api/monitor/errorLog'
 
 const { proxy } = getCurrentInstance()
@@ -177,6 +171,7 @@ const { proxy } = getCurrentInstance()
 const loading = ref(true)
 const showSearch = ref(true)
 const errorList = ref([])
+const selectedRowKeys = ref([])
 const ids = ref([])
 const multiple = ref(true)
 const total = ref(0)
@@ -195,6 +190,19 @@ const queryParams = ref({
   status: null
 })
 
+// 表格列配置
+const tableColumns = [
+  { title: '错误类型', key: 'errorType', width: 100, align: 'center' },
+  { title: '级别', key: 'errorLevel', width: 80, align: 'center' },
+  { title: '错误信息', dataIndex: 'errorMessage', key: 'errorMessage', ellipsis: true },
+  { title: '请求URL', dataIndex: 'requestUrl', key: 'requestUrl', width: 200, ellipsis: true },
+  { title: '操作人', dataIndex: 'userName', key: 'userName', width: 100, align: 'center' },
+  { title: '次数', key: 'occurCount', width: 70, align: 'center' },
+  { title: '状态', key: 'status', width: 80, align: 'center' },
+  { title: '发生时间', dataIndex: 'createTime', key: 'createTime', width: 160, align: 'center' },
+  { title: '操作', key: 'action', width: 180, align: 'center', fixed: 'right' }
+]
+
 function getList() {
   loading.value = true
   listErrorLog(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
@@ -215,9 +223,10 @@ function resetQuery() {
   handleQuery()
 }
 
-function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.errorId)
-  multiple.value = !selection.length
+function handleSelectionChange(selectedKeys) {
+  selectedRowKeys.value = selectedKeys
+  ids.value = selectedKeys
+  multiple.value = !selectedKeys.length
 }
 
 function handleView(row) {
@@ -303,19 +312,19 @@ function handleClean() {
   }).catch(() => {})
 }
 
-function getErrorTypeTag(type) {
-  const map = { SYSTEM: 'danger', BUSINESS: 'warning', API: 'info', SQL: 'danger', AUTH: 'warning' }
-  return map[type] || 'info'
+function getErrorTypeColor(type) {
+  const map = { SYSTEM: 'red', BUSINESS: 'orange', API: 'blue', SQL: 'red', AUTH: 'orange' }
+  return map[type] || 'default'
 }
 
-function getErrorLevelTag(level) {
-  const map = { FATAL: 'danger', ERROR: 'danger', WARN: 'warning' }
-  return map[level] || 'info'
+function getErrorLevelColor(level) {
+  const map = { FATAL: 'red', ERROR: 'red', WARN: 'orange' }
+  return map[level] || 'default'
 }
 
-function getStatusTag(status) {
-  const map = { '0': 'danger', '1': 'success', '2': 'info' }
-  return map[status] || 'info'
+function getStatusColor(status) {
+  const map = { '0': 'red', '1': 'green', '2': 'default' }
+  return map[status] || 'default'
 }
 
 function getStatusText(status) {
@@ -326,22 +335,108 @@ function getStatusText(status) {
 getList()
 </script>
 
-<style scoped>
-.search-form {
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
   background: #fff;
-  padding: 20px 20px 0;
+  padding: 16px;
   border-radius: 4px;
-  margin-bottom: 16px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
 }
 
 .stack-trace {
   font-family: 'Consolas', 'Monaco', monospace;
   font-size: 12px;
-}
-
-:deep(.stack-trace .el-textarea__inner) {
   background: #1e1e1e;
   color: #d4d4d4;
-  font-family: 'Consolas', 'Monaco', monospace;
+  
+  :deep(.ant-input) {
+    background: #1e1e1e;
+    color: #d4d4d4;
+    font-family: 'Consolas', 'Monaco', monospace;
+  }
 }
 </style>

+ 61 - 67
yushu-uivue3/src/views/monitor/errorLog/test.vue

@@ -1,86 +1,80 @@
 <template>
   <div class="app-container">
-    <el-card>
-      <template #header>
-        <span>错误日志测试</span>
-      </template>
+    <a-card>
+      <template #title>错误日志测试</template>
       
-      <el-alert type="warning" :closable="false" style="margin-bottom: 20px;">
-        点击下方按钮触发不同类型的错误,然后到错误日志页面查看记录效果
-      </el-alert>
+      <a-alert type="warning" :closable="false" style="margin-bottom: 20px;" show-icon>
+        <template #message>
+          点击下方按钮触发不同类型的错误,然后到错误日志页面查看记录效果
+        </template>
+      </a-alert>
 
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <el-card shadow="hover">
-            <template #header>GET 请求测试</template>
-            
-            <el-space direction="vertical" fill style="width: 100%">
-              <el-button type="danger" @click="testError('runtime')" :loading="loading.runtime">
+      <a-row :gutter="20">
+        <a-col :span="12">
+          <a-card title="GET 请求测试" :hoverable="true">
+            <a-space direction="vertical" :size="16" style="width: 100%">
+              <a-button type="primary" danger block @click="testError('runtime')" :loading="loading.runtime">
                 运行时异常
-              </el-button>
+              </a-button>
               
-              <el-button type="danger" @click="testError('nullPointer')" :loading="loading.nullPointer">
+              <a-button type="primary" danger block @click="testError('nullPointer')" :loading="loading.nullPointer">
                 空指针异常
-              </el-button>
+              </a-button>
               
-              <el-button type="danger" @click="testError('arrayIndex')" :loading="loading.arrayIndex">
+              <a-button type="primary" danger block @click="testError('arrayIndex')" :loading="loading.arrayIndex">
                 数组越界异常
-              </el-button>
+              </a-button>
               
-              <el-button type="danger" @click="testError('divideByZero')" :loading="loading.divideByZero">
+              <a-button type="primary" danger block @click="testError('divideByZero')" :loading="loading.divideByZero">
                 除零异常
-              </el-button>
-            </el-space>
-          </el-card>
-        </el-col>
+              </a-button>
+            </a-space>
+          </a-card>
+        </a-col>
         
-        <el-col :span="12">
-          <el-card shadow="hover">
-            <template #header>自定义错误测试</template>
-            
-            <el-form :model="customForm" label-width="80px">
-              <el-form-item label="错误类型">
-                <el-select v-model="customForm.errorType" style="width: 100%">
-                  <el-option label="业务错误" value="BUSINESS" />
-                  <el-option label="系统错误" value="SYSTEM" />
-                  <el-option label="API错误" value="API" />
-                </el-select>
-              </el-form-item>
-              <el-form-item label="错误消息">
-                <el-input v-model="customForm.errorMessage" placeholder="请输入错误消息" />
-              </el-form-item>
-              <el-form-item>
-                <el-button type="danger" @click="testCustomError" :loading="loading.custom">
+        <a-col :span="12">
+          <a-card title="自定义错误测试" :hoverable="true">
+            <a-form :model="customForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+              <a-form-item label="错误类型">
+                <a-select v-model:value="customForm.errorType" style="width: 100%">
+                  <a-select-option value="BUSINESS">业务错误</a-select-option>
+                  <a-select-option value="SYSTEM">系统错误</a-select-option>
+                  <a-select-option value="API">API错误</a-select-option>
+                </a-select>
+              </a-form-item>
+              <a-form-item label="错误消息">
+                <a-input v-model:value="customForm.errorMessage" placeholder="请输入错误消息" />
+              </a-form-item>
+              <a-form-item :wrapper-col="{ offset: 6, span: 16 }">
+                <a-button type="primary" danger @click="testCustomError" :loading="loading.custom">
                   触发自定义错误
-                </el-button>
-              </el-form-item>
-            </el-form>
-          </el-card>
+                </a-button>
+              </a-form-item>
+            </a-form>
+          </a-card>
           
-          <el-card shadow="hover" style="margin-top: 20px;">
-            <template #header>POST 请求测试(带JSON Body)</template>
-            
-            <el-form :model="postForm" label-width="80px">
-              <el-form-item label="消息内容">
-                <el-input v-model="postForm.message" placeholder="请输入消息" />
-              </el-form-item>
-              <el-form-item>
-                <el-button type="danger" @click="testPostError" :loading="loading.post">
+          <a-card title="POST 请求测试(带JSON Body)" :hoverable="true" style="margin-top: 20px;">
+            <a-form :model="postForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+              <a-form-item label="消息内容">
+                <a-input v-model:value="postForm.message" placeholder="请输入消息" />
+              </a-form-item>
+              <a-form-item :wrapper-col="{ offset: 6, span: 16 }">
+                <a-button type="primary" danger @click="testPostError" :loading="loading.post">
                   触发POST错误
-                </el-button>
-              </el-form-item>
-            </el-form>
-          </el-card>
-        </el-col>
-      </el-row>
+                </a-button>
+              </a-form-item>
+            </a-form>
+          </a-card>
+        </a-col>
+      </a-row>
 
-      <el-divider />
+      <a-divider />
 
-      <el-button type="primary" @click="goToErrorLog">
-        <el-icon><View /></el-icon>
+      <a-button type="primary" @click="goToErrorLog">
+        <EyeOutlined />
         查看错误日志
-      </el-button>
-    </el-card>
+      </a-button>
+    </a-card>
   </div>
 </template>
 
@@ -155,8 +149,8 @@ function goToErrorLog() {
 }
 </script>
 
-<style scoped>
-.el-button {
+<style lang="scss" scoped>
+.ant-btn {
   width: 100%;
 }
 </style>

+ 281 - 236
yushu-uivue3/src/views/monitor/job/index.vue

@@ -1,133 +1,148 @@
 <template>
    <div class="app-container">
-      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
-         <el-form-item label="任务名称" prop="jobName">
-            <el-input
-               v-model="queryParams.jobName"
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
+         <a-form-item label="任务名称" name="jobName">
+            <a-input
+               v-model:value="queryParams.jobName"
                placeholder="请输入任务名称"
-               clearable
+               allowClear
                style="width: 200px"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="任务组名" prop="jobGroup">
-            <el-select v-model="queryParams.jobGroup" placeholder="请选择任务组名" clearable style="width: 200px">
-               <el-option
+         </a-form-item>
+         <a-form-item label="任务组名" name="jobGroup">
+            <a-select v-model:value="queryParams.jobGroup" placeholder="请选择任务组名" allowClear style="width: 200px">
+               <a-select-option
                   v-for="dict in sys_job_group"
                   :key="dict.value"
-                  :label="dict.label"
                   :value="dict.value"
-               />
-            </el-select>
-         </el-form-item>
-         <el-form-item label="任务状态" prop="status">
-            <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable style="width: 200px">
-               <el-option
+               >{{ dict.label }}</a-select-option>
+            </a-select>
+         </a-form-item>
+         <a-form-item label="任务状态" name="status">
+            <a-select v-model:value="queryParams.status" placeholder="请选择任务状态" allowClear style="width: 200px">
+               <a-select-option
                   v-for="dict in sys_job_status"
                   :key="dict.value"
-                  :label="dict.label"
                   :value="dict.value"
-               />
-            </el-select>
-         </el-form-item>
-         <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-         </el-form-item>
-      </el-form>
-
-      <el-row :gutter="10" class="mb8">
-         <el-col :span="1.5">
-            <el-button
+               >{{ dict.label }}</a-select-option>
+            </a-select>
+         </a-form-item>
+         <a-form-item>
+            <a-button type="primary" @click="handleQuery">
+               <template #icon><SearchOutlined /></template>
+               搜索
+            </a-button>
+            <a-button @click="resetQuery" style="margin-left: 8px">
+               <template #icon><ReloadOutlined /></template>
+               重置
+            </a-button>
+         </a-form-item>
+      </a-form>
+
+      <a-row :gutter="10" class="mb8 button-toolbar">
+         <a-col :span="1.5">
+            <a-button
                type="primary"
-               plain
-               icon="Plus"
                @click="handleAdd"
                v-hasPermi="['monitor:job:add']"
-            >新增</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="success"
-               plain
-               icon="Edit"
+            >
+               <template #icon><PlusOutlined /></template>
+               新增
+            </a-button>
+         </a-col>
+         <a-col :span="1.5">
+            <a-button
+               type="primary"
                :disabled="single"
                @click="handleUpdate"
                v-hasPermi="['monitor:job:edit']"
-            >修改</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="danger"
-               plain
-               icon="Delete"
+            >
+               <template #icon><EditOutlined /></template>
+               修改
+            </a-button>
+         </a-col>
+         <a-col :span="1.5">
+            <a-button
+               danger
                :disabled="multiple"
                @click="handleDelete"
                v-hasPermi="['monitor:job:remove']"
-            >删除</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="warning"
-               plain
-               icon="Download"
+            >
+               <template #icon><DeleteOutlined /></template>
+               删除
+            </a-button>
+         </a-col>
+         <a-col :span="1.5">
+            <a-button
                @click="handleExport"
                v-hasPermi="['monitor:job:export']"
-            >导出</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="info"
-               plain
-               icon="Operation"
+            >
+               <template #icon><DownloadOutlined /></template>
+               导出
+            </a-button>
+         </a-col>
+         <a-col :span="1.5">
+            <a-button
                @click="handleJobLog"
                v-hasPermi="['monitor:job:query']"
-            >日志</el-button>
-         </el-col>
+            >
+               <template #icon><ToolOutlined /></template>
+               日志
+            </a-button>
+         </a-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </el-row>
-
-      <el-table v-loading="loading" :data="jobList" @selection-change="handleSelectionChange">
-         <el-table-column type="selection" width="55" align="center" />
-         <el-table-column label="任务编号" width="100" align="center" prop="jobId" />
-         <el-table-column label="任务名称" align="center" prop="jobName" :show-overflow-tooltip="true" />
-         <el-table-column label="任务组名" align="center" prop="jobGroup">
-            <template #default="scope">
-               <dict-tag :options="sys_job_group" :value="scope.row.jobGroup" />
+      </a-row>
+
+      <a-table 
+         :loading="loading" 
+         :data-source="jobList" 
+         :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+         :row-key="record => record.jobId"
+         :columns="tableColumns"
+         :pagination="false"
+      >
+         <template #bodyCell="{ column, record }">
+            <template v-if="column.key === 'jobGroup'">
+               <dict-tag :options="sys_job_group" :value="record.jobGroup" />
             </template>
-         </el-table-column>
-         <el-table-column label="调用目标字符串" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />
-         <el-table-column label="cron执行表达式" align="center" prop="cronExpression" :show-overflow-tooltip="true" />
-         <el-table-column label="状态" align="center">
-            <template #default="scope">
-               <el-switch
-                  v-model="scope.row.status"
-                  active-value="0"
-                  inactive-value="1"
-                  @change="handleStatusChange(scope.row)"
-               ></el-switch>
+            <template v-else-if="column.key === 'status'">
+               <a-switch
+                  v-model:checked="record.status"
+                  checkedValue="0"
+                  unCheckedValue="1"
+                  @change="handleStatusChange(record)"
+               />
             </template>
-         </el-table-column>
-         <el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
-            <template #default="scope">
-               <el-tooltip content="修改" placement="top">
-                  <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['monitor:job:edit']"></el-button>
-               </el-tooltip>
-               <el-tooltip content="删除" placement="top">
-                  <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['monitor:job:remove']"></el-button>
-               </el-tooltip>
-               <el-tooltip content="执行一次" placement="top">
-                  <el-button link type="primary" icon="CaretRight" @click="handleRun(scope.row)" v-hasPermi="['monitor:job:changeStatus']"></el-button>
-               </el-tooltip>
-               <el-tooltip content="任务详细" placement="top">
-                  <el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['monitor:job:query']"></el-button>
-               </el-tooltip>
-               <el-tooltip content="调度日志" placement="top">
-                  <el-button link type="primary" icon="Operation" @click="handleJobLog(scope.row)" v-hasPermi="['monitor:job:query']"></el-button>
-               </el-tooltip>
+            <template v-else-if="column.key === 'action'">
+               <a-tooltip title="修改">
+                  <a-button type="link" @click="handleUpdate(record)" v-hasPermi="['monitor:job:edit']">
+                     <template #icon><EditOutlined /></template>
+                  </a-button>
+               </a-tooltip>
+               <a-tooltip title="删除">
+                  <a-button type="link" danger @click="handleDelete(record)" v-hasPermi="['monitor:job:remove']">
+                     <template #icon><DeleteOutlined /></template>
+                  </a-button>
+               </a-tooltip>
+               <a-tooltip title="执行一次">
+                  <a-button type="link" @click="handleRun(record)" v-hasPermi="['monitor:job:changeStatus']">
+                     <template #icon><CaretRightOutlined /></template>
+                  </a-button>
+               </a-tooltip>
+               <a-tooltip title="任务详细">
+                  <a-button type="link" @click="handleView(record)" v-hasPermi="['monitor:job:query']">
+                     <template #icon><EyeOutlined /></template>
+                  </a-button>
+               </a-tooltip>
+               <a-tooltip title="调度日志">
+                  <a-button type="link" @click="handleJobLog(record)" v-hasPermi="['monitor:job:query']">
+                     <template #icon><ToolOutlined /></template>
+                  </a-button>
+               </a-tooltip>
             </template>
-         </el-table-column>
-      </el-table>
+         </template>
+      </a-table>
 
       <pagination
          v-show="total > 0"
@@ -138,149 +153,143 @@
       />
 
       <!-- 添加或修改定时任务对话框 -->
-      <el-dialog :title="title" v-model="open" width="820px" append-to-body>
-         <el-form ref="jobRef" :model="form" :rules="rules" label-width="120px">
-            <el-row>
-               <el-col :span="12">
-                  <el-form-item label="任务名称" prop="jobName">
-                     <el-input v-model="form.jobName" placeholder="请输入任务名称" />
-                  </el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="任务分组" prop="jobGroup">
-                     <el-select v-model="form.jobGroup" placeholder="请选择">
-                        <el-option
+      <a-modal :title="title" v-model:open="open" width="820px" :footer="null">
+         <a-form ref="jobRef" :model="form" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+            <a-row :gutter="16">
+               <a-col :span="12">
+                  <a-form-item label="任务名称" name="jobName">
+                     <a-input v-model:value="form.jobName" placeholder="请输入任务名称" />
+                  </a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="任务分组" name="jobGroup">
+                     <a-select v-model:value="form.jobGroup" placeholder="请选择">
+                        <a-select-option
                            v-for="dict in sys_job_group"
                            :key="dict.value"
-                           :label="dict.label"
                            :value="dict.value"
-                        ></el-option>
-                     </el-select>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item prop="invokeTarget">
+                        >{{ dict.label }}</a-select-option>
+                     </a-select>
+                  </a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item name="invokeTarget">
                      <template #label>
                         <span>
                            调用方法
-                           <el-tooltip placement="top">
-                              <template #content>
+                           <a-tooltip placement="top">
+                              <template #title>
                                  <div>
                                     Bean调用示例:ryTask.ryParams('ry')
                                     <br />Class类调用示例:com.yushu.quartz.task.RyTask.ryParams('ry')
                                     <br />参数说明:支持字符串,布尔类型,长整型,浮点型,整型
                                  </div>
                               </template>
-                              <el-icon><question-filled /></el-icon>
-                           </el-tooltip>
+                              <QuestionCircleOutlined style="margin-left: 4px" />
+                           </a-tooltip>
                         </span>
                      </template>
-                     <el-input v-model="form.invokeTarget" placeholder="请输入调用目标字符串" />
-                  </el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="cron表达式" prop="cronExpression">
-                     <el-input v-model="form.cronExpression" placeholder="请输入cron执行表达式">
-                        <template #append>
-                           <el-button type="primary" @click="handleShowCron">
-                              生成表达式
-                              <i class="el-icon-time el-icon--right"></i>
-                           </el-button>
-                        </template>
-                     </el-input>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="24" v-if="form.jobId !== undefined">
-                  <el-form-item label="状态">
-                     <el-radio-group v-model="form.status">
-                        <el-radio
+                     <a-input v-model:value="form.invokeTarget" placeholder="请输入调用目标字符串" />
+                  </a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="cron表达式" name="cronExpression">
+                     <a-input-group compact>
+                        <a-input v-model:value="form.cronExpression" placeholder="请输入cron执行表达式" style="width: calc(100% - 120px)" />
+                        <a-button type="primary" @click="handleShowCron">
+                           生成表达式
+                           <template #icon><ClockCircleOutlined /></template>
+                        </a-button>
+                     </a-input-group>
+                  </a-form-item>
+               </a-col>
+               <a-col :span="24" v-if="form.jobId !== undefined">
+                  <a-form-item label="状态">
+                     <a-radio-group v-model:value="form.status">
+                        <a-radio
                            v-for="dict in sys_job_status"
                            :key="dict.value"
                            :value="dict.value"
-                        >{{ dict.label }}</el-radio>
-                     </el-radio-group>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="执行策略" prop="misfirePolicy">
-                     <el-radio-group v-model="form.misfirePolicy">
-                        <el-radio-button value="1">立即执行</el-radio-button>
-                        <el-radio-button value="2">执行一次</el-radio-button>
-                        <el-radio-button value="3">放弃执行</el-radio-button>
-                     </el-radio-group>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="是否并发" prop="concurrent">
-                     <el-radio-group v-model="form.concurrent">
-                        <el-radio-button value="0">允许</el-radio-button>
-                        <el-radio-button value="1">禁止</el-radio-button>
-                     </el-radio-group>
-                  </el-form-item>
-               </el-col>
-            </el-row>
-         </el-form>
-         <template #footer>
-            <div class="dialog-footer">
-               <el-button type="primary" @click="submitForm">确 定</el-button>
-               <el-button @click="cancel">取 消</el-button>
-            </div>
-         </template>
-      </el-dialog>
+                        >{{ dict.label }}</a-radio>
+                     </a-radio-group>
+                  </a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="执行策略" name="misfirePolicy">
+                     <a-radio-group v-model:value="form.misfirePolicy" button-style="solid">
+                        <a-radio-button value="1">立即执行</a-radio-button>
+                        <a-radio-button value="2">执行一次</a-radio-button>
+                        <a-radio-button value="3">放弃执行</a-radio-button>
+                     </a-radio-group>
+                  </a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="是否并发" name="concurrent">
+                     <a-radio-group v-model:value="form.concurrent" button-style="solid">
+                        <a-radio-button value="0">允许</a-radio-button>
+                        <a-radio-button value="1">禁止</a-radio-button>
+                     </a-radio-group>
+                  </a-form-item>
+               </a-col>
+            </a-row>
+         </a-form>
+         <div class="dialog-footer" style="text-align: right; margin-top: 16px;">
+            <a-button type="primary" @click="submitForm">确 定</a-button>
+            <a-button style="margin-left: 8px" @click="cancel">取 消</a-button>
+         </div>
+      </a-modal>
 
-     <el-dialog title="Cron表达式生成器" v-model="openCron" append-to-body destroy-on-close>
+     <a-modal title="Cron表达式生成器" v-model:open="openCron" :footer="null" destroyOnClose>
        <crontab ref="crontabRef" @hide="openCron=false" @fill="crontabFill" :expression="expression"></crontab>
-     </el-dialog>
+     </a-modal>
 
       <!-- 任务日志详细 -->
-      <el-dialog title="任务详细" v-model="openView" width="700px" append-to-body>
-         <el-form :model="form" label-width="120px">
-            <el-row>
-               <el-col :span="12">
-                  <el-form-item label="任务编号:">{{ form.jobId }}</el-form-item>
-                  <el-form-item label="任务名称:">{{ form.jobName }}</el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="任务分组:">{{ jobGroupFormat(form) }}</el-form-item>
-                  <el-form-item label="创建时间:">{{ form.createTime }}</el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="下次执行时间:">{{ parseTime(form.nextValidTime) }}</el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="调用目标方法:">{{ form.invokeTarget }}</el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="任务状态:">
+      <a-modal title="任务详细" v-model:open="openView" width="700px" :footer="null">
+         <a-form :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
+            <a-row :gutter="16">
+               <a-col :span="12">
+                  <a-form-item label="任务编号:">{{ form.jobId }}</a-form-item>
+                  <a-form-item label="任务名称:">{{ form.jobName }}</a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="任务分组:">{{ jobGroupFormat(form) }}</a-form-item>
+                  <a-form-item label="创建时间:">{{ form.createTime }}</a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="cron表达式:">{{ form.cronExpression }}</a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="下次执行时间:">{{ parseTime(form.nextValidTime) }}</a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="调用目标方法:">{{ form.invokeTarget }}</a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="任务状态:">
                      <div v-if="form.status == 0">正常</div>
                      <div v-else-if="form.status == 1">暂停</div>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="是否并发:">
+                  </a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="是否并发:">
                      <div v-if="form.concurrent == 0">允许</div>
                      <div v-else-if="form.concurrent == 1">禁止</div>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="执行策略:">
+                  </a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="执行策略:">
                      <div v-if="form.misfirePolicy == 0">默认策略</div>
                      <div v-else-if="form.misfirePolicy == 1">立即执行</div>
                      <div v-else-if="form.misfirePolicy == 2">执行一次</div>
                      <div v-else-if="form.misfirePolicy == 3">放弃执行</div>
-                  </el-form-item>
-               </el-col>
-            </el-row>
-         </el-form>
-         <template #footer>
-            <div class="dialog-footer">
-               <el-button @click="openView = false">关 闭</el-button>
-            </div>
-         </template>
-      </el-dialog>
+                  </a-form-item>
+               </a-col>
+            </a-row>
+         </a-form>
+         <div class="dialog-footer" style="text-align: right; margin-top: 16px;">
+            <a-button @click="openView = false">关 闭</a-button>
+         </div>
+      </a-modal>
    </div>
 </template>
 
@@ -322,6 +331,18 @@ const data = reactive({
 })
 
 const { queryParams, form, rules } = toRefs(data)
+const selectedRowKeys = ref([])
+
+// 表格列配置
+const tableColumns = [
+  { title: '任务编号', dataIndex: 'jobId', key: 'jobId', width: 100, align: 'center' },
+  { title: '任务名称', dataIndex: 'jobName', key: 'jobName', align: 'center', ellipsis: true },
+  { title: '任务组名', dataIndex: 'jobGroup', key: 'jobGroup', align: 'center' },
+  { title: '调用目标字符串', dataIndex: 'invokeTarget', key: 'invokeTarget', align: 'center', ellipsis: true },
+  { title: 'cron执行表达式', dataIndex: 'cronExpression', key: 'cronExpression', align: 'center', ellipsis: true },
+  { title: '状态', key: 'status', align: 'center' },
+  { title: '操作', key: 'action', align: 'center', width: 200 }
+]
 
 /** 查询定时任务列表 */
 function getList() {
@@ -372,10 +393,11 @@ function resetQuery() {
 }
 
 // 多选框选中数据
-function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.jobId)
-  single.value = selection.length != 1
-  multiple.value = !selection.length
+function handleSelectionChange(selectedKeys, selectedRows) {
+  selectedRowKeys.value = selectedKeys
+  ids.value = selectedRows.map(item => item.jobId)
+  single.value = selectedRows.length != 1
+  multiple.value = !selectedRows.length
 }
 
 // 更多操作触发
@@ -404,6 +426,11 @@ function handleStatusChange(row) {
     proxy.$modal.msgSuccess(text + "成功")
   }).catch(function () {
     row.status = row.status === "0" ? "1" : "0"
+    // 更新表格显示
+    const index = jobList.value.findIndex(item => item.jobId === row.jobId)
+    if (index > -1) {
+      jobList.value[index].status = row.status
+    }
   })
 }
 
@@ -461,23 +488,21 @@ function handleUpdate(row) {
 
 /** 提交按钮 */
 function submitForm() {
-  proxy.$refs["jobRef"].validate(valid => {
-    if (valid) {
-      if (form.value.jobId != undefined) {
-        updateJob(form.value).then(response => {
-          proxy.$modal.msgSuccess("修改成功")
-          open.value = false
-          getList()
-        })
-      } else {
-        addJob(form.value).then(response => {
-          proxy.$modal.msgSuccess("新增成功")
-          open.value = false
-          getList()
-        })
-      }
+  proxy.$refs["jobRef"].validateFields().then(() => {
+    if (form.value.jobId != undefined) {
+      updateJob(form.value).then(response => {
+        proxy.$modal.msgSuccess("修改成功")
+        open.value = false
+        getList()
+      })
+    } else {
+      addJob(form.value).then(response => {
+        proxy.$modal.msgSuccess("新增成功")
+        open.value = false
+        getList()
+      })
     }
-  })
+  }).catch(() => {})
 }
 
 /** 删除按钮操作 */
@@ -500,3 +525,23 @@ function handleExport() {
 
 getList()
 </script>
+
+<style scoped>
+.search-form {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+
+.button-toolbar {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+
+.ant-table-wrapper {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+</style>

+ 212 - 109
yushu-uivue3/src/views/monitor/logininfor/index.vue

@@ -1,118 +1,108 @@
 <template>
    <div class="app-container">
-      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
-         <el-form-item label="登录地址" prop="ipaddr">
-            <el-input
-               v-model="queryParams.ipaddr"
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
+         <a-form-item label="登录地址" name="ipaddr">
+            <a-input
+               v-model:value="queryParams.ipaddr"
                placeholder="请输入登录地址"
-               clearable
+               allow-clear
                style="width: 240px;"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="用户名称" prop="userName">
-            <el-input
-               v-model="queryParams.userName"
+         </a-form-item>
+         <a-form-item label="用户名称" name="userName">
+            <a-input
+               v-model:value="queryParams.userName"
                placeholder="请输入用户名称"
-               clearable
+               allow-clear
                style="width: 240px;"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="状态" prop="status">
-            <el-select
-               v-model="queryParams.status"
+         </a-form-item>
+         <a-form-item label="状态" name="status">
+            <a-select
+               v-model:value="queryParams.status"
                placeholder="登录状态"
-               clearable
+               allow-clear
                style="width: 240px"
             >
-               <el-option
+               <a-select-option
                   v-for="dict in sys_common_status"
                   :key="dict.value"
-                  :label="dict.label"
                   :value="dict.value"
-               />
-            </el-select>
-         </el-form-item>
-         <el-form-item label="登录时间" style="width: 308px">
-            <el-date-picker
-               v-model="dateRange"
+               >{{ dict.label }}</a-select-option>
+            </a-select>
+         </a-form-item>
+         <a-form-item label="登录时间">
+            <a-range-picker
+               v-model:value="dateRange"
                value-format="YYYY-MM-DD HH:mm:ss"
-               type="daterange"
-               range-separator="-"
-               start-placeholder="开始日期"
-               end-placeholder="结束日期"
-               :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-            ></el-date-picker>
-         </el-form-item>
-         <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-         </el-form-item>
-      </el-form>
-
-      <el-row :gutter="10" class="mb8">
-         <el-col :span="1.5">
-            <el-button
-               type="danger"
-               plain
-               icon="Delete"
-               :disabled="multiple"
-               @click="handleDelete"
-               v-hasPermi="['monitor:logininfor:remove']"
-            >删除</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="danger"
-               plain
-               icon="Delete"
-               @click="handleClean"
-               v-hasPermi="['monitor:logininfor:remove']"
-            >清空</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="primary"
-               plain
-               icon="Unlock"
-               :disabled="single"
-               @click="handleUnlock"
-               v-hasPermi="['monitor:logininfor:unlock']"
-            >解锁</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="warning"
-               plain
-               icon="Download"
-               @click="handleExport"
-               v-hasPermi="['monitor:logininfor:export']"
-            >导出</el-button>
-         </el-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </el-row>
-
-      <el-table ref="logininforRef" v-loading="loading" :data="logininforList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
-         <el-table-column type="selection" width="55" align="center" />
-         <el-table-column label="访问编号" align="center" prop="infoId" />
-         <el-table-column label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
-         <el-table-column label="地址" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-         <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
-         <el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
-         <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
-         <el-table-column label="登录状态" align="center" prop="status">
-            <template #default="scope">
-               <dict-tag :options="sys_common_status" :value="scope.row.status" />
+               show-time
+               style="width: 308px"
+            />
+         </a-form-item>
+         <a-form-item>
+            <a-button type="primary" @click="handleQuery"><SearchOutlined />搜索</a-button>
+            <a-button style="margin-left: 8px" @click="resetQuery"><ReloadOutlined />重置</a-button>
+         </a-form-item>
+      </a-form>
+
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button
+                  danger
+                  :disabled="multiple"
+                  @click="handleDelete"
+                  v-hasPermi="['monitor:logininfor:remove']"
+               ><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button
+                  danger
+                  @click="handleClean"
+                  v-hasPermi="['monitor:logininfor:remove']"
+               ><DeleteOutlined />清空</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button
+                  type="primary"
+                  style="background-color: #52c41a; border-color: #52c41a"
+                  :disabled="single"
+                  @click="handleUnlock"
+                  v-hasPermi="['monitor:logininfor:unlock']"
+               ><UnlockOutlined />解锁</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button
+                  type="primary"
+                  style="background-color: #faad14; border-color: #faad14"
+                  @click="handleExport"
+                  v-hasPermi="['monitor:logininfor:export']"
+               ><DownloadOutlined />导出</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
+
+      <a-table
+         :loading="loading"
+         :data-source="logininforList"
+         :columns="tableColumns"
+         :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+         :row-key="record => record.infoId"
+         :pagination="false"
+         @change="handleTableChange"
+      >
+         <template #bodyCell="{ column, record }">
+            <template v-if="column.key === 'status'">
+               <dict-tag :options="sys_common_status" :value="record.status" />
             </template>
-         </el-table-column>
-         <el-table-column label="描述" align="center" prop="msg" :show-overflow-tooltip="true" />
-         <el-table-column label="访问时间" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
-            <template #default="scope">
-               <span>{{ parseTime(scope.row.loginTime) }}</span>
+            <template v-else-if="column.key === 'loginTime'">
+               <span>{{ parseTime(record.loginTime) }}</span>
             </template>
-         </el-table-column>
-      </el-table>
+         </template>
+      </a-table>
 
       <pagination
          v-show="total > 0"
@@ -125,6 +115,7 @@
 </template>
 
 <script setup name="Logininfor">
+import { SearchOutlined, ReloadOutlined, DeleteOutlined, DownloadOutlined, UnlockOutlined } from '@ant-design/icons-vue'
 import { list, delLogininfor, cleanLogininfor, unlockLogininfor } from "@/api/monitor/logininfor"
 
 const { proxy } = getCurrentInstance()
@@ -133,6 +124,7 @@ const { sys_common_status } = proxy.useDict("sys_common_status")
 const logininforList = ref([])
 const loading = ref(true)
 const showSearch = ref(true)
+const selectedRowKeys = ref([])
 const ids = ref([])
 const single = ref(true)
 const multiple = ref(true)
@@ -152,6 +144,19 @@ const queryParams = ref({
   isAsc: undefined
 })
 
+// 表格列配置
+const tableColumns = [
+  { title: '访问编号', dataIndex: 'infoId', key: 'infoId', width: 100, align: 'center' },
+  { title: '用户名称', dataIndex: 'userName', key: 'userName', align: 'center', ellipsis: true },
+  { title: '地址', dataIndex: 'ipaddr', key: 'ipaddr', align: 'center', ellipsis: true },
+  { title: '登录地点', dataIndex: 'loginLocation', key: 'loginLocation', align: 'center', ellipsis: true },
+  { title: '操作系统', dataIndex: 'os', key: 'os', align: 'center', ellipsis: true },
+  { title: '浏览器', dataIndex: 'browser', key: 'browser', align: 'center', ellipsis: true },
+  { title: '登录状态', key: 'status', width: 100, align: 'center' },
+  { title: '描述', dataIndex: 'msg', key: 'msg', align: 'center', ellipsis: true },
+  { title: '访问时间', key: 'loginTime', width: 180, align: 'center' }
+]
+
 /** 查询登录日志列表 */
 function getList() {
   loading.value = true
@@ -173,27 +178,32 @@ function resetQuery() {
   dateRange.value = []
   proxy.resetForm("queryRef")
   queryParams.value.pageNum = 1
-  proxy.$refs["logininforRef"].sort(defaultSort.value.prop, defaultSort.value.order)
+  queryParams.value.orderByColumn = defaultSort.value.prop
+  queryParams.value.isAsc = defaultSort.value.order === 'ascending' ? 'asc' : 'desc'
+  getList()
 }
 
 /** 多选框选中数据 */
-function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.infoId)
-  multiple.value = !selection.length
-  single.value = selection.length != 1
-  selectName.value = selection.map(item => item.userName)
+function handleSelectionChange(selectedKeys) {
+  selectedRowKeys.value = selectedKeys
+  ids.value = selectedKeys
+  multiple.value = !selectedKeys.length
+  single.value = selectedKeys.length != 1
+  selectName.value = logininforList.value.filter(item => selectedKeys.includes(item.infoId)).map(item => item.userName)
 }
 
-/** 排序触发事件 */
-function handleSortChange(column, prop, order) {
-  queryParams.value.orderByColumn = column.prop
-  queryParams.value.isAsc = column.order
+/** 表格变化事件 */
+function handleTableChange(pagination, filters, sorter) {
+  if (sorter && sorter.field) {
+    queryParams.value.orderByColumn = sorter.field
+    queryParams.value.isAsc = sorter.order === 'ascend' ? 'asc' : 'desc'
+  }
   getList()
 }
 
 /** 删除按钮操作 */
 function handleDelete(row) {
-  const infoIds = row.infoId || ids.value
+  const infoIds = row?.infoId || ids.value
   proxy.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?').then(function () {
     return delLogininfor(infoIds)
   }).then(() => {
@@ -231,3 +241,96 @@ function handleExport() {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 72 - 43
yushu-uivue3/src/views/monitor/online/index.vue

@@ -1,64 +1,65 @@
 <template>
    <div class="app-container">
-      <el-form :model="queryParams" ref="queryRef" :inline="true">
-         <el-form-item label="登录地址" prop="ipaddr">
-            <el-input
-               v-model="queryParams.ipaddr"
+      <a-form :model="queryParams" ref="queryRef" layout="inline" class="search-form">
+         <a-form-item label="登录地址" name="ipaddr">
+            <a-input
+               v-model:value="queryParams.ipaddr"
                placeholder="请输入登录地址"
-               clearable
+               allowClear
                style="width: 200px"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="用户名称" prop="userName">
-            <el-input
-               v-model="queryParams.userName"
+         </a-form-item>
+         <a-form-item label="用户名称" name="userName">
+            <a-input
+               v-model:value="queryParams.userName"
                placeholder="请输入用户名称"
-               clearable
+               allowClear
                style="width: 200px"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-         </el-form-item>
-      </el-form>
-      <el-table
-         v-loading="loading"
-         :data="onlineList.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
-         style="width: 100%;"
+         </a-form-item>
+         <a-form-item>
+            <a-button type="primary" @click="handleQuery">
+               <template #icon><SearchOutlined /></template>
+               搜索
+            </a-button>
+            <a-button @click="resetQuery" style="margin-left: 8px">
+               <template #icon><ReloadOutlined /></template>
+               重置
+            </a-button>
+         </a-form-item>
+      </a-form>
+      <a-table
+         :loading="loading"
+         :data-source="onlineList"
+         :columns="tableColumns"
+         :pagination="false"
+         :row-key="record => record.tokenId"
       >
-         <el-table-column label="序号" width="50" type="index" align="center">
-            <template #default="scope">
-               <span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
+         <template #bodyCell="{ column, record, index }">
+            <template v-if="column.key === 'index'">
+               <span>{{ (pageNum - 1) * pageSize + index + 1 }}</span>
             </template>
-         </el-table-column>
-         <el-table-column label="会话编号" align="center" prop="tokenId" :show-overflow-tooltip="true" />
-         <el-table-column label="登录名称" align="center" prop="userName" :show-overflow-tooltip="true" />
-         <el-table-column label="所属部门" align="center" prop="deptName" :show-overflow-tooltip="true" />
-         <el-table-column label="主机" align="center" prop="ipaddr" :show-overflow-tooltip="true" />
-         <el-table-column label="登录地点" align="center" prop="loginLocation" :show-overflow-tooltip="true" />
-         <el-table-column label="操作系统" align="center" prop="os" :show-overflow-tooltip="true" />
-         <el-table-column label="浏览器" align="center" prop="browser" :show-overflow-tooltip="true" />
-         <el-table-column label="登录时间" align="center" prop="loginTime" width="180">
-            <template #default="scope">
-               <span>{{ parseTime(scope.row.loginTime) }}</span>
+            <template v-else-if="column.key === 'loginTime'">
+               <span>{{ parseTime(record.loginTime) }}</span>
             </template>
-         </el-table-column>
-         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-            <template #default="scope">
-               <el-button link type="primary" icon="Delete" @click="handleForceLogout(scope.row)" v-hasPermi="['monitor:online:forceLogout']">强退</el-button>
+            <template v-else-if="column.key === 'action'">
+               <a-button type="link" danger @click="handleForceLogout(record)" v-hasPermi="['monitor:online:forceLogout']">
+                  <template #icon><DeleteOutlined /></template>
+                  强退
+               </a-button>
             </template>
-         </el-table-column>
-      </el-table>
+         </template>
+      </a-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="pageNum" v-model:limit="pageSize" />
+      <pagination v-show="total > 0" :total="total" v-model:page="pageNum" v-model:limit="pageSize" @pagination="getList" />
    </div>
 </template>
 
 <script setup name="Online">
 import { forceLogout, list as initData } from "@/api/monitor/online"
+import { SearchOutlined, ReloadOutlined, DeleteOutlined } from '@ant-design/icons-vue'
 
 const { proxy } = getCurrentInstance()
 
@@ -68,6 +69,20 @@ const total = ref(0)
 const pageNum = ref(1)
 const pageSize = ref(10)
 
+// 表格列配置
+const tableColumns = [
+  { title: '序号', key: 'index', width: 50, align: 'center' },
+  { title: '会话编号', dataIndex: 'tokenId', key: 'tokenId', align: 'center', ellipsis: true },
+  { title: '登录名称', dataIndex: 'userName', key: 'userName', align: 'center', ellipsis: true },
+  { title: '所属部门', dataIndex: 'deptName', key: 'deptName', align: 'center', ellipsis: true },
+  { title: '主机', dataIndex: 'ipaddr', key: 'ipaddr', align: 'center', ellipsis: true },
+  { title: '登录地点', dataIndex: 'loginLocation', key: 'loginLocation', align: 'center', ellipsis: true },
+  { title: '操作系统', dataIndex: 'os', key: 'os', align: 'center', ellipsis: true },
+  { title: '浏览器', dataIndex: 'browser', key: 'browser', align: 'center', ellipsis: true },
+  { title: '登录时间', key: 'loginTime', align: 'center', width: 180 },
+  { title: '操作', key: 'action', align: 'center' }
+]
+
 const queryParams = ref({
   ipaddr: undefined,
   userName: undefined
@@ -107,3 +122,17 @@ function handleForceLogout(row) {
 
 getList()
 </script>
+
+<style scoped>
+.search-form {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+
+.ant-table-wrapper {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+</style>

+ 260 - 161
yushu-uivue3/src/views/monitor/operlog/index.vue

@@ -1,144 +1,131 @@
 <template>
    <div class="app-container">
-      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
-         <el-form-item label="操作地址" prop="operIp">
-            <el-input
-               v-model="queryParams.operIp"
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
+         <a-form-item label="操作地址" name="operIp">
+            <a-input
+               v-model:value="queryParams.operIp"
                placeholder="请输入操作地址"
-               clearable
+               allow-clear
                style="width: 240px;"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="系统模块" prop="title">
-            <el-input
-               v-model="queryParams.title"
+         </a-form-item>
+         <a-form-item label="系统模块" name="title">
+            <a-input
+               v-model:value="queryParams.title"
                placeholder="请输入系统模块"
-               clearable
+               allow-clear
                style="width: 240px;"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="操作人员" prop="operName">
-            <el-input
-               v-model="queryParams.operName"
+         </a-form-item>
+         <a-form-item label="操作人员" name="operName">
+            <a-input
+               v-model:value="queryParams.operName"
                placeholder="请输入操作人员"
-               clearable
+               allow-clear
                style="width: 240px;"
-               @keyup.enter="handleQuery"
+               @pressEnter="handleQuery"
             />
-         </el-form-item>
-         <el-form-item label="类型" prop="businessType">
-            <el-select
-               v-model="queryParams.businessType"
+         </a-form-item>
+         <a-form-item label="类型" name="businessType">
+            <a-select
+               v-model:value="queryParams.businessType"
                placeholder="操作类型"
-               clearable
+               allow-clear
                style="width: 240px"
             >
-               <el-option
+               <a-select-option
                   v-for="dict in sys_oper_type"
                   :key="dict.value"
-                  :label="dict.label"
                   :value="dict.value"
-               />
-            </el-select>
-         </el-form-item>
-         <el-form-item label="状态" prop="status">
-            <el-select
-               v-model="queryParams.status"
+               >{{ dict.label }}</a-select-option>
+            </a-select>
+         </a-form-item>
+         <a-form-item label="状态" name="status">
+            <a-select
+               v-model:value="queryParams.status"
                placeholder="操作状态"
-               clearable
+               allow-clear
                style="width: 240px"
             >
-               <el-option
+               <a-select-option
                   v-for="dict in sys_common_status"
                   :key="dict.value"
-                  :label="dict.label"
                   :value="dict.value"
-               />
-            </el-select>
-         </el-form-item>
-         <el-form-item label="操作时间" style="width: 308px">
-            <el-date-picker
-               v-model="dateRange"
+               >{{ dict.label }}</a-select-option>
+            </a-select>
+         </a-form-item>
+         <a-form-item label="操作时间">
+            <a-range-picker
+               v-model:value="dateRange"
                value-format="YYYY-MM-DD HH:mm:ss"
-               type="daterange"
-               range-separator="-"
-               start-placeholder="开始日期"
-               end-placeholder="结束日期"
-               :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
-            ></el-date-picker>
-         </el-form-item>
-         <el-form-item>
-            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-         </el-form-item>
-      </el-form>
+               show-time
+               style="width: 308px"
+            />
+         </a-form-item>
+         <a-form-item>
+            <a-button type="primary" @click="handleQuery"><SearchOutlined />搜索</a-button>
+            <a-button style="margin-left: 8px" @click="resetQuery"><ReloadOutlined />重置</a-button>
+         </a-form-item>
+      </a-form>
 
-      <el-row :gutter="10" class="mb8">
-         <el-col :span="1.5">
-            <el-button
-               type="danger"
-               plain
-               icon="Delete"
-               :disabled="multiple"
-               @click="handleDelete"
-               v-hasPermi="['monitor:operlog:remove']"
-            >删除</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="danger"
-               plain
-               icon="Delete"
-               @click="handleClean"
-               v-hasPermi="['monitor:operlog:remove']"
-            >清空</el-button>
-         </el-col>
-         <el-col :span="1.5">
-            <el-button
-               type="warning"
-               plain
-               icon="Download"
-               @click="handleExport"
-               v-hasPermi="['monitor:operlog:export']"
-            >导出</el-button>
-         </el-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </el-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button
+                  danger
+                  :disabled="multiple"
+                  @click="handleDelete"
+                  v-hasPermi="['monitor:operlog:remove']"
+               ><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button
+                  danger
+                  @click="handleClean"
+                  v-hasPermi="['monitor:operlog:remove']"
+               ><DeleteOutlined />清空</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button
+                  type="primary"
+                  style="background-color: #faad14; border-color: #faad14"
+                  @click="handleExport"
+                  v-hasPermi="['monitor:operlog:export']"
+               ><DownloadOutlined />导出</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
-      <el-table ref="operlogRef" v-loading="loading" :data="operlogList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
-         <el-table-column type="selection" width="50" align="center" />
-         <el-table-column label="日志编号" align="center" prop="operId" />
-         <el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" />
-         <el-table-column label="操作类型" align="center" prop="businessType">
-            <template #default="scope">
-               <dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
+      <a-table
+         :loading="loading"
+         :data-source="operlogList"
+         :columns="tableColumns"
+         :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+         :row-key="record => record.operId"
+         :pagination="false"
+         @change="handleTableChange"
+      >
+         <template #bodyCell="{ column, record }">
+            <template v-if="column.key === 'businessType'">
+               <dict-tag :options="sys_oper_type" :value="record.businessType" />
             </template>
-         </el-table-column>
-         <el-table-column label="操作人员" align="center" width="110" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
-         <el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
-         <el-table-column label="操作状态" align="center" prop="status">
-            <template #default="scope">
-               <dict-tag :options="sys_common_status" :value="scope.row.status" />
+            <template v-else-if="column.key === 'status'">
+               <dict-tag :options="sys_common_status" :value="record.status" />
             </template>
-         </el-table-column>
-         <el-table-column label="操作日期" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']">
-            <template #default="scope">
-               <span>{{ parseTime(scope.row.operTime) }}</span>
+            <template v-else-if="column.key === 'operTime'">
+               <span>{{ parseTime(record.operTime) }}</span>
             </template>
-         </el-table-column>
-         <el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
-            <template #default="scope">
-               <span>{{ scope.row.costTime }}毫秒</span>
+            <template v-else-if="column.key === 'costTime'">
+               <span>{{ record.costTime }}毫秒</span>
             </template>
-         </el-table-column>
-         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-            <template #default="scope">
-               <el-button link type="primary" icon="View" @click="handleView(scope.row, scope.index)" v-hasPermi="['monitor:operlog:query']">详细</el-button>
+            <template v-else-if="column.key === 'action'">
+               <a-button type="link" size="small" @click="handleView(record)" v-hasPermi="['monitor:operlog:query']"><EyeOutlined />详细</a-button>
             </template>
-         </el-table-column>
-      </el-table>
+         </template>
+      </a-table>
 
       <pagination
          v-show="total > 0"
@@ -149,55 +136,54 @@
       />
 
       <!-- 操作日志详细 -->
-      <el-dialog title="操作日志详细" v-model="open" width="800px" append-to-body>
-         <el-form :model="form" label-width="100px">
-            <el-row>
-               <el-col :span="12">
-                  <el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
-                  <el-form-item
-                    label="登录信息:"
-                  >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
-               </el-col>
-               <el-col :span="12">
-                  <el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
-                  <el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="操作方法:">{{ form.method }}</el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
-               </el-col>
-               <el-col :span="8">
-                  <el-form-item label="操作状态:">
+      <a-modal title="操作日志详细" v-model:open="open" width="800px" :footer="null">
+         <a-form :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+            <a-row>
+               <a-col :span="12">
+                  <a-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</a-form-item>
+                  <a-form-item label="登录信息:">{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</a-form-item>
+               </a-col>
+               <a-col :span="12">
+                  <a-form-item label="请求地址:">{{ form.operUrl }}</a-form-item>
+                  <a-form-item label="请求方式:">{{ form.requestMethod }}</a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="操作方法:">{{ form.method }}</a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="请求参数:">{{ form.operParam }}</a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="返回参数:">{{ form.jsonResult }}</a-form-item>
+               </a-col>
+               <a-col :span="8">
+                  <a-form-item label="操作状态:">
                      <div v-if="form.status === 0">正常</div>
                      <div v-else-if="form.status === 1">失败</div>
-                  </el-form-item>
-               </el-col>
-               <el-col :span="8">
-                  <el-form-item label="消耗时间:">{{ form.costTime }}毫秒</el-form-item>
-               </el-col>
-               <el-col :span="8">
-                  <el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
-               </el-col>
-               <el-col :span="24">
-                  <el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
-               </el-col>
-            </el-row>
-         </el-form>
+                  </a-form-item>
+               </a-col>
+               <a-col :span="8">
+                  <a-form-item label="消耗时间:">{{ form.costTime }}毫秒</a-form-item>
+               </a-col>
+               <a-col :span="8">
+                  <a-form-item label="操作时间:">{{ parseTime(form.operTime) }}</a-form-item>
+               </a-col>
+               <a-col :span="24">
+                  <a-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</a-form-item>
+               </a-col>
+            </a-row>
+         </a-form>
          <template #footer>
             <div class="dialog-footer">
-               <el-button @click="open = false">关 闭</el-button>
+               <a-button @click="open = false">关 闭</a-button>
             </div>
          </template>
-      </el-dialog>
+      </a-modal>
    </div>
 </template>
 
 <script setup name="Operlog">
+import { SearchOutlined, ReloadOutlined, DeleteOutlined, DownloadOutlined, EyeOutlined } from '@ant-design/icons-vue'
 import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog"
 
 const { proxy } = getCurrentInstance()
@@ -207,8 +193,8 @@ const operlogList = ref([])
 const open = ref(false)
 const loading = ref(true)
 const showSearch = ref(true)
+const selectedRowKeys = ref([])
 const ids = ref([])
-const single = ref(true)
 const multiple = ref(true)
 const total = ref(0)
 const title = ref("")
@@ -224,12 +210,27 @@ const data = reactive({
     title: undefined,
     operName: undefined,
     businessType: undefined,
-    status: undefined
+    status: undefined,
+    orderByColumn: undefined,
+    isAsc: undefined
   }
 })
 
 const { queryParams, form } = toRefs(data)
 
+// 表格列配置
+const tableColumns = [
+  { title: '日志编号', dataIndex: 'operId', key: 'operId', width: 100, align: 'center' },
+  { title: '系统模块', dataIndex: 'title', key: 'title', align: 'center', ellipsis: true },
+  { title: '操作类型', key: 'businessType', width: 120, align: 'center' },
+  { title: '操作人员', dataIndex: 'operName', key: 'operName', width: 110, align: 'center', ellipsis: true },
+  { title: '操作地址', dataIndex: 'operIp', key: 'operIp', width: 130, align: 'center', ellipsis: true },
+  { title: '操作状态', key: 'status', width: 100, align: 'center' },
+  { title: '操作日期', key: 'operTime', width: 180, align: 'center' },
+  { title: '消耗时间', key: 'costTime', width: 110, align: 'center', ellipsis: true },
+  { title: '操作', key: 'action', width: 100, align: 'center' }
+]
+
 /** 查询登录日志 */
 function getList() {
   loading.value = true
@@ -256,19 +257,24 @@ function resetQuery() {
   dateRange.value = []
   proxy.resetForm("queryRef")
   queryParams.value.pageNum = 1
-  proxy.$refs["operlogRef"].sort(defaultSort.value.prop, defaultSort.value.order)
+  queryParams.value.orderByColumn = defaultSort.value.prop
+  queryParams.value.isAsc = defaultSort.value.order === 'ascending' ? 'asc' : 'desc'
+  getList()
 }
 
 /** 多选框选中数据 */
-function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.operId)
-  multiple.value = !selection.length
+function handleSelectionChange(selectedKeys) {
+  selectedRowKeys.value = selectedKeys
+  ids.value = selectedKeys
+  multiple.value = !selectedKeys.length
 }
 
-/** 排序触发事件 */
-function handleSortChange(column, prop, order) {
-  queryParams.value.orderByColumn = column.prop
-  queryParams.value.isAsc = column.order
+/** 表格变化事件 */
+function handleTableChange(pagination, filters, sorter) {
+  if (sorter && sorter.field) {
+    queryParams.value.orderByColumn = sorter.field
+    queryParams.value.isAsc = sorter.order === 'ascend' ? 'asc' : 'desc'
+  }
   getList()
 }
 
@@ -280,7 +286,7 @@ function handleView(row) {
 
 /** 删除按钮操作 */
 function handleDelete(row) {
-  const operIds = row.operId || ids.value
+  const operIds = row?.operId || ids.value
   proxy.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?').then(function () {
     return delOperlog(operIds)
   }).then(() => {
@@ -303,8 +309,101 @@ function handleClean() {
 function handleExport() {
   proxy.download("monitor/operlog/export",{
     ...queryParams.value,
-  }, `config_${new Date().getTime()}.xlsx`)
+  }, `operlog_${new Date().getTime()}.xlsx`)
 }
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 16px;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 328 - 169
yushu-uivue3/src/views/monitor/server/index.vue

@@ -1,187 +1,346 @@
 <template>
   <div class="app-container">
-    <el-row :gutter="10">
-      <el-col :span="12" class="card-box">
-        <el-card>
-          <template #header><Cpu style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">CPU</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%;">
-              <thead>
-                <tr>
-                  <th class="el-table__cell is-leaf"><div class="cell">属性</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">值</div></th>
-                </tr>
-              </thead>
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">核心数</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">用户使用率</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">系统使用率</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">当前空闲率</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="12" class="card-box">
-        <el-card>
-          <template #header><Tickets style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">内存</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%;">
-              <thead>
-                <tr>
-                  <th class="el-table__cell is-leaf"><div class="cell">属性</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">内存</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">JVM</div></th>
-                </tr>
-              </thead>
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">总内存</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">已用内存</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">剩余内存</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">使用率</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="24" class="card-box">
-        <el-card>
-          <template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">服务器信息</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%;">
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">服务器名称</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">操作系统</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">服务器IP</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">系统架构</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="24" class="card-box">
-        <el-card>
-          <template #header><CoffeeCup style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">Java虚拟机信息</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%;table-layout:fixed;">
-              <tbody>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">Java名称</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">Java版本</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
-                </tr>
-                <tr>
-                  <td class="el-table__cell is-leaf"><div class="cell">启动时间</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">运行时长</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
-                </tr>
-                <tr>
-                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">安装路径</div></td>
-                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
-                </tr>
-                <tr>
-                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">项目路径</div></td>
-                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
-                </tr>
-                <tr>
-                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">运行参数</div></td>
-                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.inputArgs }}</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-
-      <el-col :span="24" class="card-box">
-        <el-card>
-          <template #header><MessageBox style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">磁盘状态</span></template>
-          <div class="el-table el-table--enable-row-hover el-table--medium">
-            <table cellspacing="0" style="width: 100%;">
-              <thead>
-                <tr>
-                  <th class="el-table__cell el-table__cell is-leaf"><div class="cell">盘符路径</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">文件系统</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">盘符类型</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">总大小</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">可用大小</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">已用大小</div></th>
-                  <th class="el-table__cell is-leaf"><div class="cell">已用百分比</div></th>
-                </tr>
-              </thead>
-              <tbody v-if="server.sysFiles">
-                <tr v-for="(sysFile, index) in server.sysFiles" :key="index">
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td>
-                  <td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+    <a-row :gutter="10">
+      <a-col :span="12" class="card-box">
+        <a-card>
+          <template #title>
+            <ThunderboltOutlined style="margin-right: 8px" />
+            <span>CPU</span>
+          </template>
+          <a-table 
+            :dataSource="cpuData" 
+            :columns="cpuColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="true"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="12" class="card-box">
+        <a-card>
+          <template #title>
+            <DatabaseOutlined style="margin-right: 8px" />
+            <span>内存</span>
+          </template>
+          <a-table 
+            :dataSource="memoryData" 
+            :columns="memoryColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="true"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="24" class="card-box">
+        <a-card>
+          <template #title>
+            <MonitorOutlined style="margin-right: 8px" />
+            <span>服务器信息</span>
+          </template>
+          <a-table 
+            :dataSource="serverInfoData" 
+            :columns="serverInfoColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="false"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="24" class="card-box">
+        <a-card>
+          <template #title>
+            <CodeOutlined style="margin-right: 8px" />
+            <span>Java虚拟机信息</span>
+          </template>
+          <a-table 
+            :dataSource="jvmData" 
+            :columns="jvmColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="false"
+          />
+        </a-card>
+      </a-col>
+
+      <a-col :span="24" class="card-box">
+        <a-card>
+          <template #title>
+            <InboxOutlined style="margin-right: 8px" />
+            <span>磁盘状态</span>
+          </template>
+          <a-table 
+            :dataSource="diskData" 
+            :columns="diskColumns" 
+            :pagination="false"
+            size="small"
+            :showHeader="true"
+          />
+        </a-card>
+      </a-col>
+    </a-row>
   </div>
 </template>
 
 <script setup>
+import { h } from 'vue'
 import { getServer } from '@/api/monitor/server'
+import { ThunderboltOutlined, DatabaseOutlined, MonitorOutlined, CodeOutlined, InboxOutlined } from '@ant-design/icons-vue'
+import { message } from 'ant-design-vue'
 
-const server = ref([])
+const server = ref({})
 const { proxy } = getCurrentInstance()
 
+// CPU 表格数据
+const cpuData = computed(() => {
+  if (!server.value.cpu) return []
+  return [
+    { key: '1', attr: '核心数', value: server.value.cpu.cpuNum },
+    { key: '2', attr: '用户使用率', value: `${server.value.cpu.used}%` },
+    { key: '3', attr: '系统使用率', value: `${server.value.cpu.sys}%` },
+    { key: '4', attr: '当前空闲率', value: `${server.value.cpu.free}%` }
+  ]
+})
+
+const cpuColumns = [
+  { title: '属性', dataIndex: 'attr', key: 'attr', width: '50%' },
+  { title: '值', dataIndex: 'value', key: 'value', width: '50%' }
+]
+
+// 内存表格数据
+const memoryData = computed(() => {
+  if (!server.value.mem || !server.value.jvm) return []
+  return [
+    { 
+      key: '1', 
+      attr: '总内存', 
+      memory: server.value.mem.total ? `${server.value.mem.total}G` : '-',
+      jvm: server.value.jvm.total ? `${server.value.jvm.total}M` : '-'
+    },
+    { 
+      key: '2', 
+      attr: '已用内存', 
+      memory: server.value.mem.used ? `${server.value.mem.used}G` : '-',
+      jvm: server.value.jvm.used ? `${server.value.jvm.used}M` : '-'
+    },
+    { 
+      key: '3', 
+      attr: '剩余内存', 
+      memory: server.value.mem.free ? `${server.value.mem.free}G` : '-',
+      jvm: server.value.jvm.free ? `${server.value.jvm.free}M` : '-'
+    },
+    { 
+      key: '4', 
+      attr: '使用率', 
+      memory: server.value.mem.usage ? `${server.value.mem.usage}%` : '-',
+      jvm: server.value.jvm.usage ? `${server.value.jvm.usage}%` : '-',
+      memoryDanger: server.value.mem.usage > 80,
+      jvmDanger: server.value.jvm.usage > 80
+    }
+  ]
+})
+
+const memoryColumns = [
+  { title: '属性', dataIndex: 'attr', key: 'attr', width: '33%' },
+  { 
+    title: '内存', 
+    dataIndex: 'memory', 
+    key: 'memory', 
+    width: '33%',
+    customRender: ({ record }) => {
+      return h('span', { class: record.memoryDanger ? 'text-danger' : '' }, record.memory)
+    }
+  },
+  { 
+    title: 'JVM', 
+    dataIndex: 'jvm', 
+    key: 'jvm', 
+    width: '33%',
+    customRender: ({ record }) => {
+      return h('span', { class: record.jvmDanger ? 'text-danger' : '' }, record.jvm)
+    }
+  }
+]
+
+// 服务器信息表格数据
+const serverInfoData = computed(() => {
+  if (!server.value.sys) return []
+  return [
+    { 
+      key: '1', 
+      label1: '服务器名称', 
+      value1: server.value.sys.computerName || '-',
+      label2: '操作系统',
+      value2: server.value.sys.osName || '-'
+    },
+    { 
+      key: '2', 
+      label1: '服务器IP', 
+      value1: server.value.sys.computerIp || '-',
+      label2: '系统架构',
+      value2: server.value.sys.osArch || '-'
+    }
+  ]
+})
+
+const serverInfoColumns = [
+  { dataIndex: 'label1', key: 'label1', width: '12.5%' },
+  { dataIndex: 'value1', key: 'value1', width: '37.5%' },
+  { dataIndex: 'label2', key: 'label2', width: '12.5%' },
+  { dataIndex: 'value2', key: 'value2', width: '37.5%' }
+]
+
+// JVM 信息表格数据
+const jvmData = computed(() => {
+  if (!server.value.jvm || !server.value.sys) return []
+  return [
+    { 
+      key: '1', 
+      label1: 'Java名称', 
+      value1: server.value.jvm.name || '-',
+      label2: 'Java版本',
+      value2: server.value.jvm.version || '-'
+    },
+    { 
+      key: '2', 
+      label1: '启动时间', 
+      value1: server.value.jvm.startTime || '-',
+      label2: '运行时长',
+      value2: server.value.jvm.runTime || '-'
+    },
+    { 
+      key: '3', 
+      label1: '安装路径', 
+      value1: server.value.jvm.home || '-',
+      label2: '',
+      value2: '',
+      colspan: 3
+    },
+    { 
+      key: '4', 
+      label1: '项目路径', 
+      value1: server.value.sys.userDir || '-',
+      label2: '',
+      value2: '',
+      colspan: 3
+    },
+    { 
+      key: '5', 
+      label1: '运行参数', 
+      value1: server.value.jvm.inputArgs || '-',
+      label2: '',
+      value2: '',
+      colspan: 3
+    }
+  ]
+})
+
+const jvmColumns = [
+  { dataIndex: 'label1', key: 'label1', width: '12.5%' },
+  { 
+    dataIndex: 'value1', 
+    key: 'value1', 
+    width: '37.5%',
+    customCell: (record, index, column) => {
+      if (record && record.colspan) {
+        return { colSpan: record.colspan }
+      }
+      return {}
+    }
+  },
+  { 
+    dataIndex: 'label2', 
+    key: 'label2', 
+    width: '12.5%',
+    customCell: (record, index, column) => {
+      if (record && record.colspan) {
+        return { colSpan: 0 }
+      }
+      return {}
+    }
+  },
+  { 
+    dataIndex: 'value2', 
+    key: 'value2', 
+    width: '37.5%',
+    customCell: (record, index, column) => {
+      if (record && record.colspan) {
+        return { colSpan: 0 }
+      }
+      return {}
+    }
+  }
+]
+
+// 磁盘状态表格数据
+const diskData = computed(() => {
+  if (!server.value.sysFiles) return []
+  return server.value.sysFiles.map((sysFile, index) => ({
+    key: index,
+    dirName: sysFile.dirName,
+    sysTypeName: sysFile.sysTypeName,
+    typeName: sysFile.typeName,
+    total: sysFile.total,
+    free: sysFile.free,
+    used: sysFile.used,
+    usage: sysFile.usage,
+    danger: sysFile.usage > 80
+  }))
+})
+
+const diskColumns = [
+  { title: '盘符路径', dataIndex: 'dirName', key: 'dirName' },
+  { title: '文件系统', dataIndex: 'sysTypeName', key: 'sysTypeName' },
+  { title: '盘符类型', dataIndex: 'typeName', key: 'typeName' },
+  { title: '总大小', dataIndex: 'total', key: 'total' },
+  { title: '可用大小', dataIndex: 'free', key: 'free' },
+  { title: '已用大小', dataIndex: 'used', key: 'used' },
+  { 
+    title: '已用百分比', 
+    dataIndex: 'usage', 
+    key: 'usage',
+    customRender: ({ record }) => {
+      return h('span', { class: record.danger ? 'text-danger' : '' }, `${record.usage}%`)
+    }
+  }
+]
+
 function getList() {
-  proxy.$modal.loading("正在加载服务监控数据,请稍候!")
+  const hide = message.loading("正在加载服务监控数据,请稍候!", 0)
   getServer().then(response => {
     server.value = response.data
-    proxy.$modal.closeLoading()
+    hide()
+  }).catch(() => {
+    hide()
   })
 }
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 16px;
+}
+
+.card-box {
+  margin-bottom: 16px;
+}
+
+.text-danger {
+  color: #ff4d4f;
+}
+
+:deep(.ant-table) {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+</style>

+ 122 - 11
yushu-uivue3/src/views/system/dept/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="部门名称" name="deptName">
             <a-input
                v-model:value="queryParams.deptName"
@@ -25,15 +25,17 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd()" v-hasPermi="['system:dept:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button @click="toggleExpandAll"><SortAscendingOutlined />展开/折叠</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd()" v-hasPermi="['system:dept:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button @click="toggleExpandAll"><SortAscendingOutlined />展开/折叠</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
          v-if="refreshTable"
@@ -61,6 +63,14 @@
         </template>
       </a-table>
 
+      <pagination
+         v-show="total > 0"
+         :total="total"
+         v-model:page="queryParams.pageNum"
+         v-model:limit="queryParams.pageSize"
+         @pagination="getList"
+      />
+
       <!-- 添加或修改部门对话框 -->
       <a-modal :title="title" v-model:open="open" width="600px" :footer="null">
          <a-form ref="deptRef" :model="form" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
@@ -140,6 +150,7 @@ const deptOptions = ref([])
 const isExpandAll = ref(true)
 const refreshTable = ref(true)
 const expandedRowKeys = ref([])
+const total = ref(0)
 
 const tableColumns = [
   { title: '部门名称', dataIndex: 'deptName', key: 'deptName', width: 260 },
@@ -152,6 +163,8 @@ const tableColumns = [
 const data = reactive({
   form: {},
   queryParams: {
+    pageNum: 1,
+    pageSize: 10,
     deptName: undefined,
     status: undefined
   },
@@ -194,7 +207,8 @@ function handleExpand(expanded, record) {
 function getList() {
   loading.value = true
   listDept(queryParams.value).then(response => {
-    deptList.value = proxy.handleTree(response.data, "deptId")
+    deptList.value = proxy.handleTree(response.data || response.rows, "deptId")
+    total.value = response.total || (response.data ? response.data.length : 0)
     if (isExpandAll.value) {
       expandedRowKeys.value = getAllDeptIds(deptList.value)
     }
@@ -224,12 +238,15 @@ function reset() {
 
 /** 搜索按钮操作 */
 function handleQuery() {
+  queryParams.value.pageNum = 1
   getList()
 }
 
 /** 重置按钮操作 */
 function resetQuery() {
   queryParams.value = {
+    pageNum: 1,
+    pageSize: 10,
     deptName: undefined,
     status: undefined
   }
@@ -311,3 +328,97 @@ function handleDelete(row) {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 115 - 19
yushu-uivue3/src/views/system/dict/data.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="字典名称" name="dictType">
             <a-select v-model:value="queryParams.dictType" style="width: 200px">
                <a-select-option
@@ -34,24 +34,26 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd" v-hasPermi="['system:dict:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:dict:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:dict:remove']"><DeleteOutlined />删除</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:dict:export']"><DownloadOutlined />导出</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleClose"><CloseOutlined />关闭</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd" v-hasPermi="['system:dict:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:dict:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:dict:remove']"><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:dict:export']"><DownloadOutlined />导出</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleClose"><CloseOutlined />关闭</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
         :loading="loading"
@@ -351,3 +353,97 @@ function handleExport() {
 getTypes(route.params && route.params.dictId)
 getTypeList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 116 - 21
yushu-uivue3/src/views/system/dict/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="字典名称" name="dictName">
             <a-input
                v-model:value="queryParams.dictName"
@@ -33,10 +33,11 @@
                >{{ dict.label }}</a-select-option>
             </a-select>
          </a-form-item>
-         <a-form-item label="创建时间" style="width: 308px">
+         <a-form-item label="创建时间">
             <a-range-picker
                v-model:value="dateRange"
                value-format="YYYY-MM-DD"
+               style="width: 308px"
             />
          </a-form-item>
          <a-form-item>
@@ -45,24 +46,26 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd" v-hasPermi="['system:dict:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:dict:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:dict:remove']"><DeleteOutlined />删除</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:dict:export']"><DownloadOutlined />导出</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger @click="handleRefreshCache" v-hasPermi="['system:dict:remove']"><ReloadOutlined />刷新缓存</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd" v-hasPermi="['system:dict:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:dict:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:dict:remove']"><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:dict:export']"><DownloadOutlined />导出</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger @click="handleRefreshCache" v-hasPermi="['system:dict:remove']"><ReloadOutlined />刷新缓存</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
         :loading="loading"
@@ -306,7 +309,99 @@ function handleRefreshCache() {
 getList()
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+
 .link-type {
   color: #1890ff;
 }

+ 27 - 1
yushu-uivue3/src/views/system/icon/index.vue

@@ -13,6 +13,9 @@
       <div class="header-right">
         <div class="icon-stats">
           共 <span class="count">{{ filteredIcons.length }}</span> 个图标
+          <span v-if="filteredIcons.length > 0" style="margin-left: 8px; color: #8c8c8c;">
+            (第 {{ (pageNum - 1) * pageSize + 1 }}-{{ Math.min(pageNum * pageSize, filteredIcons.length) }} 个)
+          </span>
         </div>
         <a-button v-if="isDev" type="primary" @click="showUploadDialog = true" v-hasPermi="['tool:icon:add']">
           <template #icon><PlusOutlined /></template>
@@ -24,7 +27,7 @@
     <!-- 图标网格 -->
     <div class="icon-grid">
       <div
-        v-for="icon in filteredIcons"
+        v-for="icon in paginatedIcons"
         :key="icon"
         class="icon-item"
         @click="handleCopy(icon)"
@@ -51,6 +54,15 @@
     <!-- 空状态 -->
     <a-empty v-if="filteredIcons.length === 0" description="没有找到匹配的图标" />
 
+    <!-- 分页 -->
+    <pagination
+      v-show="filteredIcons.length > 0"
+      :total="filteredIcons.length"
+      v-model:page="pageNum"
+      v-model:limit="pageSize"
+      :page-sizes="[24, 48, 96, 192]"
+    />
+
     <!-- 上传对话框 -->
     <a-modal v-model:open="showUploadDialog" title="上传图标" :width="500">
       <a-upload-dragger
@@ -84,6 +96,8 @@ const showUploadDialog = ref(false)
 const uploading = ref(false)
 const uploadRef = ref(null)
 const uploadFiles = ref([])
+const pageNum = ref(1)
+const pageSize = ref(48)
 
 // 判断是否开发环境
 const isDev = import.meta.env.DEV
@@ -102,6 +116,18 @@ const filteredIcons = computed(() => {
   return allIcons.filter(icon => icon.toLowerCase().includes(query))
 })
 
+// 分页后的图标
+const paginatedIcons = computed(() => {
+  const start = (pageNum.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredIcons.value.slice(start, end)
+})
+
+// 监听搜索变化,重置页码
+watch(searchQuery, () => {
+  pageNum.value = 1
+})
+
 // 复制图标名称
 function handleCopy(iconName) {
   navigator.clipboard.writeText(iconName).then(() => {

+ 9 - 24
yushu-uivue3/src/views/system/mail/inbox/index.vue

@@ -66,17 +66,17 @@
 
       <div class="list-filter" v-if="total > 0">
         <span>共 {{ total }} 封邮件</span>
-        <div class="pagination-simple">
-          <a-button type="link" size="small" :disabled="queryParams.pageNum <= 1" @click="prevPage">
-            <template #icon><LeftOutlined /></template>
-          </a-button>
-          <span>{{ queryParams.pageNum }}</span>
-          <a-button type="link" size="small" :disabled="queryParams.pageNum * queryParams.pageSize >= total" @click="nextPage">
-            <template #icon><RightOutlined /></template>
-          </a-button>
-        </div>
       </div>
 
+      <pagination
+         v-show="total > 0"
+         :total="total"
+         v-model:page="queryParams.pageNum"
+         v-model:limit="queryParams.pageSize"
+         @pagination="getList"
+         style="padding: 16px; background: #fff; margin-bottom: 8px;"
+      />
+
       <div class="mail-list-scroll" style="flex: 1; overflow: auto;" v-loading="loading">
         <div v-if="inboxList.length > 0">
           <div 
@@ -408,21 +408,6 @@ function getList() {
   })
 }
 
-/** 上一页 */
-function prevPage() {
-  if (queryParams.pageNum > 1) {
-    queryParams.pageNum--
-    getList()
-  }
-}
-
-/** 下一页 */
-function nextPage() {
-  if (queryParams.pageNum * queryParams.pageSize < total.value) {
-    queryParams.pageNum++
-    getList()
-  }
-}
 
 /** 同步邮件 */
 function handleSync() {

+ 119 - 24
yushu-uivue3/src/views/system/mail/log/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="app-container">
-    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="mb8">
+    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
       <a-form-item label="收件人" name="receiver">
         <a-input v-model:value="queryParams.receiver" placeholder="请输入收件人" allowClear style="width: 200px" @pressEnter="handleQuery" />
       </a-form-item>
@@ -14,11 +14,12 @@
           <a-select-option value="2">发送中</a-select-option>
         </a-select>
       </a-form-item>
-      <a-form-item label="发送时间" style="width: 308px">
+      <a-form-item label="发送时间">
         <a-range-picker
           v-model:value="dateRange"
           value-format="YYYY-MM-DD"
           format="YYYY-MM-DD"
+          style="width: 308px"
         />
       </a-form-item>
       <a-form-item>
@@ -33,27 +34,29 @@
       </a-form-item>
     </a-form>
 
-    <a-row :gutter="10" class="mb8">
-      <a-col :span="1.5">
-        <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:mail:log:remove']">
-          <template #icon><DeleteOutlined /></template>
-          删除
-        </a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button danger @click="handleClean" v-hasPermi="['system:mail:log:remove']">
-          <template #icon><DeleteOutlined /></template>
-          清空
-        </a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button @click="handleExport" v-hasPermi="['system:mail:log:export']">
-          <template #icon><DownloadOutlined /></template>
-          导出
-        </a-button>
-      </a-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </a-row>
+    <div class="button-toolbar">
+      <a-row :gutter="10">
+        <a-col :span="1.5">
+          <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:mail:log:remove']">
+            <template #icon><DeleteOutlined /></template>
+            删除
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button danger @click="handleClean" v-hasPermi="['system:mail:log:remove']">
+            <template #icon><DeleteOutlined /></template>
+            清空
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button @click="handleExport" v-hasPermi="['system:mail:log:export']">
+            <template #icon><DownloadOutlined /></template>
+            导出
+          </a-button>
+        </a-col>
+        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+      </a-row>
+    </div>
 
     <a-table 
       :loading="loading" 
@@ -244,7 +247,99 @@ function handleExport() {
 getList()
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+
 .content-container {
   padding: 15px;
   background-color: #f5f5f5;

+ 120 - 11
yushu-uivue3/src/views/system/menu/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="菜单名称" name="menuName">
             <a-input
                v-model:value="queryParams.menuName"
@@ -25,15 +25,17 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd()" v-hasPermi="['system:menu:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button @click="toggleExpandAll"><SortAscendingOutlined />展开/折叠</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd()" v-hasPermi="['system:menu:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button @click="toggleExpandAll"><SortAscendingOutlined />展开/折叠</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
          v-if="refreshTable"
@@ -64,6 +66,14 @@
         </template>
       </a-table>
 
+      <pagination
+         v-show="total > 0"
+         :total="total"
+         v-model:page="queryParams.pageNum"
+         v-model:limit="queryParams.pageSize"
+         @pagination="getList"
+      />
+
       <!-- 添加或修改菜单对话框 -->
       <a-modal :title="title" v-model:open="open" width="680px" :footer="null">
          <a-form ref="menuRef" :model="form" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
@@ -285,6 +295,7 @@ const isExpandAll = ref(false)
 const refreshTable = ref(true)
 const iconSelectRef = ref(null)
 const expandedRowKeys = ref([])
+const total = ref(0)
 
 const tableColumns = [
   { title: '菜单名称', dataIndex: 'menuName', key: 'menuName', ellipsis: true, width: 160 },
@@ -300,6 +311,8 @@ const tableColumns = [
 const data = reactive({
   form: {},
   queryParams: {
+    pageNum: 1,
+    pageSize: 10,
     menuName: undefined,
     visible: undefined
   },
@@ -340,7 +353,8 @@ function handleExpand(expanded, record) {
 function getList() {
   loading.value = true
   listMenu(queryParams.value).then(response => {
-    menuList.value = proxy.handleTree(response.data, "menuId")
+    menuList.value = proxy.handleTree(response.data || response.rows, "menuId")
+    total.value = response.total || (response.data ? response.data.length : 0)
     loading.value = false
   })
 }
@@ -391,6 +405,7 @@ function selected(name) {
 
 /** 搜索按钮操作 */
 function handleQuery() {
+  queryParams.value.pageNum = 1
   getList()
 }
 
@@ -476,3 +491,97 @@ function handleDelete(row) {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 119 - 25
yushu-uivue3/src/views/system/message/index.vue

@@ -17,7 +17,7 @@
     </a-alert>
 
     <!-- 搜索栏 -->
-    <a-form :model="queryParams" ref="queryFormRef" layout="inline" v-show="showSearch" class="mb8">
+    <a-form :model="queryParams" ref="queryFormRef" layout="inline" v-show="showSearch" class="search-form">
       <a-form-item label="消息标题" name="title">
         <a-input
           v-model:value="queryParams.title"
@@ -47,30 +47,32 @@
     </a-form>
 
     <!-- 操作按钮 -->
-    <a-row :gutter="10" class="mb8">
-      <a-col :span="1.5">
-        <a-button
-          type="primary"
-          @click="handleSend"
-          v-hasPermi="['system:message:send']"
-        >
-          <template #icon><SendOutlined /></template>
-          发布通知
-        </a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button
-          danger
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['system:message:remove']"
-        >
-          <template #icon><DeleteOutlined /></template>
-          删除
-        </a-button>
-      </a-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </a-row>
+    <div class="button-toolbar">
+      <a-row :gutter="10">
+        <a-col :span="1.5">
+          <a-button
+            type="primary"
+            @click="handleSend"
+            v-hasPermi="['system:message:send']"
+          >
+            <template #icon><SendOutlined /></template>
+            发布通知
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button
+            danger
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['system:message:remove']"
+          >
+            <template #icon><DeleteOutlined /></template>
+            删除
+          </a-button>
+        </a-col>
+        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+      </a-row>
+    </div>
 
     <!-- 数据表格 -->
     <a-table 
@@ -301,6 +303,98 @@ getList()
 </script>
 
 <style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+
 .message-content {
   padding: 15px;
   background: #f8fafc;

+ 109 - 13
yushu-uivue3/src/views/system/notice/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="公告标题" name="noticeTitle">
             <a-input
                v-model:value="queryParams.noticeTitle"
@@ -34,18 +34,20 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd" v-hasPermi="['system:notice:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:notice:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:notice:remove']"><DeleteOutlined />删除</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd" v-hasPermi="['system:notice:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:notice:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:notice:remove']"><DeleteOutlined />删除</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
         :loading="loading"
@@ -279,3 +281,97 @@ function handleDelete(row) {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 121 - 25
yushu-uivue3/src/views/system/notification/index.vue

@@ -17,7 +17,7 @@
     </a-alert>
 
     <!-- 搜索栏 -->
-    <a-form :model="queryParams" ref="queryFormRef" layout="inline" v-show="showSearch" class="mb8">
+    <a-form :model="queryParams" ref="queryFormRef" layout="inline" v-show="showSearch" class="search-form">
       <a-form-item label="通知标题" name="title">
         <a-input
           v-model:value="queryParams.title"
@@ -54,30 +54,32 @@
     </a-form>
 
     <!-- 操作按钮 -->
-    <a-row :gutter="10" class="mb8">
-      <a-col :span="1.5">
-        <a-button
-          type="primary"
-          @click="handleAdd"
-          v-hasPermi="['system:notification:add']"
-        >
-          <template #icon><PlusOutlined /></template>
-          新增通知
-        </a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button
-          danger
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['system:notification:remove']"
-        >
-          <template #icon><DeleteOutlined /></template>
-          删除
-        </a-button>
-      </a-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </a-row>
+    <div class="button-toolbar">
+      <a-row :gutter="10">
+        <a-col :span="1.5">
+          <a-button
+            type="primary"
+            @click="handleAdd"
+            v-hasPermi="['system:notification:add']"
+          >
+            <template #icon><PlusOutlined /></template>
+            新增通知
+          </a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button
+            danger
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['system:notification:remove']"
+          >
+            <template #icon><DeleteOutlined /></template>
+            删除
+          </a-button>
+        </a-col>
+        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+      </a-row>
+    </div>
 
     <!-- 通知列表 -->
     <a-table 
@@ -457,3 +459,97 @@ function searchUsers(query) {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 117 - 21
yushu-uivue3/src/views/system/param/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="app-container">
-    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
       <a-form-item label="参数名称" name="configName">
         <a-input v-model:value="queryParams.configName" placeholder="请输入参数名称" allow-clear style="width: 240px" @pressEnter="handleQuery" />
       </a-form-item>
@@ -12,8 +12,8 @@
           <a-select-option v-for="dict in sys_yes_no" :key="dict.value" :value="dict.value">{{ dict.label }}</a-select-option>
         </a-select>
       </a-form-item>
-      <a-form-item label="创建时间" style="width: 308px">
-        <a-range-picker v-model:value="dateRange" value-format="YYYY-MM-DD" />
+      <a-form-item label="创建时间">
+        <a-range-picker v-model:value="dateRange" value-format="YYYY-MM-DD" style="width: 308px" />
       </a-form-item>
       <a-form-item>
         <a-button type="primary" @click="handleQuery"><SearchOutlined />搜索</a-button>
@@ -21,24 +21,26 @@
       </a-form-item>
     </a-form>
 
-    <a-row :gutter="10" class="mb8">
-      <a-col :span="1.5">
-        <a-button type="primary" @click="handleAdd" v-hasPermi="['system:config:add']"><PlusOutlined />新增</a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:config:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:config:remove']"><DeleteOutlined />删除</a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:config:export']"><DownloadOutlined />导出</a-button>
-      </a-col>
-      <a-col :span="1.5">
-        <a-button danger @click="handleRefreshCache" v-hasPermi="['system:config:remove']"><ReloadOutlined />刷新缓存</a-button>
-      </a-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </a-row>
+    <div class="button-toolbar">
+      <a-row :gutter="10">
+        <a-col :span="1.5">
+          <a-button type="primary" @click="handleAdd" v-hasPermi="['system:config:add']"><PlusOutlined />新增</a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:config:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:config:remove']"><DeleteOutlined />删除</a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:config:export']"><DownloadOutlined />导出</a-button>
+        </a-col>
+        <a-col :span="1.5">
+          <a-button danger @click="handleRefreshCache" v-hasPermi="['system:config:remove']"><ReloadOutlined />刷新缓存</a-button>
+        </a-col>
+        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+      </a-row>
+    </div>
 
     <a-table
       :loading="loading"
@@ -256,3 +258,97 @@ function handleRefreshCache() {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 112 - 16
yushu-uivue3/src/views/system/post/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+      <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
          <a-form-item label="岗位编码" name="postCode">
             <a-input
                v-model:value="queryParams.postCode"
@@ -34,21 +34,23 @@
          </a-form-item>
       </a-form>
 
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd" v-hasPermi="['system:post:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:post:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:post:remove']"><DeleteOutlined />删除</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:post:export']"><DownloadOutlined />导出</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd" v-hasPermi="['system:post:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:post:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:post:remove']"><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:post:export']"><DownloadOutlined />导出</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <a-table
         :loading="loading"
@@ -275,3 +277,97 @@ function handleExport() {
 
 getList()
 </script>
+
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+</style>

+ 113 - 18
yushu-uivue3/src/views/system/role/index.vue

@@ -1,6 +1,6 @@
 <template>
    <div class="app-container">
-      <a-form :model="queryParams" ref="queryRef" v-show="showSearch" layout="inline">
+      <a-form :model="queryParams" ref="queryRef" v-show="showSearch" layout="inline" class="search-form">
          <a-form-item label="角色名称" name="roleName">
             <a-input
                v-model:value="queryParams.roleName"
@@ -33,10 +33,11 @@
                >{{ dict.label }}</a-select-option>
             </a-select>
          </a-form-item>
-         <a-form-item label="创建时间" style="width: 308px">
+         <a-form-item label="创建时间">
             <a-range-picker
                v-model:value="dateRange"
                value-format="YYYY-MM-DD"
+               style="width: 308px"
             />
          </a-form-item>
          <a-form-item>
@@ -44,21 +45,23 @@
             <a-button style="margin-left: 8px" @click="resetQuery"><ReloadOutlined />重置</a-button>
          </a-form-item>
       </a-form>
-      <a-row :gutter="10" class="mb8">
-         <a-col :span="1.5">
-            <a-button type="primary" @click="handleAdd" v-hasPermi="['system:role:add']"><PlusOutlined />新增</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:role:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:role:remove']"><DeleteOutlined />删除</a-button>
-         </a-col>
-         <a-col :span="1.5">
-            <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:role:export']"><DownloadOutlined />导出</a-button>
-         </a-col>
-         <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-      </a-row>
+      <div class="button-toolbar">
+         <a-row :gutter="10">
+            <a-col :span="1.5">
+               <a-button type="primary" @click="handleAdd" v-hasPermi="['system:role:add']"><PlusOutlined />新增</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:role:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:role:remove']"><DeleteOutlined />删除</a-button>
+            </a-col>
+            <a-col :span="1.5">
+               <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:role:export']"><DownloadOutlined />导出</a-button>
+            </a-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+         </a-row>
+      </div>
 
       <!-- 表格数据 -->
       <a-table
@@ -566,7 +569,99 @@ function cancelDataScope() {
 getList()
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
+// 搜索表单布局
+.search-form.ant-form-inline {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  
+  .ant-form-item {
+    margin-right: 16px;
+    margin-bottom: 16px;
+    display: inline-flex;
+    flex-wrap: nowrap;
+    align-items: center;
+    
+    .ant-form-item-label {
+      padding-right: 8px;
+      flex-shrink: 0;
+      
+      > label {
+        white-space: nowrap;
+        height: 32px;
+        line-height: 32px;
+        margin-bottom: 0;
+      }
+    }
+    
+    .ant-form-item-control {
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
+    }
+    
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+
+// 按钮工具栏
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
+      }
+    }
+  }
+}
+
+// 表格容器
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+
+// 表格样式
+.ant-table {
+  .ant-table-thead > tr > th {
+    background-color: #fafafa;
+    font-weight: 600;
+    color: #262626;
+  }
+  
+  .ant-table-tbody > tr > td {
+    padding: 12px 16px;
+  }
+}
+
+// 按钮图标间距
+.ant-btn {
+  .anticon + span,
+  span + .anticon {
+    margin-left: 4px;
+  }
+}
+
 .tree-border {
   margin-top: 5px;
   border: 1px solid #d9d9d9;

+ 50 - 36
yushu-uivue3/src/views/system/user/index.vue

@@ -26,7 +26,7 @@
         <!--用户数据-->
         <pane size="84">
           <a-col>
-            <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch">
+            <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
               <a-form-item label="用户名称" name="userName">
                 <a-input v-model:value="queryParams.userName" placeholder="请输入用户名称" allow-clear style="width: 240px" @pressEnter="handleQuery" />
               </a-form-item>
@@ -47,24 +47,26 @@
               </a-form-item>
             </a-form>
 
-            <a-row :gutter="10" class="mb8">
-              <a-col :span="1.5">
-                <a-button type="primary" @click="handleAdd" v-hasPermi="['system:user:add']"><PlusOutlined />新增</a-button>
-              </a-col>
-              <a-col :span="1.5">
-                <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
-              </a-col>
-              <a-col :span="1.5">
-                <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']"><DeleteOutlined />删除</a-button>
-              </a-col>
-              <a-col :span="1.5">
-                <a-button @click="handleImport" v-hasPermi="['system:user:import']"><UploadOutlined />导入</a-button>
-              </a-col>
-              <a-col :span="1.5">
-                <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:user:export']"><DownloadOutlined />导出</a-button>
-              </a-col>
-              <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
-            </a-row>
+            <div class="button-toolbar">
+              <a-row :gutter="10">
+                <a-col :span="1.5">
+                  <a-button type="primary" @click="handleAdd" v-hasPermi="['system:user:add']"><PlusOutlined />新增</a-button>
+                </a-col>
+                <a-col :span="1.5">
+                  <a-button type="primary" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']" style="background-color: #52c41a; border-color: #52c41a"><EditOutlined />修改</a-button>
+                </a-col>
+                <a-col :span="1.5">
+                  <a-button danger :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']"><DeleteOutlined />删除</a-button>
+                </a-col>
+                <a-col :span="1.5">
+                  <a-button @click="handleImport" v-hasPermi="['system:user:import']"><UploadOutlined />导入</a-button>
+                </a-col>
+                <a-col :span="1.5">
+                  <a-button type="primary" style="background-color: #faad14; border-color: #faad14" @click="handleExport" v-hasPermi="['system:user:export']"><DownloadOutlined />导出</a-button>
+                </a-col>
+                <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+              </a-row>
+            </div>
 
             <a-table
               :loading="loading"
@@ -661,19 +663,16 @@ onMounted(() => {
 
 <style lang="scss" scoped>
 // 搜索表单布局
-.ant-form-inline {
+.search-form.ant-form-inline {
   background: #fff;
-  padding: 16px;
+  padding: 0;
   border-radius: 4px;
-  margin-bottom: 16px;
-  display: flex;
-  flex-wrap: wrap;
-  align-items: flex-start;
   
   .ant-form-item {
     margin-right: 16px;
     margin-bottom: 16px;
-    display: flex;
+    display: inline-flex;
+    flex-wrap: nowrap;
     align-items: center;
     
     .ant-form-item-label {
@@ -684,11 +683,19 @@ onMounted(() => {
         white-space: nowrap;
         height: 32px;
         line-height: 32px;
+        margin-bottom: 0;
       }
     }
     
     .ant-form-item-control {
-      flex: 1;
+      flex: 0 0 auto;
+      display: inline-block;
+    }
+    
+    .ant-form-item-control-input {
+      min-height: 32px;
+      display: flex;
+      align-items: center;
     }
     
     &:last-child {
@@ -697,16 +704,23 @@ onMounted(() => {
   }
 }
 
-// 按钮组间距
-.mb8 {
+// 按钮工具栏 - 与表格对齐
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
   margin-bottom: 16px;
   
-  .ant-col {
-    .ant-btn {
-      margin-right: 8px;
-      
-      &:last-child {
-        margin-right: 0;
+  .ant-row {
+    margin: 0;
+    
+    .ant-col {
+      .ant-btn {
+        margin-right: 8px;
+        
+        &:last-child {
+          margin-right: 0;
+        }
       }
     }
   }
@@ -715,7 +729,7 @@ onMounted(() => {
 // 表格容器
 .ant-table-wrapper {
   background: #fff;
-  padding: 16px;
+  padding: 0;
   border-radius: 4px;
 }
 

+ 19 - 15
yushu-uivue3/src/views/tool/build/index.vue

@@ -6,7 +6,7 @@
           <img :src="logo" alt="logo"> Form Generator
         </div>
       </div>
-      <el-scrollbar class="left-scrollbar">
+      <div class="left-scrollbar" style="overflow: auto; height: 100%;">
         <div class="components-list">
           <div class="components-title">
             <svg-icon icon-class="component" />输入型组件
@@ -54,24 +54,27 @@
             </template>
           </draggable>
         </div>
-      </el-scrollbar>
+      </div>
     </div>
     <div class="center-board">
       <div class="action-bar">
-        <el-button icon="Download" type="primary" text @click="download">
+        <a-button type="primary" @click="download">
+          <template #icon><DownloadOutlined /></template>
           导出vue文件
-        </el-button>
-        <el-button class="copy-btn-main" icon="DocumentCopy" type="primary" text @click="copy">
+        </a-button>
+        <a-button class="copy-btn-main" type="primary" @click="copy">
+          <template #icon><CopyOutlined /></template>
           复制代码
-        </el-button>
-        <el-button class="delete-btn" icon="Delete" text @click="empty" type="danger">
+        </a-button>
+        <a-button class="delete-btn" danger @click="empty">
+          <template #icon><DeleteOutlined /></template>
           清空
-        </el-button>
+        </a-button>
       </div>
-      <el-scrollbar class="center-scrollbar">
-        <el-row class="center-board-row" :gutter="formConf.gutter">
-          <el-form :size="formConf.size" :label-position="formConf.labelPosition" :disabled="formConf.disabled"
-            :label-width="formConf.labelWidth + 'px'">
+      <div class="center-scrollbar" style="overflow: auto; height: 100%;">
+        <a-row class="center-board-row" :gutter="formConf.gutter">
+          <a-form :size="formConf.size" :label-col="{ style: { width: formConf.labelWidth + 'px' } }" :disabled="formConf.disabled"
+            :label-align="formConf.labelPosition === 'left' ? 'left' : formConf.labelPosition === 'right' ? 'right' : 'left'">
             <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup"
               item-key="label">
               <template #item="{ element, index }">
@@ -83,9 +86,9 @@
             <div v-show="!drawingList.length" class="empty-info">
               从左侧拖入或点选组件进行表单设计
             </div>
-          </el-form>
-        </el-row>
-      </el-scrollbar>
+          </a-form>
+        </a-row>
+      </div>
     </div>
     <right-panel :active-data="activeData" :form-conf="formConf" :show-field="!!drawingList.length"
       @tag-change="tagChange" />
@@ -108,6 +111,7 @@ import { makeUpJs } from '@/utils/generator/js'
 import { makeUpCss } from '@/utils/generator/css'
 import Download from '@/plugins/download'
 import { notification } from 'ant-design-vue'
+import { DownloadOutlined, CopyOutlined, DeleteOutlined } from '@ant-design/icons-vue'
 import DraggableItem from './DraggableItem'
 import RightPanel from './RightPanel'
 import CodeTypeDialog from './CodeTypeDialog'

+ 5 - 5
yushu-uivue3/src/views/tool/gen/createTable.vue

@@ -1,15 +1,15 @@
 <template>
   <!-- 创建表 -->
-  <el-dialog title="创建表" v-model="visible" width="800px" top="5vh" append-to-body>
+  <a-modal title="创建表" v-model:open="visible" width="800px" :styles="{ top: '5vh' }" @ok="handleImportTable">
     <span>创建表语句(支持多个建表语句):</span>
-    <el-input type="textarea" :rows="10" placeholder="请输入文本" v-model="content"></el-input>
+    <a-textarea :rows="10" placeholder="请输入文本" v-model:value="content" style="margin-top: 8px"></a-textarea>
     <template #footer>
       <div class="dialog-footer">
-        <el-button type="primary" @click="handleImportTable">确 定</el-button>
-        <el-button @click="visible = false">取 消</el-button>
+        <a-button type="primary" @click="handleImportTable">确 定</a-button>
+        <a-button @click="visible = false">取 消</a-button>
       </div>
     </template>
-  </el-dialog>
+  </a-modal>
 </template>
 
 <script setup>

+ 70 - 35
yushu-uivue3/src/views/tool/gen/importTable.vue

@@ -1,38 +1,47 @@
 <template>
   <!-- 导入表 -->
-  <el-dialog title="导入表" v-model="visible" width="800px" top="5vh" append-to-body>
-    <el-form :model="queryParams" ref="queryRef" :inline="true">
-      <el-form-item label="表名称" prop="tableName">
-        <el-input
-          v-model="queryParams.tableName"
+  <a-modal title="导入表" v-model:open="visible" width="800px" :styles="{ top: '5vh' }" @ok="handleImportTable">
+    <a-form :model="queryParams" ref="queryRef" layout="inline">
+      <a-form-item label="表名称" name="tableName">
+        <a-input
+          v-model:value="queryParams.tableName"
           placeholder="请输入表名称"
-          clearable
+          allowClear
           style="width: 180px"
-          @keyup.enter="handleQuery"
+          @pressEnter="handleQuery"
         />
-      </el-form-item>
-      <el-form-item label="表描述" prop="tableComment">
-        <el-input
-          v-model="queryParams.tableComment"
+      </a-form-item>
+      <a-form-item label="表描述" name="tableComment">
+        <a-input
+          v-model:value="queryParams.tableComment"
           placeholder="请输入表描述"
-          clearable
+          allowClear
           style="width: 180px"
-          @keyup.enter="handleQuery"
+          @pressEnter="handleQuery"
         />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-    <el-row>
-      <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
-        <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="createTime" label="创建时间"></el-table-column>
-        <el-table-column prop="updateTime" label="更新时间"></el-table-column>
-      </el-table>
+      </a-form-item>
+      <a-form-item>
+        <a-button type="primary" @click="handleQuery">
+          <template #icon><SearchOutlined /></template>
+          搜索
+        </a-button>
+        <a-button @click="resetQuery" style="margin-left: 8px">
+          <template #icon><ReloadOutlined /></template>
+          重置
+        </a-button>
+      </a-form-item>
+    </a-form>
+    <a-row style="margin-top: 16px">
+      <a-table 
+        @row-click="clickRow" 
+        ref="table" 
+        :data-source="dbTableList" 
+        :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+        :row-key="record => record.tableName"
+        :columns="tableColumns"
+        :pagination="false"
+        :scroll="{ y: 260 }"
+      />
       <pagination
         v-show="total>0"
         :total="total"
@@ -40,25 +49,35 @@
         v-model:limit="queryParams.pageSize"
         @pagination="getList"
       />
-    </el-row>
+    </a-row>
     <template #footer>
       <div class="dialog-footer">
-        <el-button type="primary" @click="handleImportTable">确 定</el-button>
-        <el-button @click="visible = false">取 消</el-button>
+        <a-button type="primary" @click="handleImportTable">确 定</a-button>
+        <a-button @click="visible = false">取 消</a-button>
       </div>
     </template>
-  </el-dialog>
+  </a-modal>
 </template>
 
 <script setup>
 import { listDbTable, importTable } from "@/api/tool/gen"
+import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue'
 
 const total = ref(0)
 const visible = ref(false)
 const tables = ref([])
 const dbTableList = ref([])
+const selectedRowKeys = ref([])
 const { proxy } = getCurrentInstance()
 
+// 表格列配置
+const tableColumns = [
+  { title: '表名称', dataIndex: 'tableName', key: 'tableName', ellipsis: true },
+  { title: '表描述', dataIndex: 'tableComment', key: 'tableComment', ellipsis: true },
+  { title: '创建时间', dataIndex: 'createTime', key: 'createTime' },
+  { title: '更新时间', dataIndex: 'updateTime', key: 'updateTime' }
+]
+
 const queryParams = reactive({
   pageNum: 1,
   pageSize: 10,
@@ -70,18 +89,34 @@ const emit = defineEmits(["ok"])
 
 /** 查询参数列表 */
 function show() {
+  selectedRowKeys.value = []
+  tables.value = []
   getList()
   visible.value = true
 }
 
 /** 单击选择行 */
-function clickRow(row) {
-  proxy.$refs.table.toggleRowSelection(row)
+function clickRow(record) {
+  const index = selectedRowKeys.value.indexOf(record.tableName)
+  if (index > -1) {
+    selectedRowKeys.value.splice(index, 1)
+  } else {
+    selectedRowKeys.value.push(record.tableName)
+  }
+  updateTables()
 }
 
 /** 多选框选中数据 */
-function handleSelectionChange(selection) {
-  tables.value = selection.map(item => item.tableName)
+function handleSelectionChange(selectedKeys, selectedRows) {
+  selectedRowKeys.value = selectedKeys
+  updateTables()
+}
+
+/** 更新选中的表名列表 */
+function updateTables() {
+  tables.value = dbTableList.value
+    .filter(item => selectedRowKeys.value.includes(item.tableName))
+    .map(item => item.tableName)
 }
 
 /** 查询表数据 */

+ 180 - 114
yushu-uivue3/src/views/tool/gen/index.vue

@@ -1,124 +1,141 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
-      <el-form-item label="表名称" prop="tableName">
-        <el-input
-          v-model="queryParams.tableName"
+    <a-form :model="queryParams" ref="queryRef" layout="inline" v-show="showSearch" class="search-form">
+      <a-form-item label="表名称" name="tableName">
+        <a-input
+          v-model:value="queryParams.tableName"
           placeholder="请输入表名称"
-          clearable
+          allowClear
           style="width: 200px"
-          @keyup.enter="handleQuery"
+          @pressEnter="handleQuery"
         />
-      </el-form-item>
-      <el-form-item label="表描述" prop="tableComment">
-        <el-input
-          v-model="queryParams.tableComment"
+      </a-form-item>
+      <a-form-item label="表描述" name="tableComment">
+        <a-input
+          v-model:value="queryParams.tableComment"
           placeholder="请输入表描述"
-          clearable
+          allowClear
           style="width: 200px"
-          @keyup.enter="handleQuery"
+          @pressEnter="handleQuery"
         />
-      </el-form-item>
-      <el-form-item label="创建时间" style="width: 308px">
-        <el-date-picker
-          v-model="dateRange"
-          value-format="YYYY-MM-DD"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
+      </a-form-item>
+      <a-form-item label="创建时间" style="width: 308px">
+        <a-range-picker
+          v-model:value="dateRange"
+          format="YYYY-MM-DD"
+        />
+      </a-form-item>
+      <a-form-item>
+        <a-button type="primary" @click="handleQuery">
+          <template #icon><SearchOutlined /></template>
+          搜索
+        </a-button>
+        <a-button @click="resetQuery" style="margin-left: 8px">
+          <template #icon><ReloadOutlined /></template>
+          重置
+        </a-button>
+      </a-form-item>
+    </a-form>
 
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button
+    <a-row :gutter="10" class="mb8 button-toolbar">
+      <a-col :span="1.5">
+        <a-button
           type="primary"
-          plain
-          icon="Download"
           :disabled="multiple"
           @click="handleGenTable"
           v-hasPermi="['tool:gen:code']"
-        >生成</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
+        >
+          <template #icon><DownloadOutlined /></template>
+          生成
+        </a-button>
+      </a-col>
+      <a-col :span="1.5">
+        <a-button
           type="primary"
-          plain
-          icon="Plus"
           @click="openCreateTable"
           v-hasRole="['admin']"
-        >创建</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="info"
-          plain
-          icon="Upload"
+        >
+          <template #icon><PlusOutlined /></template>
+          创建
+        </a-button>
+      </a-col>
+      <a-col :span="1.5">
+        <a-button
           @click="openImportTable"
           v-hasPermi="['tool:gen:import']"
-        >导入</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="success"
-          plain
-          icon="Edit"
+        >
+          <template #icon><UploadOutlined /></template>
+          导入
+        </a-button>
+      </a-col>
+      <a-col :span="1.5">
+        <a-button
+          type="primary"
           :disabled="single"
           @click="handleEditTable"
           v-hasPermi="['tool:gen:edit']"
-        >修改</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="danger"
-          plain
-          icon="Delete"
+        >
+          <template #icon><EditOutlined /></template>
+          修改
+        </a-button>
+      </a-col>
+      <a-col :span="1.5">
+        <a-button
+          danger
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['tool:gen:remove']"
-        >删除</el-button>
-      </el-col>
+        >
+          <template #icon><DeleteOutlined /></template>
+          删除
+        </a-button>
+      </a-col>
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
+    </a-row>
 
-    <el-table ref="genRef" v-loading="loading" :data="tableList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
-      <el-table-column type="selection" align="center" width="55"></el-table-column>
-      <el-table-column label="序号" type="index" width="50" align="center">
-        <template #default="scope">
-          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
+    <a-table 
+      ref="genRef" 
+      :loading="loading" 
+      :data-source="tableList" 
+      :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }"
+      :row-key="record => record.tableId"
+      :columns="tableColumns"
+      :pagination="false"
+      @change="handleTableChange"
+    >
+      <template #bodyCell="{ column, record, index }">
+        <template v-if="column.key === 'index'">
+          <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + index + 1}}</span>
         </template>
-      </el-table-column>
-      <el-table-column label="表名称" align="center" prop="tableName" :show-overflow-tooltip="true" />
-      <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" />
-      <el-table-column label="实体" align="center" prop="className" :show-overflow-tooltip="true" />
-      <el-table-column label="创建时间" align="center" prop="createTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']" />
-      <el-table-column label="更新时间" align="center" prop="updateTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']" />
-      <el-table-column label="操作" align="center" width="330" class-name="small-padding fixed-width">
-        <template #default="scope">
-          <el-tooltip content="预览" placement="top">
-            <el-button link type="primary" icon="View" @click="handlePreview(scope.row)" v-hasPermi="['tool:gen:preview']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="编辑" placement="top">
-            <el-button link type="primary" icon="Edit" @click="handleEditTable(scope.row)" v-hasPermi="['tool:gen:edit']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="删除" placement="top">
-            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['tool:gen:remove']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="同步" placement="top">
-            <el-button link type="primary" icon="Refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['tool:gen:edit']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="生成代码" placement="top">
-            <el-button link type="primary" icon="Download" @click="handleGenTable(scope.row)" v-hasPermi="['tool:gen:code']"></el-button>
-          </el-tooltip>
+        <template v-else-if="column.key === 'action'">
+          <a-tooltip title="预览">
+            <a-button type="link" @click="handlePreview(record)" v-hasPermi="['tool:gen:preview']">
+              <template #icon><EyeOutlined /></template>
+            </a-button>
+          </a-tooltip>
+          <a-tooltip title="编辑">
+            <a-button type="link" @click="handleEditTable(record)" v-hasPermi="['tool:gen:edit']">
+              <template #icon><EditOutlined /></template>
+            </a-button>
+          </a-tooltip>
+          <a-tooltip title="删除">
+            <a-button type="link" danger @click="handleDelete(record)" v-hasPermi="['tool:gen:remove']">
+              <template #icon><DeleteOutlined /></template>
+            </a-button>
+          </a-tooltip>
+          <a-tooltip title="同步">
+            <a-button type="link" @click="handleSynchDb(record)" v-hasPermi="['tool:gen:edit']">
+              <template #icon><ReloadOutlined /></template>
+            </a-button>
+          </a-tooltip>
+          <a-tooltip title="生成代码">
+            <a-button type="link" @click="handleGenTable(record)" v-hasPermi="['tool:gen:code']">
+              <template #icon><DownloadOutlined /></template>
+            </a-button>
+          </a-tooltip>
         </template>
-      </el-table-column>
-    </el-table>
+      </template>
+    </a-table>
     <pagination
       v-show="total>0"
       :total="total"
@@ -127,19 +144,21 @@
       @pagination="getList"
     />
     <!-- 预览界面 -->
-    <el-dialog :title="preview.title" v-model="preview.open" width="80%" top="5vh" append-to-body class="scrollbar">
-      <el-tabs v-model="preview.activeName">
-        <el-tab-pane
+    <a-modal :title="preview.title" v-model:open="preview.open" width="80%" :footer="null" :styles="{ top: '5vh' }" class="scrollbar">
+      <a-tabs v-model:activeKey="preview.activeName">
+        <a-tab-pane
           v-for="(value, key) in preview.data"
-          :label="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
-          :name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
-          :key="value"
+          :key="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
+          :tab="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
         >
-          <el-link :underline="false" icon="DocumentCopy" v-copyText="value" v-copyText:callback="copyTextSuccess" style="float:right">&nbsp;复制</el-link>
+          <a-typography-link :underline="false" v-copyText="value" v-copyText:callback="copyTextSuccess" style="float:right">
+            <template #icon><CopyOutlined /></template>
+            &nbsp;复制
+          </a-typography-link>
           <pre>{{ value }}</pre>
-        </el-tab-pane>
-      </el-tabs>
-    </el-dialog>
+        </a-tab-pane>
+      </a-tabs>
+    </a-modal>
     <import-table ref="importRef" @ok="handleQuery" />
     <create-table ref="createRef" @ok="handleQuery" />
   </div>
@@ -150,6 +169,7 @@ import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/
 import router from "@/router"
 import importTable from "./importTable"
 import createTable from "./createTable"
+import { SearchOutlined, ReloadOutlined, DownloadOutlined, PlusOutlined, UploadOutlined, EditOutlined, DeleteOutlined, EyeOutlined, CopyOutlined } from '@ant-design/icons-vue'
 
 const route = useRoute()
 const { proxy } = getCurrentInstance()
@@ -165,6 +185,17 @@ const tableNames = ref([])
 const dateRange = ref([])
 const uniqueId = ref("")
 const defaultSort = ref({ prop: "createTime", order: "descending" })
+const selectedRowKeys = ref([])
+
+// 表格列配置
+const tableColumns = [
+  { title: '表名称', dataIndex: 'tableName', key: 'tableName', align: 'center', ellipsis: true },
+  { title: '表描述', dataIndex: 'tableComment', key: 'tableComment', align: 'center', ellipsis: true },
+  { title: '实体', dataIndex: 'className', key: 'className', align: 'center', ellipsis: true },
+  { title: '创建时间', dataIndex: 'createTime', key: 'createTime', align: 'center', width: 160, sorter: true },
+  { title: '更新时间', dataIndex: 'updateTime', key: 'updateTime', align: 'center', width: 160, sorter: true },
+  { title: '操作', key: 'action', align: 'center', width: 330 }
+]
 
 const data = reactive({
   queryParams: {
@@ -199,7 +230,15 @@ onActivated(() => {
 /** 查询表集合 */
 function getList() {
   loading.value = true
-  listTable(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
+  // 转换日期范围格式
+  let dateRangeFormatted = []
+  if (dateRange.value && dateRange.value.length === 2) {
+    dateRangeFormatted = [
+      dateRange.value[0] ? (typeof dateRange.value[0] === 'string' ? dateRange.value[0] : dateRange.value[0].format('YYYY-MM-DD')) : undefined,
+      dateRange.value[1] ? (typeof dateRange.value[1] === 'string' ? dateRange.value[1] : dateRange.value[1].format('YYYY-MM-DD')) : undefined
+    ]
+  }
+  listTable(proxy.addDateRange(queryParams.value, dateRangeFormatted)).then(response => {
     tableList.value = response.rows
     total.value = response.total
     loading.value = false
@@ -254,7 +293,9 @@ function resetQuery() {
   dateRange.value = []
   proxy.resetForm("queryRef")
   queryParams.value.pageNum = 1
-  proxy.$refs["genRef"].sort(defaultSort.value.prop, defaultSort.value.order)
+  queryParams.value.orderByColumn = defaultSort.value.prop
+  queryParams.value.isAsc = defaultSort.value.order
+  getList()
 }
 
 /** 预览按钮 */
@@ -272,17 +313,20 @@ function copyTextSuccess() {
 }
 
 // 多选框选中数据
-function handleSelectionChange(selection) {
-  ids.value = selection.map(item => item.tableId)
-  tableNames.value = selection.map(item => item.tableName)
-  single.value = selection.length != 1
-  multiple.value = !selection.length
+function handleSelectionChange(selectedKeys, selectedRows) {
+  selectedRowKeys.value = selectedKeys
+  ids.value = selectedRows.map(item => item.tableId)
+  tableNames.value = selectedRows.map(item => item.tableName)
+  single.value = selectedRows.length != 1
+  multiple.value = !selectedRows.length
 }
 
-/** 排序触发事件 */
-function handleSortChange(column, prop, order) {
-  queryParams.value.orderByColumn = column.prop
-  queryParams.value.isAsc = column.order
+/** 表格变化事件(排序、筛选等) */
+function handleTableChange(pagination, filters, sorter) {
+  if (sorter && sorter.field) {
+    queryParams.value.orderByColumn = sorter.field
+    queryParams.value.isAsc = sorter.order === 'ascend' ? 'ascending' : 'descending'
+  }
   getList()
 }
 
@@ -307,3 +351,25 @@ function handleDelete(row) {
 
 getList()
 </script>
+
+<style scoped>
+.search-form {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 0;
+}
+
+.button-toolbar {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+  margin-bottom: 0;
+}
+
+.ant-table-wrapper {
+  background: #fff;
+  padding: 0;
+  border-radius: 4px;
+}
+</style>