mirror of
https://github.com/fumiama/paper-manager.git
synced 2026-06-28 14:50:29 +08:00
finish filelist/file
This commit is contained in:
@@ -16,4 +16,38 @@ export default [
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
url: '/api/getFileStatus',
|
||||||
|
timeout: 500,
|
||||||
|
method: 'get',
|
||||||
|
response: (request: requestParams) => {
|
||||||
|
const token = getRequestToken(request)
|
||||||
|
if (!token) return resultError('Invalid token')
|
||||||
|
const id = Number(request.query.id)
|
||||||
|
if (!id || id < 0) return resultError('Invalid id')
|
||||||
|
return resultSuccess({
|
||||||
|
name: '100.docx',
|
||||||
|
size: 1.5,
|
||||||
|
questions: [
|
||||||
|
{ count: 4, point: 10, name: '一、填空题' },
|
||||||
|
{ count: 10, point: 20, name: '二、不定项选择题' },
|
||||||
|
{ count: 5, point: 10, name: '三、判断改错题' },
|
||||||
|
{ count: 5, point: 30, name: '四、简述题' },
|
||||||
|
{ count: 4, point: 30, name: '五、综合题' },
|
||||||
|
],
|
||||||
|
duplications: [
|
||||||
|
{ percent: 10, name: '二.1' },
|
||||||
|
{ percent: 20, name: '二.2' },
|
||||||
|
{ percent: 30, name: '二.3' },
|
||||||
|
{ percent: 40, name: '二.4' },
|
||||||
|
{ percent: 50, name: '二.5' },
|
||||||
|
{ percent: 60, name: '二.6' },
|
||||||
|
{ percent: 70, name: '二.7' },
|
||||||
|
{ percent: 80, name: '二.8' },
|
||||||
|
{ percent: 90, name: '二.9' },
|
||||||
|
{ percent: 100, name: '二.10' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
] as MockMethod[]
|
] as MockMethod[]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defHttp } from '/@/utils/http/axios'
|
import { defHttp } from '/@/utils/http/axios'
|
||||||
import { getFileListModel, FilePercent, DelFile, AnalyzeFile } from './model/fileListModel'
|
import { getFileListModel, FilePercent, DelFile, AnalyzeFile } from './model/fileListModel'
|
||||||
import { DownloadFile } from './model/fileModel'
|
import { DownloadFile, FileStatus } from './model/fileModel'
|
||||||
|
|
||||||
enum Api {
|
enum Api {
|
||||||
GetFileList = '/getFileList',
|
GetFileList = '/getFileList',
|
||||||
@@ -8,6 +8,7 @@ enum Api {
|
|||||||
DelFile = '/delFile',
|
DelFile = '/delFile',
|
||||||
AnalyzeFile = '/analyzeFile',
|
AnalyzeFile = '/analyzeFile',
|
||||||
DlFile = '/dlFile',
|
DlFile = '/dlFile',
|
||||||
|
GetFileStatus = '/getFileStatus',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,3 +45,10 @@ export const analyzeFile = (id: number) => {
|
|||||||
export const downloadFile = (id: number) => {
|
export const downloadFile = (id: number) => {
|
||||||
return defHttp.get<DownloadFile>({ url: Api.DlFile, params: { id: id } })
|
return defHttp.get<DownloadFile>({ url: Api.DlFile, params: { id: id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Get file status
|
||||||
|
*/
|
||||||
|
export const getFileStatus = (id: number) => {
|
||||||
|
return defHttp.get<FileStatus>({ url: Api.GetFileStatus, params: { id: id } })
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
export interface DownloadFile {
|
export interface DownloadFile {
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Question {
|
||||||
|
count: number
|
||||||
|
point: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Duplication {
|
||||||
|
percent: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileStatus {
|
||||||
|
name: string
|
||||||
|
size: number
|
||||||
|
questions: Question[]
|
||||||
|
duplications: Duplication[]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper :title="t('routes.filelist.file')">
|
<PageWrapper :title="t('routes.filelist.file') + ': ' + docxNameRef">
|
||||||
<template #headerContent>
|
<template #headerContent>
|
||||||
<a-button type="primary" @click="downloadDocx"> 下载试卷 </a-button>
|
<a-button type="primary" @click="downloadDocx"> 下载试卷 ({{ docxSizeRef }}MB) </a-button>
|
||||||
</template>
|
</template>
|
||||||
<div ref="chartRef" :style="{ height, width }"></div>
|
<div ref="chartRef" :style="{ height, width }"></div>
|
||||||
<div class="docxWrap" :style="{ width }">
|
<div class="docxWrap" :style="{ width }">
|
||||||
@@ -10,14 +10,15 @@
|
|||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, unref, PropType, ref, Ref, onMounted } from 'vue'
|
import { computed, defineComponent, unref, PropType, ref, Ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { PageWrapper } from '/@/components/Page'
|
import { PageWrapper } from '/@/components/Page'
|
||||||
import { useECharts } from '/@/hooks/web/useECharts'
|
import { useECharts } from '/@/hooks/web/useECharts'
|
||||||
import { renderAsync } from 'docx-preview'
|
import { renderAsync } from 'docx-preview'
|
||||||
import { downloadFile } from '/@/api/page'
|
import { downloadFile, getFileStatus } from '/@/api/page'
|
||||||
import { DownloadFile } from '/@/api/page/model/fileModel'
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
import { useGo } from '/@/hooks/web/usePage'
|
import { useGo } from '/@/hooks/web/usePage'
|
||||||
|
import { useTabs } from '/@/hooks/web/useTabs'
|
||||||
import { PageEnum } from '/@/enums/pageEnum'
|
import { PageEnum } from '/@/enums/pageEnum'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n'
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { downloadByData } from '/@/utils/file/download'
|
import { downloadByData } from '/@/utils/file/download'
|
||||||
@@ -27,6 +28,9 @@
|
|||||||
|
|
||||||
let docxRef = ref(null)
|
let docxRef = ref(null)
|
||||||
|
|
||||||
|
let docxNameRef = ref('paper.docx')
|
||||||
|
let docxSizeRef = ref(0)
|
||||||
|
|
||||||
let docxBlob: Blob | null = null
|
let docxBlob: Blob | null = null
|
||||||
|
|
||||||
function loadDocx(file: Blob) {
|
function loadDocx(file: Blob) {
|
||||||
@@ -46,7 +50,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function downloadDocx() {
|
function downloadDocx() {
|
||||||
downloadByData(docxBlob as BlobPart, 'testName.docx')
|
downloadByData(docxBlob as BlobPart, docxNameRef.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -64,6 +68,8 @@
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { currentRoute } = useRouter()
|
const { currentRoute } = useRouter()
|
||||||
|
const { createMessage } = useMessage()
|
||||||
|
const { closeCurrent } = useTabs()
|
||||||
const go = useGo()
|
const go = useGo()
|
||||||
|
|
||||||
const params = computed(() => {
|
const params = computed(() => {
|
||||||
@@ -72,141 +78,167 @@
|
|||||||
|
|
||||||
if (!params.value || !params.value.id) {
|
if (!params.value || !params.value.id) {
|
||||||
go(PageEnum.ERROR_PAGE)
|
go(PageEnum.ERROR_PAGE)
|
||||||
|
closeCurrent()
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFile(Number(params.value.id)).then((file: DownloadFile) => {
|
;(async () => {
|
||||||
if (file && file.url) {
|
try {
|
||||||
axios({
|
const ret = await downloadFile(Number(params.value.id))
|
||||||
method: 'get',
|
if (ret && ret.url) {
|
||||||
responseType: 'blob',
|
const { data } = await axios({
|
||||||
url: file.url,
|
method: 'get',
|
||||||
}).then(({ data }) => {
|
responseType: 'blob',
|
||||||
loadDocx(data)
|
url: ret.url,
|
||||||
})
|
})
|
||||||
} else go(PageEnum.ERROR_PAGE)
|
if (data) {
|
||||||
})
|
loadDocx(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go(PageEnum.ERROR_PAGE)
|
||||||
|
closeCurrent()
|
||||||
|
} catch (error) {
|
||||||
|
createMessage.error('加载docx错误: ' + (error as unknown as Error).message)
|
||||||
|
go(PageEnum.ERROR_PAGE)
|
||||||
|
closeCurrent()
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
const chartRef = ref<HTMLDivElement | null>(null)
|
const chartRef = ref<HTMLDivElement | null>(null)
|
||||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>)
|
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>)
|
||||||
const dataAll = [389, 259, 262, 324, 232, 176, 196, 214, 133, 370]
|
|
||||||
const yAxisData = [
|
;(async () => {
|
||||||
'原因1',
|
try {
|
||||||
'原因2',
|
const ret = await getFileStatus(Number(params.value.id))
|
||||||
'原因3',
|
if (ret && ret.duplications.length > 0 && ret.questions.length > 0) {
|
||||||
'原因4',
|
docxNameRef.value = ret.name
|
||||||
'原因5',
|
docxSizeRef.value = ret.size
|
||||||
'原因6',
|
const barNames = ret.duplications.map((value) => {
|
||||||
'原因7',
|
return value.name
|
||||||
'原因8',
|
})
|
||||||
'原因9',
|
const barData = ret.duplications.map((value) => {
|
||||||
'原因10',
|
return value.percent
|
||||||
]
|
})
|
||||||
onMounted(() => {
|
const queData = ret.questions.map((value) => {
|
||||||
setOptions({
|
return { value: value.count, name: value.name }
|
||||||
title: [
|
})
|
||||||
{
|
const ptData = ret.questions.map((value) => {
|
||||||
text: '题量占比',
|
return { value: value.point, name: value.name }
|
||||||
left: '2%',
|
})
|
||||||
top: '1%',
|
setOptions({
|
||||||
textStyle: {
|
title: [
|
||||||
fontSize: 20,
|
{
|
||||||
},
|
text: '题量占比',
|
||||||
},
|
left: '2%',
|
||||||
{
|
top: '1%',
|
||||||
text: '重复率前十',
|
textStyle: {
|
||||||
left: '40%',
|
fontSize: 20,
|
||||||
top: '1%',
|
},
|
||||||
textStyle: {
|
},
|
||||||
fontSize: 20,
|
{
|
||||||
},
|
text: '重复率前十',
|
||||||
},
|
left: '40%',
|
||||||
{
|
top: '1%',
|
||||||
text: '分数占比',
|
textStyle: {
|
||||||
left: '2%',
|
fontSize: 20,
|
||||||
top: '50%',
|
},
|
||||||
textStyle: {
|
},
|
||||||
fontSize: 20,
|
{
|
||||||
},
|
text: '分数占比',
|
||||||
},
|
left: '2%',
|
||||||
],
|
top: '50%',
|
||||||
grid: [{ left: '50%', top: '7%', width: '45%', height: '90%' }],
|
textStyle: {
|
||||||
tooltip: {
|
fontSize: 20,
|
||||||
formatter: '{b} ({c})',
|
},
|
||||||
},
|
},
|
||||||
xAxis: [
|
|
||||||
{
|
|
||||||
gridIndex: 0,
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLabel: { show: false },
|
|
||||||
splitLine: { show: false },
|
|
||||||
axisLine: { show: false },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
gridIndex: 0,
|
|
||||||
interval: 0,
|
|
||||||
data: yAxisData.reverse(),
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLabel: { show: true },
|
|
||||||
splitLine: { show: false },
|
|
||||||
axisLine: { show: true },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '各渠道投诉占比',
|
|
||||||
type: 'pie',
|
|
||||||
radius: '30%',
|
|
||||||
center: ['22%', '25%'],
|
|
||||||
data: [
|
|
||||||
{ value: 335, name: '客服电话' },
|
|
||||||
{ value: 310, name: '奥迪官网' },
|
|
||||||
{ value: 234, name: '媒体曝光' },
|
|
||||||
{ value: 135, name: '质检总局' },
|
|
||||||
{ value: 105, name: '其他' },
|
|
||||||
],
|
],
|
||||||
labelLine: { show: false },
|
grid: [{ left: '50%', top: '7%', width: '45%', height: '90%' }],
|
||||||
label: {
|
tooltip: {
|
||||||
show: true,
|
formatter: '{b} ({c})',
|
||||||
formatter: '{b} \n ({d}%)',
|
|
||||||
},
|
},
|
||||||
},
|
xAxis: [
|
||||||
{
|
{
|
||||||
name: '各级别投诉占比',
|
gridIndex: 0,
|
||||||
type: 'pie',
|
axisTick: { show: false },
|
||||||
radius: '30%',
|
axisLabel: { show: false },
|
||||||
center: ['22%', '75%'],
|
splitLine: { show: false },
|
||||||
labelLine: { show: false },
|
axisLine: { show: false },
|
||||||
data: [
|
},
|
||||||
{ value: 335, name: 'A级' },
|
|
||||||
{ value: 310, name: 'B级' },
|
|
||||||
{ value: 234, name: 'C级' },
|
|
||||||
{ value: 135, name: 'D级' },
|
|
||||||
],
|
],
|
||||||
label: {
|
yAxis: [
|
||||||
show: true,
|
{
|
||||||
formatter: '{b} \n ({d}%)',
|
gridIndex: 0,
|
||||||
},
|
interval: 0,
|
||||||
},
|
data: barNames,
|
||||||
{
|
axisTick: { show: false },
|
||||||
name: '投诉原因TOP10',
|
axisLabel: { show: true },
|
||||||
type: 'bar',
|
splitLine: { show: false },
|
||||||
xAxisIndex: 0,
|
axisLine: { show: true },
|
||||||
yAxisIndex: 0,
|
},
|
||||||
barWidth: '45%',
|
],
|
||||||
itemStyle: { color: '#86c9f4' },
|
series: [
|
||||||
label: { show: true, position: 'right' },
|
{
|
||||||
data: dataAll.sort(),
|
name: '题量占比',
|
||||||
},
|
type: 'pie',
|
||||||
],
|
radius: '30%',
|
||||||
})
|
center: ['22%', '25%'],
|
||||||
})
|
data: queData,
|
||||||
|
labelLine: { show: false },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
formatter: function (d) {
|
||||||
|
return d.name + '(' + d.value + ')'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分数占比',
|
||||||
|
type: 'pie',
|
||||||
|
radius: '30%',
|
||||||
|
center: ['22%', '75%'],
|
||||||
|
labelLine: { show: false },
|
||||||
|
data: ptData,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
formatter: '{b}\n ({d}%) ',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '重复率前十',
|
||||||
|
type: 'bar',
|
||||||
|
xAxisIndex: 0,
|
||||||
|
yAxisIndex: 0,
|
||||||
|
barWidth: '45%',
|
||||||
|
itemStyle: { color: '#86c9f4' },
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'right',
|
||||||
|
formatter: function (d) {
|
||||||
|
return d.data + '%'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: barData,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go(PageEnum.ERROR_PAGE)
|
||||||
|
closeCurrent()
|
||||||
|
} catch (error) {
|
||||||
|
createMessage.error('加载分析数据错误: ' + (error as unknown as Error).message)
|
||||||
|
go(PageEnum.ERROR_PAGE)
|
||||||
|
closeCurrent()
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
chartRef,
|
chartRef,
|
||||||
docxRef,
|
docxRef,
|
||||||
downloadDocx,
|
downloadDocx,
|
||||||
|
docxNameRef,
|
||||||
|
docxSizeRef,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user