فهرست منبع

[Feat 0000] 系统部署包页面增加历史查询列表

wangkeyi 1 روز پیش
والد
کامیت
e21c72ffe5

+ 136 - 0
src/views/vent/packageUpload/components/DeployHistory.vue

@@ -0,0 +1,136 @@
+<template>
+  <div class="deploy-history">
+    <div class="search-bar">
+      <div class="search-item">
+        <span class="search-label">时间范围:</span>
+        <a-range-picker
+          v-model:value="searchForm.timeRange"
+          show-time
+          format="YYYY-MM-DD HH:mm:ss"
+          :placeholder="['开始时间', '结束时间']"
+          style="width: 360px"
+        />
+      </div>
+      <div class="search-item">
+        <a-button type="primary" @click="handleSearch">
+          <template #icon><search-outlined /></template>
+          查询
+        </a-button>
+        <a-button style="margin-left: 8px" @click="handleReset">
+          <template #icon><reload-outlined /></template>
+          重置
+        </a-button>
+      </div>
+    </div>
+    <BasicTable @register="registerTable" />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { reactive, h } from 'vue';
+  import { SearchOutlined, ReloadOutlined } from '@ant-design/icons-vue';
+  import { Tooltip } from 'ant-design-vue';
+  import dayjs from 'dayjs';
+  import { BasicTable, useTable } from '/@/components/Table';
+  import { deployLogListApi } from '../package.api';
+
+  const searchForm = reactive({
+    timeRange: null as any,
+  });
+
+  function stripAnsi(str: string): string {
+    return str.replace(new RegExp(String.fromCharCode(27) + '\[[0-9;]*m', 'g'), '');
+  }
+
+  function parseLogContent(val: string): string {
+    if (!val) return '';
+    try {
+      const obj = JSON.parse(val);
+      return stripAnsi(obj.msg || '');
+    } catch {
+      return stripAnsi(val);
+    }
+  }
+
+  const columns = [
+    { title: '部署时间', dataIndex: 'createTime', width: 180 },
+    { title: '部署包名称', dataIndex: 'packName', width: 240 },
+    {
+      title: '部署类型',
+      dataIndex: 'packType',
+      width: 120,
+      customRender: ({ text }) => (text === 'jar' ? '后端包' : text === 'page' ? '前端包' : text),
+    },
+    { title: '操作人', dataIndex: 'createBy', width: 120 },
+    {
+      title: '部署结果',
+      dataIndex: 'isSuccess',
+      width: 100,
+      customRender: ({ text }) => (text === 1 ? '成功' : '失败'),
+    },
+    {
+      title: '更新日志',
+      dataIndex: 'logContent',
+      width: 120,
+      customRender: ({ text }) => {
+        const content = parseLogContent(text);
+        return h(Tooltip, { title: content, placement: 'topRight', overlayStyle: { maxWidth: '600px', whiteSpace: 'pre-wrap' } }, () =>
+          h('span', { style: { color: '#0a84ff', cursor: 'pointer' } }, '详情')
+        );
+      },
+    },
+  ];
+
+  const [registerTable, { reload }] = useTable({
+    api: deployLogListApi,
+    columns,
+    rowKey: 'id',
+    pagination: true,
+    bordered: true,
+    showIndexColumn: true,
+    beforeFetch: (params) => {
+      if (searchForm.timeRange && searchForm.timeRange.length === 2) {
+        params.startTime = dayjs(searchForm.timeRange[0]).format('YYYY-MM-DD HH:mm:ss');
+        params.endTime = dayjs(searchForm.timeRange[1]).format('YYYY-MM-DD HH:mm:ss');
+      }
+      params.pageNo = params.pageNo || 1;
+      params.pageSize = params.pageSize || 10;
+      return params;
+    },
+  });
+
+  function handleSearch() {
+    reload();
+  }
+
+  function handleReset() {
+    searchForm.timeRange = null;
+    reload();
+  }
+</script>
+
+<style lang="less" scoped>
+  .deploy-history {
+    .search-bar {
+      margin-bottom: 16px;
+      padding: 16px;
+      background: rgba(255, 255, 255, 0.06);
+      border-radius: 4px;
+      display: flex;
+      align-items: center;
+      gap: 12px;
+
+      .search-item {
+        display: flex;
+        align-items: center;
+        flex-shrink: 0;
+      }
+
+      .search-label {
+        color: #fff;
+        white-space: nowrap;
+        margin-right: 4px;
+      }
+    }
+  }
+</style>

+ 289 - 0
src/views/vent/packageUpload/components/PackageUpload.vue

@@ -0,0 +1,289 @@
+<template>
+  <div class="upload-content">
+    <a-card title="上传部署包" :bordered="true" style="width: 100%">
+      <a-form :label-col="{ span: 4 }" :wrapper-col="{ span: 16 }">
+        <a-form-item label="部署包类型">
+          <a-radio-group v-model:value="packageType">
+            <a-radio value="frontend">前端部署包 (zip)</a-radio>
+            <a-radio value="backend">后端部署包 (jar)</a-radio>
+          </a-radio-group>
+        </a-form-item>
+        <a-form-item label="选择文件">
+          <a-alert type="warning" show-icon style="margin-bottom: 12px">
+            <template #message>
+              <template v-if="packageType === 'frontend'">
+                <span style="font-weight: bold">前端包文件命名规则:</span>
+                <div>
+                  dist + 端口号.zip,例如一通三防智能管控平台前端包为
+                  <b>dist8092.zip</b>
+                </div>
+                <div style="margin-top: 4px; font-weight: bold">上传包时请严格按照命名规则,否则会导致部署失败或引起其他系统问题!!!</div>
+              </template>
+              <template v-else>
+                <span style="font-weight: bold">后端包文件命名规则:</span>
+                <div style="margin-top: 4px">
+                  <div>jeecg-cloud-gateway-3.2.0.jar</div>
+                  <div>jeecg-cloud-nacos-3.2.0.jar</div>
+                  <div>jeecg-cloud-system-start-3.2.0.jar</div>
+                  <div>ventanaly-monitor-3.2.0.jar</div>
+                  <div>ventanaly-model-3.2.0.jar</div>
+                  <div>ventanaly-jingtaifengliang-3.2.0.jar</div>
+                  <div>ventanaly-sharefile-3.2.0.jar</div>
+                  <div>ventanaly-province-3.2.0.jar</div>
+                  <div>ventanaly-ai-service-3.2.0.jar</div>
+                  <div>ventanaly-company-3.2.0.jar</div>
+                </div>
+                <div style="margin-top: 4px; font-weight: bold">上传包时请严格按照命名规则,否则会导致部署失败或引起其他系统问题!!!</div>
+              </template>
+            </template>
+          </a-alert>
+          <a-upload :before-upload="beforeUpload" :file-list="fileList" :remove="handleRemove" :max-count="1">
+            <a-button type="primary">
+              <template #icon><upload-outlined /></template>
+              选择文件
+            </a-button>
+          </a-upload>
+          <div class="file-tip" v-if="fileList.length > 0">
+            <span>已选择: {{ fileList[0]?.name }}</span>
+            <span style="margin-left: 12px; color: #999">({{ formatFileSize(fileList[0]?.size) }})</span>
+            <span v-if="nameWarning" class="name-warning">{{ nameWarning }}</span>
+          </div>
+        </a-form-item>
+        <a-form-item :wrapper-col="{ offset: 4, span: 16 }">
+          <a-button type="primary" danger :loading="deploying" :disabled="fileList.length === 0 || !!nameWarning" @click="handleUploadAndDeploy">
+            <template #icon><cloud-upload-outlined /></template>
+            上传并部署
+          </a-button>
+        </a-form-item>
+      </a-form>
+    </a-card>
+  </div>
+
+  <!-- 全屏loading -->
+  <div class="fullscreen-loading" v-if="deploying">
+    <a-spin size="large" />
+    <span class="loading-text">上传并部署中,请勿关闭或操作页面</span>
+  </div>
+
+  <!-- 部署结果弹框 -->
+  <a-modal v-model:visible="resultVisible" :title="deployIsSuccess ? '部署成功' : '部署失败'" :footer="null" width="600px">
+    <div class="deploy-status-icon" :class="deployIsSuccess ? 'is-success' : 'is-fail'">
+      <template v-if="deployIsSuccess">
+        <span class="icon-check"></span>
+      </template>
+      <template v-else>
+        <span class="icon-cross"></span>
+      </template>
+    </div>
+    <div class="deploy-msg">{{ deployMsg }}</div>
+  </a-modal>
+</template>
+
+<script setup lang="ts">
+  import { ref, watch } from 'vue';
+  import { UploadOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
+  import { message } from 'ant-design-vue';
+  import { uploadProgramApi } from '../package.api';
+
+  const packageType = ref<string>('frontend');
+  const fileList = ref<any[]>([]);
+  const deploying = ref<boolean>(false);
+  const resultVisible = ref<boolean>(false);
+  const deployIsSuccess = ref<boolean>(false);
+  const deployMsg = ref<string>('');
+  const nameWarning = ref<string>('');
+
+  const acceptMap: Record<string, string> = {
+    frontend: '.zip',
+    backend: '.jar',
+  };
+
+  const backendJarNames = [
+    'jeecg-cloud-gateway-3.2.0.jar',
+    'jeecg-cloud-nacos-3.2.0.jar',
+    'jeecg-cloud-system-start-3.2.0.jar',
+    'ventanaly-monitor-3.2.0.jar',
+    'ventanaly-model-3.2.0.jar',
+    'ventanaly-jingtaifengliang-3.2.0.jar',
+    'ventanaly-sharefile-3.2.0.jar',
+    'ventanaly-province-3.2.0.jar',
+    'ventanaly-ai-service-3.2.0.jar',
+    'ventanaly-company-3.2.0.jar',
+  ];
+
+  watch(packageType, () => {
+    fileList.value = [];
+    nameWarning.value = '';
+  });
+
+  function beforeUpload(file) {
+    const accept = acceptMap[packageType.value];
+    const acceptExts = accept.split(',');
+    const ext = '.' + file.name.split('.').pop().toLowerCase();
+    if (!acceptExts.includes(ext)) {
+      message.error(`当前类型仅支持 ${accept} 格式的文件`);
+      return false;
+    }
+    if (packageType.value === 'frontend') {
+      nameWarning.value = /^dist\d+\.zip$/i.test(file.name) ? '' : '包名不符合命名规则,请检查!!!';
+    } else {
+      nameWarning.value = backendJarNames.includes(file.name) ? '' : '包名不符合命名规则,请检查!!!';
+    }
+    fileList.value = [file];
+    return false;
+  }
+
+  function handleRemove() {
+    fileList.value = [];
+    nameWarning.value = '';
+  }
+
+  function formatFileSize(size?: number): string {
+    if (!size) return '0 B';
+    const units = ['B', 'KB', 'MB', 'GB'];
+    let i = 0;
+    let s = size;
+    while (s >= 1024 && i < units.length - 1) {
+      s /= 1024;
+      i++;
+    }
+    return s.toFixed(2) + ' ' + units[i];
+  }
+
+  async function handleUploadAndDeploy() {
+    if (fileList.value.length === 0) {
+      message.warning('请先选择文件');
+      return;
+    }
+    deploying.value = true;
+    try {
+      const res = await uploadProgramApi(fileList.value[0]);
+      const result = res?.result || {};
+      deployIsSuccess.value = result.isSuccess === true;
+      deployMsg.value = result.msg || res?.message || '未知结果';
+      resultVisible.value = true;
+      if (result.isSuccess) {
+        fileList.value = [];
+      }
+    } catch (e: any) {
+      deployIsSuccess.value = false;
+      deployMsg.value = e?.message || '上传请求失败,请检查网络连接';
+      resultVisible.value = true;
+    } finally {
+      deploying.value = false;
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+  @import '/@/design/theme.less';
+
+  .upload-content {
+    :deep(.zxm-card-head-title),
+    :deep(.zxm-form-item-label > label) {
+      color: #fff !important;
+    }
+
+    :deep(.anticon-exclamation-circle) {
+      display: none;
+    }
+
+    .file-tip {
+      margin-top: 8px;
+      font-size: 13px;
+      color: #fff;
+    }
+
+    .name-warning {
+      margin-left: 12px;
+      color: #ff4d4f;
+      font-weight: bold;
+    }
+  }
+
+  .fullscreen-loading {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, 0.45);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    z-index: 9999;
+
+    .loading-text {
+      margin-top: 16px;
+      color: #fff;
+      font-size: 16px;
+    }
+  }
+
+  .deploy-status-icon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 48px;
+    height: 48px;
+    border-radius: 50%;
+    margin: 8px auto 20px;
+
+    &.is-success {
+      background: #52c41a;
+
+      .icon-check {
+        display: block;
+        width: 20px;
+        height: 36px;
+        border: solid #fff;
+        border-width: 0 5px 5px 0;
+        transform: rotate(45deg) translate(-3px, -3px);
+      }
+    }
+
+    &.is-fail {
+      background: #ff4d4f;
+
+      .icon-cross {
+        display: block;
+        width: 32px;
+        height: 32px;
+        position: relative;
+
+        &::before,
+        &::after {
+          content: '';
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          width: 5px;
+          height: 32px;
+          background: #fff;
+          border-radius: 2px;
+        }
+
+        &::before {
+          transform: translate(-50%, -50%) rotate(45deg);
+        }
+
+        &::after {
+          transform: translate(-50%, -50%) rotate(-45deg);
+        }
+      }
+    }
+  }
+
+  .deploy-msg {
+    white-space: pre-wrap;
+    word-break: break-all;
+    max-height: 400px;
+    overflow-y: auto;
+    padding: 12px;
+    border-radius: 4px;
+    font-size: 20px;
+    line-height: 1.6;
+    text-align: center;
+  }
+</style>

+ 26 - 269
src/views/vent/packageUpload/index.vue

@@ -3,181 +3,23 @@
     <div class="upload-header">
       <span class="title">部署包管理</span>
     </div>
-    <div class="upload-content">
-      <a-card title="上传部署包" :bordered="true" style="width: 100%">
-        <a-form :label-col="{ span: 4 }" :wrapper-col="{ span: 16 }">
-          <a-form-item label="部署包类型">
-            <a-radio-group v-model:value="packageType">
-              <a-radio value="frontend">前端部署包 (zip)</a-radio>
-              <a-radio value="backend">后端部署包 (jar)</a-radio>
-            </a-radio-group>
-          </a-form-item>
-          <a-form-item label="选择文件">
-            <a-alert type="warning" show-icon style="margin-bottom: 12px">
-              <template #message>
-                <template v-if="packageType === 'frontend'">
-                  <span style="font-weight: bold">前端包文件命名规则:</span>
-                  <div>
-                    dist + 端口号.zip,例如一通三防智能管控平台前端包为
-                    <b>dist8092.zip</b>
-                  </div>
-                  <div style="margin-top: 4px; font-weight: bold">上传包时请严格按照命名规则,否则会导致部署失败或引起其他系统问题!!!</div>
-                </template>
-                <template v-else>
-                  <span style="font-weight: bold">后端包文件命名规则:</span>
-                  <div style="margin-top: 4px">
-                    <div>jeecg-cloud-gateway-3.2.0.jar</div>
-                    <div>jeecg-cloud-nacos-3.2.0.jar</div>
-                    <div>jeecg-cloud-system-start-3.2.0.jar</div>
-                    <div>ventanaly-monitor-3.2.0.jar</div>
-                    <div>ventanaly-model-3.2.0.jar</div>
-                    <div>ventanaly-jingtaifengliang-3.2.0.jar</div>
-                    <div>ventanaly-sharefile-3.2.0.jar</div>
-                    <div>ventanaly-province-3.2.0.jar</div>
-                    <div>ventanaly-ai-service-3.2.0.jar</div>
-                    <div>ventanaly-company-3.2.0.jar</div>
-                  </div>
-                  <div style="margin-top: 4px; font-weight: bold">上传包时请严格按照命名规则,否则会导致部署失败或引起其他系统问题!!!</div>
-                </template>
-              </template>
-            </a-alert>
-            <a-upload :before-upload="beforeUpload" :file-list="fileList" :remove="handleRemove" :max-count="1">
-              <a-button type="primary">
-                <template #icon><upload-outlined /></template>
-                选择文件
-              </a-button>
-            </a-upload>
-            <div class="file-tip" v-if="fileList.length > 0">
-              <span>已选择: {{ fileList[0]?.name }}</span>
-              <span style="margin-left: 12px; color: #999">({{ formatFileSize(fileList[0]?.size) }})</span>
-              <span v-if="nameWarning" class="name-warning">{{ nameWarning }}</span>
-            </div>
-          </a-form-item>
-          <a-form-item :wrapper-col="{ offset: 4, span: 16 }">
-            <a-button type="primary" danger :loading="deploying" :disabled="fileList.length === 0 || !!nameWarning" @click="handleUploadAndDeploy">
-              <template #icon><cloud-upload-outlined /></template>
-              上传并部署
-            </a-button>
-          </a-form-item>
-        </a-form>
-      </a-card>
-    </div>
-
-    <!-- 全屏loading -->
-    <div class="fullscreen-loading" v-if="deploying">
-      <a-spin size="large" />
-      <span class="loading-text">上传并部署中,请勿关闭或操作页面</span>
-    </div>
-
-    <!-- 部署结果弹框 -->
-    <a-modal v-model:visible="resultVisible" :title="deployIsSuccess ? '部署成功' : '部署失败'" :footer="null" width="600px">
-      <div class="deploy-status-icon" :class="deployIsSuccess ? 'is-success' : 'is-fail'">
-        <template v-if="deployIsSuccess">
-          <span class="icon-check"></span>
-        </template>
-        <template v-else>
-          <span class="icon-cross"></span>
-        </template>
-      </div>
-      <div class="deploy-msg">{{ deployMsg }}</div>
-    </a-modal>
+    <a-tabs v-model:activeKey="activeTab" type="line">
+      <a-tab-pane key="upload" tab="上传部署包">
+        <PackageUpload />
+      </a-tab-pane>
+      <a-tab-pane key="history" tab="部署历史">
+        <DeployHistory />
+      </a-tab-pane>
+    </a-tabs>
   </div>
 </template>
 
 <script setup lang="ts">
-  import { ref, watch } from 'vue';
-  import { UploadOutlined, CloudUploadOutlined } from '@ant-design/icons-vue';
-  import { message } from 'ant-design-vue';
-  import { uploadProgramApi } from './package.api';
-
-  const packageType = ref<string>('frontend');
-  const fileList = ref<any[]>([]);
-  const deploying = ref<boolean>(false);
-  const resultVisible = ref<boolean>(false);
-  const deployIsSuccess = ref<boolean>(false);
-  const deployMsg = ref<string>('');
-  const nameWarning = ref<string>('');
-
-  const acceptMap: Record<string, string> = {
-    frontend: '.zip',
-    backend: '.jar',
-  };
-
-  const backendJarNames = [
-    'jeecg-cloud-gateway-3.2.0.jar',
-    'jeecg-cloud-nacos-3.2.0.jar',
-    'jeecg-cloud-system-start-3.2.0.jar',
-    'ventanaly-monitor-3.2.0.jar',
-    'ventanaly-model-3.2.0.jar',
-    'ventanaly-jingtaifengliang-3.2.0.jar',
-    'ventanaly-sharefile-3.2.0.jar',
-    'ventanaly-province-3.2.0.jar',
-    'ventanaly-ai-service-3.2.0.jar',
-    'ventanaly-company-3.2.0.jar',
-  ];
-
-  watch(packageType, () => {
-    fileList.value = [];
-    nameWarning.value = '';
-  });
-
-  function beforeUpload(file) {
-    const accept = acceptMap[packageType.value];
-    const acceptExts = accept.split(',');
-    const ext = '.' + file.name.split('.').pop().toLowerCase();
-    if (!acceptExts.includes(ext)) {
-      message.error(`当前类型仅支持 ${accept} 格式的文件`);
-      return false;
-    }
-    if (packageType.value === 'frontend') {
-      nameWarning.value = /^dist\d+\.zip$/i.test(file.name) ? '' : '包名不符合命名规则,请检查!!!';
-    } else {
-      nameWarning.value = backendJarNames.includes(file.name) ? '' : '包名不符合命名规则,请检查!!!';
-    }
-    fileList.value = [file];
-    return false;
-  }
+  import { ref } from 'vue';
+  import PackageUpload from './components/PackageUpload.vue';
+  import DeployHistory from './components/DeployHistory.vue';
 
-  function handleRemove() {
-    fileList.value = [];
-    nameWarning.value = '';
-  }
-
-  function formatFileSize(size?: number): string {
-    if (!size) return '0 B';
-    const units = ['B', 'KB', 'MB', 'GB'];
-    let i = 0;
-    let s = size;
-    while (s >= 1024 && i < units.length - 1) {
-      s /= 1024;
-      i++;
-    }
-    return s.toFixed(2) + ' ' + units[i];
-  }
-
-  async function handleUploadAndDeploy() {
-    if (fileList.value.length === 0) {
-      message.warning('请先选择文件');
-      return;
-    }
-    deploying.value = true;
-    try {
-      const res = await uploadProgramApi(fileList.value[0]);
-      const result = res?.result || {};
-      deployIsSuccess.value = result.isSuccess === true;
-      deployMsg.value = result.msg || res?.message || '未知结果';
-      resultVisible.value = true;
-      if (result.isSuccess) {
-        fileList.value = [];
-      }
-    } catch (e: any) {
-      deployIsSuccess.value = false;
-      deployMsg.value = e?.message || '上传请求失败,请检查网络连接';
-      resultVisible.value = true;
-    } finally {
-      deploying.value = false;
-    }
-  }
+  const activeTab = ref<string>('upload');
 </script>
 
 <style lang="less" scoped>
@@ -188,15 +30,6 @@
     height: 100%;
     overflow-y: auto;
 
-    :deep(.zxm-card-head-title),
-    :deep(.zxm-form-item-label > label) {
-      color: #fff !important;
-    }
-
-    :deep(.anticon-exclamation-circle) {
-      display: none;
-    }
-
     .upload-header {
       margin-bottom: 20px;
 
@@ -207,102 +40,26 @@
       }
     }
 
-    .file-tip {
-      margin-top: 8px;
-      font-size: 13px;
-      color: #fff;
-    }
-
-    .name-warning {
-      margin-left: 12px;
-      color: #ff4d4f;
-      font-weight: bold;
-    }
-  }
-
-  .fullscreen-loading {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    background: rgba(0, 0, 0, 0.45);
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    z-index: 9999;
-
-    .loading-text {
-      margin-top: 16px;
-      color: #fff;
-      font-size: 16px;
-    }
-  }
-
-  .deploy-status-icon {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 48px;
-    height: 48px;
-    border-radius: 50%;
-    margin: 8px auto 20px;
-
-    &.is-success {
-      background: #52c41a;
+    :deep(.zxm-tabs-nav) {
+      .zxm-tabs-tab {
+        color: rgba(255, 255, 255, 0.55);
 
-      .icon-check {
-        display: block;
-        width: 20px;
-        height: 36px;
-        border: solid #fff;
-        border-width: 0 5px 5px 0;
-        transform: rotate(45deg) translate(-3px, -3px);
-      }
-    }
-
-    &.is-fail {
-      background: #ff4d4f;
-
-      .icon-cross {
-        display: block;
-        width: 32px;
-        height: 32px;
-        position: relative;
-
-        &::before,
-        &::after {
-          content: '';
-          position: absolute;
-          top: 50%;
-          left: 50%;
-          width: 5px;
-          height: 32px;
-          background: #fff;
-          border-radius: 2px;
+        &:hover {
+          color: rgba(255, 255, 255, 0.85);
         }
 
-        &::before {
-          transform: translate(-50%, -50%) rotate(45deg);
-        }
+        &.zxm-tabs-tab-active {
+          color: #0a84ff;
 
-        &::after {
-          transform: translate(-50%, -50%) rotate(-45deg);
+          .zxm-tabs-tab-btn {
+            color: #0a84ff;
+          }
         }
       }
-    }
-  }
 
-  .deploy-msg {
-    white-space: pre-wrap;
-    word-break: break-all;
-    max-height: 400px;
-    overflow-y: auto;
-    padding: 12px;
-    border-radius: 4px;
-    font-size: 20px;
-    line-height: 1.6;
-    text-align: center;
+      .zxm-tabs-ink-bar {
+        background: #0a84ff;
+      }
+    }
   }
 </style>

+ 7 - 0
src/views/vent/packageUpload/package.api.ts

@@ -3,6 +3,8 @@ import { defHttp } from '/@/utils/http/axios';
 enum Api {
   sysUploadProgram = '/ventanaly-device/safety/common/uploadProgram',
   uploadProgram = '/jeecg-system/sys/common/uploadProgram',
+  deployLogList = '/ventanaly-device/safety/common/deployLogList',
+
 }
 
 /**
@@ -13,3 +15,8 @@ export const uploadProgramApi = async (file: File) => {
   const url = fileName.includes('system') ? Api.sysUploadProgram : Api.uploadProgram;
   return defHttp.uploadFile({ url, timeout: 15 * 60 * 1000 }, { file, name: 'file' }, { isReturnResponse: true });
 };
+
+/**
+ * 部署包历史记录
+ */
+export const deployLogListApi = (params) => defHttp.get({ url: Api.deployLogList, params }, { joinParamsToUrl: true });