使用oracle数据库做的数据上传系统前端
kongdeqiang
2026-03-23 2cfc4ce5ec5095aa7be712444c32de12ffa891e3
fix: 更新系统
4个文件已添加
550 ■■■■■ 已修改文件
src/api/statistics.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/unitTask.js 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/UnitTask.vue 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/statistics/UnitStatistics.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/statistics.js
New file
@@ -0,0 +1,10 @@
import request from '@/utils/request'
export const getUnitStatisticsPage = (params) => {
  return request({
    url: '/data-task/pageNew',
    method: 'get',
    params
  })
}
src/api/unitTask.js
New file
@@ -0,0 +1,39 @@
import request from '@/utils/request'
export const getUnitTaskPage = (params) => {
  return request({
    url: '/data-task/page',
    method: 'get',
    params
  })
}
export const getUnitTaskById = (id) => {
  return request({
    url: `/data-task/${id}`,
    method: 'get'
  })
}
export const createUnitTask = (data) => {
  return request({
    url: '/data-task',
    method: 'post',
    data
  })
}
export const updateUnitTask = (data) => {
  return request({
    url: '/data-task',
    method: 'put',
    data
  })
}
export const deleteUnitTask = (id) => {
  return request({
    url: `/data-task/${id}`,
    method: 'delete'
  })
}
src/views/data/UnitTask.vue
New file
@@ -0,0 +1,307 @@
<template>
  <div class="unit-task-management">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>单位上传任务</span>
          <el-button type="primary" :icon="Plus" @click="handleAdd">新增任务</el-button>
        </div>
      </template>
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="单位">
          <el-select
              v-model="searchForm.unitCode"
              placeholder="请选择单位"
              clearable
              filterable
              style="width: 250px"
          >
            <el-option
                v-for="dept in flatDepartmentList"
                :key="dept.deptCode"
                :label="`${dept.deptCode} - ${dept.deptName}`"
                :value="dept.deptCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
          <el-button :icon="Refresh" @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table :data="tableData" v-loading="loading" border stripe>
        <el-table-column prop="unitCode" label="单位编码" width="150" />
        <el-table-column prop="unitName" label="单位名称" width="300" />
        <el-table-column prop="taskCount" label="任务条数" width="120" />
        <el-table-column prop="createTime" label="创建时间" width="300" />
        <el-table-column prop="updateTime" label="更新时间" width="300" />
        <el-table-column label="操作" fixed="right" >
          <template #default="{ row }">
            <el-button type="primary" link :icon="Edit" @click="handleEdit(row)">编辑</el-button>
            <el-button type="danger" link :icon="Delete" @click="handleDelete(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        v-model:current-page="pagination.currentPage"
        v-model:page-size="pagination.pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        style="margin-top: 20px; justify-content: flex-end"
      />
    </el-card>
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px" @close="handleDialogClose">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="单位" prop="unitCode">
          <el-select
            v-model="form.unitCode"
            placeholder="请选择单位"
            style="width: 100%"
            filterable
            @change="handleUnitChange"
            :disabled="!!form.id"
          >
            <el-option
              v-for="dept in flatDepartmentList"
              :key="dept.deptCode"
              :label="`${dept.deptCode} - ${dept.deptName}`"
              :value="dept.deptCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="单位名称" prop="unitName">
          <el-input v-model="form.unitName" placeholder="选择单位后自动带出" disabled />
        </el-form-item>
        <el-form-item label="任务条数" prop="taskCount">
          <el-input-number v-model="form.taskCount" :min="0" style="width: 100%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Edit, Delete,Refresh,Search } from '@element-plus/icons-vue'
import { getDepartmentTree } from '@/api/department'
import { getUnitTaskPage, createUnitTask, updateUnitTask, deleteUnitTask } from '@/api/unitTask'
const loading = ref(false)
const tableData = ref([])
const dialogVisible = ref(false)
const dialogTitle = ref('')
const formRef = ref(null)
const departmentList = ref([])
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0
})
const form = reactive({
  id: null,
  unitCode: '',
  unitName: '',
  taskCount: 0
})
const searchForm = reactive({
  unitName: '',
  unitCode: ''
})
const rules = {
  unitCode: [{ required: true, message: '请选择单位', trigger: 'change' }],
  unitName: [{ required: true, message: '单位名称不能为空', trigger: 'blur' }],
  taskCount: [{ required: true, message: '请输入任务条数', trigger: 'blur' }]
}
const flatDepartmentList = computed(() => {
  const flatten = (list) => {
    let result = []
    list.forEach(item => {
      result.push(item)
      if (item.children && item.children.length > 0) {
        result = result.concat(flatten(item.children))
      }
    })
    return result
  }
  return flatten(departmentList.value)
})
const buildTree = (list) => {
  const map = {}
  const roots = []
  list.forEach(item => {
    map[item.deptCode] = { ...item, children: [] }
  })
  list.forEach(item => {
    const parent = map[item.parentCode]
    if (parent) {
      parent.children.push(map[item.deptCode])
    } else {
      roots.push(map[item.deptCode])
    }
  })
  const cleanEmptyChildren = (nodes) => {
    nodes.forEach(node => {
      if (node.children && node.children.length === 0) {
        delete node.children
      } else {
        cleanEmptyChildren(node.children)
      }
    })
  }
  cleanEmptyChildren(roots)
  return roots
}
const handleSearch = () => {
  pagination.current = 1
  fetchData()
}
const handleReset = () => {
  searchForm.unitName = ''
  handleSearch()
}
const fetchDepartmentList = async () => {
  try {
    const res = await getDepartmentTree()
    departmentList.value = buildTree(res.data)
  } catch (error) {
    console.error('获取部门列表失败:', error)
  }
}
const fetchData = async () => {
  loading.value = true
  try {
    const res = await getUnitTaskPage({
      page: pagination.currentPage,
      size: pagination.pageSize,
      ...searchForm
    })
    tableData.value = res.data.records || res.data
    pagination.total = res.data.total || res.data.length
  } catch (error) {
    console.error('获取单位上传任务列表失败:', error)
  } finally {
    loading.value = false
  }
}
const handleUnitChange = (value) => {
  const dept = flatDepartmentList.value.find(item => item.deptCode === value)
  if (dept) {
    form.unitName = dept.deptName
  }
}
const handleAdd = () => {
  dialogTitle.value = '新增任务'
  resetForm()
  dialogVisible.value = true
}
const handleEdit = (row) => {
  dialogTitle.value = '编辑任务'
  resetForm()
  Object.assign(form, row)
  dialogVisible.value = true
}
const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm('确定要删除该任务吗?', '提示', {
      type: 'warning'
    })
    await deleteUnitTask(row.id)
    ElMessage.success('删除成功')
    fetchData()
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除任务失败:', error)
    }
  }
}
const handleSubmit = async () => {
  if (!formRef.value) return
  await formRef.value.validate(async (valid) => {
    if (valid) {
      try {
        if (form.id) {
          await updateUnitTask(form)
          ElMessage.success('修改成功')
        } else {
          await createUnitTask(form)
          ElMessage.success('新增成功')
        }
        dialogVisible.value = false
        fetchData()
      } catch (error) {
        console.error('保存任务失败:', error)
      }
    }
  })
}
const handleDialogClose = () => {
  formRef.value?.resetFields()
}
const resetForm = () => {
  form.id = null
  form.unitCode = ''
  form.unitName = ''
  form.taskCount = 0
}
const handleSizeChange = (val) => {
  pagination.pageSize = val
  fetchData()
}
const handleCurrentChange = (val) => {
  pagination.currentPage = val
  fetchData()
}
onMounted(() => {
  fetchDepartmentList()
  fetchData()
})
</script>
<style scoped>
.unit-task-management {
  padding: 20px;
}
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
src/views/statistics/UnitStatistics.vue
New file
@@ -0,0 +1,194 @@
<template>
  <div class="unit-statistics">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>各单位数据统计</span>
        </div>
      </template>
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="单位">
          <el-select
            v-model="searchForm.unitCode"
            placeholder="请选择单位"
            clearable
            filterable
            style="width: 250px"
          >
            <el-option
              v-for="dept in flatDepartmentList"
              :key="dept.deptCode"
              :label="`${dept.deptCode} - ${dept.deptName}`"
              :value="dept.deptCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
          <el-button :icon="Refresh" @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table :data="tableData" v-loading="loading" border stripe>
        <el-table-column prop="unitCode" label="单位编码" width="150" />
        <el-table-column prop="unitName" label="单位名称" width="300" />
        <el-table-column prop="taskCount" label="任务条数" width="120" />
        <el-table-column prop="successCount" label="完成条数" width="120" />
        <el-table-column prop="status" label="完成状态" width="100">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'warning'">
              {{ row.status === 1 ? '已完成' : '未完成' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="lastTime" label="最后上传时间" />
      </el-table>
      <el-pagination
        v-model:current-page="pagination.currentPage"
        v-model:page-size="pagination.pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="pagination.total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        style="margin-top: 20px; justify-content: flex-end"
      />
    </el-card>
  </div>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { Search, Refresh } from '@element-plus/icons-vue'
import { getDepartmentTree } from '@/api/department'
import { getUnitStatisticsPage } from '@/api/statistics'
const loading = ref(false)
const tableData = ref([])
const departmentList = ref([])
const searchForm = reactive({
  unitCode: ''
})
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0
})
const flatDepartmentList = computed(() => {
  const flatten = (list) => {
    let result = []
    list.forEach(item => {
      result.push(item)
      if (item.children && item.children.length > 0) {
        result = result.concat(flatten(item.children))
      }
    })
    return result
  }
  return flatten(departmentList.value)
})
const buildTree = (list) => {
  const map = {}
  const roots = []
  list.forEach(item => {
    map[item.deptCode] = { ...item, children: [] }
  })
  list.forEach(item => {
    const parent = map[item.parentCode]
    if (parent) {
      parent.children.push(map[item.deptCode])
    } else {
      roots.push(map[item.deptCode])
    }
  })
  const cleanEmptyChildren = (nodes) => {
    nodes.forEach(node => {
      if (node.children && node.children.length === 0) {
        delete node.children
      } else {
        cleanEmptyChildren(node.children)
      }
    })
  }
  cleanEmptyChildren(roots)
  return roots
}
const fetchDepartmentList = async () => {
  try {
    const res = await getDepartmentTree()
    departmentList.value = buildTree(res.data)
  } catch (error) {
    console.error('获取部门列表失败:', error)
  }
}
const fetchData = async () => {
  loading.value = true
  try {
    const res = await getUnitStatisticsPage({
      page: pagination.currentPage,
      size: pagination.pageSize,
      unitCode: searchForm.unitCode
    })
    tableData.value = res.data.records || res.data
    pagination.total = res.data.total || res.data.length
  } catch (error) {
    console.error('获取统计数据失败:', error)
  } finally {
    loading.value = false
  }
}
const handleSearch = () => {
  pagination.currentPage = 1
  fetchData()
}
const handleReset = () => {
  searchForm.unitCode = ''
  pagination.currentPage = 1
  fetchData()
}
const handleSizeChange = (val) => {
  pagination.pageSize = val
  fetchData()
}
const handleCurrentChange = (val) => {
  pagination.currentPage = val
  fetchData()
}
onMounted(() => {
  fetchDepartmentList()
  fetchData()
})
</script>
<style scoped>
.unit-statistics {
  padding: 20px;
}
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.search-form {
  margin-bottom: 20px;
}
</style>