ソースを参照

添加 AdminUploadTask.vue 页面

reghao 2 週間 前
コミット
2350ecb004
3 ファイル変更190 行追加2 行削除
  1. 7 2
      src/api/oss.js
  2. 9 0
      src/router/background_oss.js
  3. 174 0
      src/views/admin/oss/AdminUploadTask.vue

+ 7 - 2
src/api/oss.js

@@ -1,4 +1,4 @@
-import {get, post, postForm} from '@/utils/request'
+import { get, post, postForm } from '@/utils/request'
 
 const ossApi = {
   getStoreList: '/api/oss/store/list',
@@ -13,7 +13,8 @@ const ossApi = {
   getChannelList: '/api/oss/channel/list',
   getChannelAttr: '/api/oss/channel/attr',
   addChannel: '/api/oss/channel/add',
-  initChannel: '/api/oss/channel/init'
+  initChannel: '/api/oss/channel/init',
+  uploadTask: '/api/oss/upload_task'
 }
 
 export function getStoreList() {
@@ -67,3 +68,7 @@ export function addChannel(payload) {
 export function initChannel() {
   return post(ossApi.initChannel)
 }
+
+export function getUploadTasks(queryParams) {
+  return get(ossApi.uploadTask + '/list', queryParams)
+}

+ 9 - 0
src/router/background_oss.js

@@ -2,6 +2,7 @@ const Background = () => import('views/admin/Background')
 const AdminStoreNode = () => import('views/admin/oss/AdminStoreNode')
 const AdminUserNode = () => import('views/admin/oss/AdminUserNode')
 const AdminUploadChannel = () => import('views/admin/oss/AdminUploadChannel')
+const AdminUploadTask = () => import('views/admin/oss/AdminUploadTask')
 const AdminStoreObject = () => import('views/admin/oss/AdminStoreObject')
 
 export default {
@@ -37,6 +38,14 @@ export default {
       component: AdminUploadChannel,
       meta: { needAuth: true, roles: ['tnb_admin'] }
     },
+    {
+      path: '/bg/oss/upload_task',
+      name: 'AdminUploadTask',
+      title: '上传任务',
+      icon: 'el-icon-files',
+      component: AdminUploadTask,
+      meta: { needAuth: true, roles: ['tnb_admin'] }
+    },
     {
       path: '/bg/oss/object',
       name: 'AdminStoreObject',

+ 174 - 0
src/views/admin/oss/AdminUploadTask.vue

@@ -0,0 +1,174 @@
+<template>
+  <el-container>
+    <el-header height="80"> <h3>上传任务</h3>
+      <el-row style="margin-top: 10px">
+        <el-select
+          v-model="queryParams.status"
+          clearable
+          placeholder="请选择状态"
+          style="margin-left: 5px"
+          @change="onSelectChange"
+        >
+          <el-option v-for="(item, index) in statusList" :key="index" :label="item.label" :value="item.value" />
+        </el-select>
+        <el-button style="margin-left: 5px" type="plain" icon="el-icon-refresh" @click="getData">刷新</el-button>
+      </el-row>
+    </el-header>
+    <el-main>
+      <el-table
+        :data="dataList"
+        border
+        height="480"
+        style="width: 100%"
+      >
+        <el-table-column
+          fixed="left"
+          label="No"
+          type="index"
+          width="60"
+        />
+        <el-table-column
+          prop="uploadBy"
+          label="上传用户"
+        />
+        <el-table-column
+          prop="hostPort"
+          label="存储节点"
+        />
+        <el-table-column
+          prop="sha256sum"
+          label="sha256sum"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          prop="expireTime"
+          label="过期时间"
+        />
+        <el-table-column
+          prop="size"
+          label="文件大小"
+        ></el-table-column>
+        <el-table-column
+          prop="status"
+          label="状态"
+        >
+          <template slot-scope="scope">
+            <el-tag :type="statusTagMap[scope.row.status] || 'info'" size="small">
+              {{ scope.row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        background
+        :small="screenWidth <= 768"
+        layout="prev, pager, next"
+        :page-size="pageSize"
+        :current-page="currentPage"
+        :total="totalSize"
+        @current-change="handleCurrentChange"
+      />
+    </el-main>
+  </el-container>
+</template>
+
+<script>
+import { getUploadTasks } from '@/api/oss'
+
+export default {
+  name: 'AdminUploadTask',
+  data() {
+    return {
+      queryParams: {
+        pn: 1,
+        status: null
+      },
+      statusList: [
+        { 'label': 'UPLOADING', 'value': '1' },
+        { 'label': 'FLUSHING', 'value': '2' },
+        { 'label': 'AVAILABLE', 'value': '3' }
+      ],
+      // 用于表格 Tag 映射
+      statusTagMap: { 'UPLOADING': 'danger', 'FLUSHING': 'warning', 'AVAILABLE': 'success' },
+      screenWidth: document.body.clientWidth,
+      currentPage: 1,
+      pageSize: 12,
+      totalSize: 0,
+      dataList: []
+    }
+  },
+  watch: {
+    // 🌟 核心侦听器:当 URL 的 query 发生变动时,实时触发数据更新
+    // 这能确保用户点击浏览器“前进/后退”按钮时,页面数据也同步发生变化
+    '$route.query': {
+      handler() {
+        this.syncUrlParamsToForm()
+        this.getData()
+      },
+      deep: true
+    }
+  },
+  created() {
+    // 1. 初始化页面时,先从 URL 中提取参数还原到表单中
+    this.syncUrlParamsToForm()
+    // 2. 执行首次数据加载
+    this.getData()
+  },
+  methods: {
+    // 从 URL 查询参数反向同步到组件的 Data 中
+    syncUrlParamsToForm() {
+      const query = this.$route.query
+      // 如果没有传 pn,则默认为第一页。注意转为 Number 格式
+      this.queryParams.pn = query.pn ? Number(query.pn) : 1
+      this.currentPage = this.queryParams.pn
+
+      // 如果没有状态,设为 null
+      this.queryParams.status = query.status || null
+    },
+
+    // 核心路由更新逻辑:集中把参数写进 URL 地址栏
+    updateUrlQuery() {
+      // 过滤掉为 null、undefined 或空字符串的无效参数,让 URL 更清爽
+      const newQuery = {}
+      if (this.queryParams.pn && this.queryParams.pn !== 1) {
+        newQuery.pn = this.queryParams.pn
+      }
+      if (this.queryParams.status) {
+        newQuery.status = this.queryParams.status
+      }
+
+      // 检查新的 query 是否和当前一致,避免产生相同路由跳转的 Redundant 报错
+      if (JSON.stringify(this.$route.query) !== JSON.stringify(newQuery)) {
+        // 使用 replace 而不是 push,这样不会在浏览器中产生无数个无意义的历史返回记录
+        this.$router.replace({ path: this.$route.path, query: newQuery }).catch(() => {})
+      }
+    },
+
+    getData() {
+      getUploadTasks(this.queryParams).then(resp => {
+        if (resp.code === 0) {
+          this.dataList = resp.data.list
+          this.totalSize = resp.data.totalSize
+        }
+      })
+    },
+
+    handleCurrentChange(pageNumber) {
+      this.queryParams.pn = pageNumber
+      // 不要直接调 getData,而是优先改变 URL,通过 watch 去驱动 getData 触发
+      this.updateUrlQuery()
+      // 回到顶部
+      scrollTo(0, 0)
+    },
+
+    onSelectChange() {
+      // 当选择框变动或被 clearable 清空时,重置页码回第一页
+      this.queryParams.pn = 1
+      this.updateUrlQuery()
+    }
+  }
+}
+</script>
+
+<style scoped>
+</style>