123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546 |
- <template>
- <OCRDialog ref="ocrDialog" :title="queueData.title" :queue_category="queueData.queue_category"
- :queue_name="queueData.queue_name" @success="jobCreated"></OCRDialog>
- <QueueSelectDialog ref="queueSelectDialog" :title="'选择队列'" @success="jobMoved" :queue_data="queueIdNameDict">
- </QueueSelectDialog>
- <TextViewDialog ref="textViewDialog" :title="'查看文件'" :content="textViewData"></TextViewDialog>
- <el-row>
- <span style="text-align: right;">
- <h2>工作队列- {{ pageTitle }} </h2>
- </span>
- </el-row>
- <el-row style="margin:15px;">
- <el-form :model="searchForm" :inline="true" label-position="right" :size="'medium'">
- <el-form-item label="任务名称" prop="job_name" :label-width="70" style="margin-left:0px;margin-right:0px;">
- <el-input v-model="searchForm.job_name" :maxlength="32" :size="30"></el-input>
- </el-form-item>
- <el-form-item label="任务类型" prop="start_category" :label-width="70"
- style="margin-left:5px;margin-right:0px;">
- <el-select v-model="searchForm.start_category" placeholder="请选择任务类型" style="width:100px;">
- <el-option v-for="item in jobStartCategoryList" :key="item.id" :label="item.label"
- :value="item.id"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="工序" prop="job_category" :label-width="50" style="margin-left:5px;margin-right:0px;">
- <el-select v-model="searchForm.job_category" placeholder="请选择任务类型" style="width:120px;margin:0px;">
- <el-option v-for="item in jobCategoryList" :key="item.id" :label="item.label"
- :value="item.id"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="状态" prop="status" :label-width="50" style="margin-left:5px;margin-right:0px;">
- <el-select v-model="searchForm.status" placeholder="请选择状态" style="width:120px;">
- <el-option v-for="item in jobStatusList" :key="item.value" :label="item.label"
- :value="item.value"></el-option>
- </el-select>
- </el-form-item>
- <el-form-item style="justify-items: right;margin-left:10px;">
- <el-button type="primary" @click="handleSearch">搜索</el-button>
- <el-button type="primary" @click="handleSearchReset" style="margin-left:5px;">重置</el-button>
- <el-dropdown style="margin-left:5px;">
- <el-button type="primary">
- 新建<i class="el-icon-arrow-down el-icon--right"></i>
- </el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item @click="handleCreateJob('SYSTEM', 'OCR', 'PDF 任务')">PDF
- 任务</el-dropdown-item>
- <el-dropdown-item @click="handleCreateJob('SYSTEM', 'WORD', 'Word 任务')">Word
- 任务</el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- <el-button @click="handleRefreshTable" style="margin-left:5px;" type="success">刷新</el-button>
- </el-form-item>
- </el-form>
- </el-row>
- <el-row>
- <el-table :data="pageData.records" height="650" style="width: 100%;" highlight-current-row
- @current-change="handleCurrentChange">
- <el-table-column prop="id" label="ID" width="50"></el-table-column>
- <el-table-column prop="job_name" label="文件名称" width="200"></el-table-column>
- <el-table-column prop="start_category" label="任务类型" width="200">
- <template v-slot="scope">
- {{ formatJobCategory(scope.row.start_category) }}
- </template>
- </el-table-column>
- <el-table-column prop="job_category" label="当前工序" width="200">
- <template v-slot="scope">
- {{ formatJobCategory(scope.row.job_category) }}
- </template>
- </el-table-column>
- <el-table-column prop="job_creator" label="创建人" width="100"></el-table-column>
- <el-table-column prop="status" label="状态" width="100">
- <template v-slot="scope">
- <el-tag :type="getJobStatusTag(scope.row.status)">{{ formatStatus(scope.row.status) }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="500">
- <template v-slot="scope">
- <el-menu mode="horizontal">
- <el-sub-menu index="1">
- <template #title>操作</template>
- <el-menu-item index="1-1" @click="handleViewJob(scope.row)">查看</el-menu-item>
- <!-- <el-menu-item index="1-2" @click="handlePutJobIntoQueue(scope.row)">移入队列</el-menu-item> -->
- <el-menu-item index="1-3" @click="handleDeleteJob(scope.row)">删除</el-menu-item>
- </el-sub-menu>
- </el-menu>
- </template>
- </el-table-column>
- </el-table>
- </el-row>
- <el-row style="margin-top:30px;">
- <el-pagination background layout="prev, pager, next" :total="pageData.total" :page-size="pageData.page_size"
- @current-change="handleCurrentPageChange" :current-page.sync="pageData.page">
- </el-pagination>
- <span style="margin-left: 20px;">{{ pageData.total }}条记录</span>
- </el-row>
- <el-drawer title="工作详情" v-model="showDrawer" :direction="showDrawerDirection" size="45%">
- <el-tabs type="border-card" v-model="jobDetailsActivateTab">
- <el-tab-pane label="基本信息" name="basic_info">
- <div class="prop_header">任务类型</div>
- <div>{{ currentJob?.start_category }}</div>
- <div class="prop_header">任务名称</div>
- <div>{{ currentJob?.job_name }}</div>
- <div class="prop_header">创建人</div>
- <div>{{ currentJob?.job_creator }}</div>
- <div class="prop_header">创建时间</div>
- <div>{{ formatDate(currentJob?.created) }}</div>
- <div class="prop_header">更新时间</div>
- <div>{{ formatDate(currentJob?.updated) }}</div>
- <div class="prop_header">日志</div>
- <div><el-input type="textarea" :rows="20">{{ currentJob?.job_logs }}</el-input></div>
- </el-tab-pane>
- <el-tab-pane label="文件夹" name="file_browse">
- <el-row>
- <el-col :span="4" style="border-right: 1px solid #CDCDCD;">
- <el-tree :data="jobFileData" :props="jobFileTree" @node-click="handleTreeNodeClick"></el-tree>
- </el-col>
- <el-col :span="20">
- <el-table v-if="jobFileInDir.length > 0" :data="jobFileInDir" highlight-current-row
- style="width: 100%;">
- <el-table-column prop="type" label="类型" width="50">
- </el-table-column>
- <el-table-column prop="name" label="名称" width="250">
- </el-table-column>
- <el-table-column prop="size" label="操作" width="100">
- <template v-slot="scope">
- <a
- :href="'/api/file/download/' + currentJob?.id + '?path=' + encodeURIComponent(scope.row.path)">下载</a>
- <a @click="handleViewFile(currentJob, scope.row.path)">查看</a>
- </template>
- </el-table-column>
- </el-table>
- </el-col>
- </el-row>
- </el-tab-pane>
- </el-tabs>
- </el-drawer>
- </template>
- <script setup lang="ts">
- import { ref, onMounted, watch, watchEffect } from 'vue'
- import { useRoute, useRouter } from 'vue-router'
- import {
- getJob,
- getJobs,
- getStartQueueJobs,
- getQueue,
- browseJobFile,
- getJobStatus,
- getJobStatusTag,
- JobSatus,
- deleteJob,
- updateJob,
- updateJobStatus,
- searchJobs,
- getFileContent
- } from '@/api/AgentApi'
- import type { JobData, SearchData } from '@/api/AgentApi'
- import OCRDialog from '@/dialogs/OCRDialog.vue'
- import QueueSelectDialog from '@/dialogs/QueueSelectDialog.vue'
- import TextViewDialog from '@/dialogs/TextViewDialog.vue'
- import { ElNotification, ElMessageBox } from 'element-plus'
- import { formatTime } from 'element-plus/es/components/countdown/src/utils.mjs'
- import { formatDate } from '@/utils/misc'
- import { getSessionVar, saveSessionVar } from '@/utils/session'
- const router = useRouter()
- //从路由参数中获取队列ID
- interface ViewJobData {
- id: number,
- job_category: string,
- job_name: string,
- job_creator: string,
- created: string,
- updated: string,
- job_logs: string,
- start_category: string,
- }
- const sessionId = ref("")
- const ocrDialog = ref()
- const pageTitle = ref("全部工作")
- const allowCreateJob = ref(false)
- const queueSelectDialog = ref()
- const textViewDialog = ref()
- //const queueId = ref("")
- const queueData = ref({ id: "0", queue_category: "", queue_name: "", title: "" })
- const showDrawer = ref(false)
- const showDrawerDirection = ref('rtl')
- const jobDetailsActivateTab = ref('basic_info')
- const queueIdNameDict = ref([
- { id: "0", name: "DEFAULT", category: 'SYSTEM', title: "全部工作", dialog: null, is_start: false },
- { id: "1", name: "OCR", category: 'SYSTEM', title: "文档OCR", dialog: ocrDialog, is_start: true },
- { id: "2", name: "OCR_RESULTS", title: "OCR结果校对", category: 'SYSTEM', dialog: null, is_start: false },
- { id: "3", name: "CHUNKS", title: "文本切片队列", category: 'SYSTEM', dialog: null, is_start: false },
- { id: "4", name: "KB_EXTRACT", title: "知识抽取", category: 'SYSTEM', dialog: null, is_start: false },
- { id: "5", name: "KB_BUILD", title: "图谱数据构建", category: 'SYSTEM', dialog: null, is_start: false },
- { id: "6", name: "WORD", title: "WORD文档抽取", category: 'SYSTEM', dialog: ocrDialog, is_start: true },
- ])
- const searchForm = ref<SearchData>({ job_name: "", start_category: "SYSTEM_ALL", status: 9999, job_category: "SYSTEM_ALL" })
- const jobStartCategoryList = ref([{ id: "SYSTEM_ALL", label: "所有类型" }, { id: "SYSTEM_WORD", label: "WORD文档抽取" }, { id: "SYSTEM_OCR", label: "PDF文档抽取" }])
- const jobCategoryList = ref([{ id: "SYSTEM_ALL", label: "所有工序" }, { id: "SYSTEM_CHUNKS", label: "文档切片" }, { id: "SYSTEM_KB_EXTRACT", label: "知识抽取" }, { id: "SYSTEM_KB_BUILD", label: "知识构建" }])
- var textViewContent = "hello"
- const textViewData = ref(textViewContent)
- const jobStatusList = ref(JobSatus)
- const jobFileTree = ref({
- children: 'children',
- label: 'display_name'
- })
- const pageData = ref({ page: 1, pages: 1, page_size: 10, total: 0, records: [] })
- const jobFileData = ref([])
- const jobFileInDir = ref([])
- const currentJob = ref<ViewJobData>({ id: 0, job_category: "USER", job_name: "", job_creator: "", created: "", updated: "", job_logs: "no job logs", start_category: "" })
- const currentActionJob = ref({ id: 0, job_category: "USER", job_name: "" })
- const route = useRoute()
- // watchEffect(route, (newValue, oldValue) => {
- // let para = newValue.params.id as string | undefined
- // if (para == undefined) {
- // return
- // }
- // console.log('route changed')
- // //queueId.value = para
- // queueData.value.id = "0"
- // loadQueueData()
- // })
- watchEffect(() => {
- let para = route.params.id as string | undefined
- if (para == undefined) {
- return
- }
- console.log('route changed')
- //queueId.value = para
- queueData.value.id = "0"
- // queueData.value.queue_category = "SYSTEM"
- // queueData.value.queue_name = "ALL"
- // queueData.value.title = "全部工作"
- loadQueueData()
- })
- const handleCreateJob = (category: string, name: string, dialog_title: string) => {
- if (queueData.value.id == "0") {
- ElNotification.info({
- title: '消息',
- message: '工作队列数据正在加载,请稍候再试',
- })
- return
- }
- queueData.value.queue_category = category
- queueData.value.queue_name = name
- queueData.value.title = dialog_title
- let queue_data = queueIdNameDict.value.find((item) => item.category == category && item.name == name)
- if (queue_data == undefined) {
- return
- }
- console.log("HHHH")
- if (queue_data.dialog != undefined) {
- queue_data.dialog.showDialog()
- }
- }
- const handleViewFile = (job: any, path: string) => {
- console.log("handleViewFile")
- const url = '/api/file/view/' + job?.id + '?path=' + encodeURIComponent(path)
- console.log(url)
- getFileContent(url).then((res) => {
- console.log(res)
- textViewData.value = res.records[0].content
- textViewDialog.value.showDialog(true)
- })
- }
- const handleRefreshTable = () => {
- handleCurrentPageChange(pageData.value.page)
- }
- function formatStatus(status: number) {
- return getJobStatus(status)
- }
- function formatJobCategory(category: string) {
- var title = ""
- queueIdNameDict.value.forEach((item) => {
- // console.log(category, 'category')
- if ((item.category + "_" + item.name) == category) {
- // console.log(item.title)
- title = item.title
- }
- })
- return title
- }
- function formatFolderName(name: string) {
- let translate = new Map([
- ["logs", "日志"],
- ["results", "结果"],
- ["chunks", "切片"],
- ["files", "文件"],
- ["ocr_output", "文本转换结果"],
- ["kb_extract", "知识抽取"],
- ["kb_build", "知识构建"],
- ["upload", "文件上传"],
- ["output", "输出"]]
- )
- if (translate.get(name) != undefined) {
- return translate.get(name)
- }
- return name
- }
- function resetViewData() {
- jobFileData.value = []
- jobFileInDir.value = []
- currentJob.value = { id: 0, job_category: "USER", job_name: "", job_creator: "", created: "", updated: "", job_logs: "no job logs", start_category: "" }
- searchForm.value = { job_name: "", start_category: "SYSTEM_ALL", status: 9999, job_category: "SYSTEM_ALL" }
- pageData.value.page = 1
- pageData.value.page_size = 10
- }
- function loadJobs(reset: boolean) {
- console.log("searchJobs")
- if (reset) {
- resetViewData()
- }
- searchJobs(searchForm.value, pageData.value.page, pageData.value.page_size).then((res) => {
- pageData.value.page = res.meta.page
- pageData.value.pages = res.meta.pages
- pageData.value.total = res.meta.total
- pageData.value.records = res.records
- })
- }
- function loadQueueData() {
- jobFileData.value = []
- jobFileInDir.value = []
- //currentJob.value = {id:0,job_category:"USER",job_name:""}
- currentActionJob.value = { id: 0, job_category: "USER", job_name: "" }
- // 根据队列ID获取队列数据
- let queue_data = queueIdNameDict.value.find((item) => item.category == queueData.value.queue_category && item.name == queueData.value.queue_name)
- if (queue_data == undefined) {
- queueData.value = { id: "999", queue_category: 'SYSTEM', queue_name: 'ALL', title: "未知队列" }
- return
- }
- if (queue_data.dialog != null) {
- console.log("queue_data.dialog is allowed")
- allowCreateJob.value = true
- } else {
- allowCreateJob.value = false
- }
- getQueue(queue_data.category, queue_data.name).then((res) => {
- if (res.records.length == 0) {
- return
- }
- queueData.value.id = res.records[0].id
- queueData.value.queue_category = res.records[0].queue_category
- queueData.value.queue_name = res.records[0].queue_name
- queueData.value.title = queue_data.title
- console.log(queueData.value, ' queueData')
- handleCurrentPageChange(1)
- })
- }
- function jobMoved() {
- queueSelectDialog.value.showDialog(null, false)
- var filterdJobs = pageData.value.records.filter((item: JobData) => {
- return item.id != currentActionJob.value.id
- })
- pageData.value.records = filterdJobs
- ElNotification.success({
- title: '成功',
- message: '工作已经移入指定队列了',
- })
- }
- function jobCreated() {
- let queue_data = queueIdNameDict.value.find((item) => item.category == queueData.value.queue_category && item.name == queueData.value.queue_name)
- if (queue_data == undefined) {
- ElNotification.info({
- title: '失败',
- message: '工作队列不存在',
- })
- return
- }
- if (queue_data.dialog != undefined) {
- queue_data.dialog.showDialog(false)
- }
- ElNotification.success({
- title: '成功',
- message: '创建工作成功',
- })
- }
- function handleJobSetStatus(job: JobData, status: number) {
- if (job == null) {
- return
- }
- job.status = status
- updateJobStatus(job).then((res) => {
- handleRefreshTable()
- ElNotification.success({
- title: '成功',
- message: '变更工作状态成功',
- })
- })
- }
- function handleDeleteJob(job: JobData) {
- if (job == null) {
- return
- }
- ElMessageBox.confirm(
- '此操作将永久删除该工作, 是否继续?',
- '提示',
- ).then(() => {
- deleteJob({ job_id: job.id }).then((res) => {
- handleRefreshTable()
- ElNotification.success({
- title: '成功',
- message: '删除工作成功',
- })
- })
- }).catch(() => {
- ElNotification.error({
- title: '失败',
- message: '删除工作失败,请稍后再试',
- })
- })
- }
- function handlePutJobIntoQueue(job: JobData) {
- currentActionJob.value = job
- queueSelectDialog.value.showDialog(job)
- }
- function handleTreeNodeClick(data: any) {
- if (data.type == 'dir') {
- browseJobFile({ job_id: currentJob.value.id, path: data.name }).then((res) => {
- jobFileInDir.value = res.records
- })
- }
- }
- function handleCurrentPageChange(page: number) {
- pageData.value.page = page
- loadJobs(false)
- // let queue_data = queueIdNameDict.value.find((item) => item.id == queueId.value)
- // console.log(queue_data)
- // if (queue_data == undefined) {
- // return
- // }
- // if (queue_data?.is_start == false) {
- // getJobs(queueData.value.queue_category, queueData.value.queue_name, page).then((res) => {
- // pageData.value.page = res.meta.page
- // pageData.value.pages = res.meta.pages
- // pageData.value.total = res.meta.total
- // pageData.value.records = res.records
- // })
- // } else {
- // getStartQueueJobs(queueData.value.queue_category, queueData.value.queue_name, page).then((res) => {
- // pageData.value.page = res.meta.page
- // pageData.value.pages = res.meta.pages
- // pageData.value.total = res.meta.total
- // pageData.value.records = res.records
- // })
- // }
- }
- function handleJobMenuSelect(key: string, keyPath: string[]) {
- console.log(key, keyPath)
- }
- function handleViewJob(job: JobData) {
- if (job == null) {
- return
- }
- router.push({ name: 'job-view', params: { id: job.id } })
- // jobFileData.value = []
- // jobFileInDir.value = []
- // getJob(job.id).then((res) => {
- // currentJob.value = res.records[0]
- // showDrawer.value = true
- // browseJobFile({ job_id:job.id, path:""}).then((res) => {
- // for (let i = 0; i < res.records.length; i++) {
- // res.records[i]['label'] = res.records[i].name
- // res.records[i]['children'] = []
- // res.records[i]['display_name'] = formatFolderName(res.records[i].name)
- // }
- // jobFileData.value = res.records
- // console.log("show drawer")
- // })
- // })
- }
- function handleCurrentChange(data: any) {
- if (data == null) {
- return
- }
- //currentJob.value = data
- }
- function handleSearch() {
- pageData.value.page = 1
- pageData.value.pages = 0
- pageData.value.total = 0
- pageData.value.records = []
- pageTitle.value = "搜索结果"
- loadJobs(false)
- }
- function handleSearchReset() {
- pageData.value.page = 1
- pageData.value.pages = 0
- pageData.value.total = 0
- pageData.value.records = []
- resetViewData()
- pageTitle.value = "全部工作"
- loadJobs(false)
- }
- onMounted(() => {
- sessionId.value = getSessionVar("session_id") as string | ""
- //loadQueueData()
- loadJobs(true)
- })
- </script>
- <style lang="css" scoped>
- .prop_header {
- font-weight: bold;
- margin-top: 10px;
- margin-bottom: 5px;
- }
- .el-dropdown {
- vertical-align: top;
- }
- .el-dropdown+.el-dropdown {
- margin-left: 15px;
- }
- .el-icon-arrow-down {
- font-size: 12px;
- }
- </style>
|