Browse Source

需求更新优化

master
xuhuajiao 3 months ago
parent
commit
36e2085dda
  1. 5
      public/static/config.js
  2. 34
      src/api/ai/ai.js
  3. BIN
      src/assets/images/serve1-1.png
  4. BIN
      src/assets/images/serve1-2.png
  5. BIN
      src/assets/images/serve1-3.png
  6. BIN
      src/assets/images/serve1.png
  7. BIN
      src/assets/images/ter1-1.png
  8. BIN
      src/assets/images/ter1.png
  9. BIN
      src/assets/images/ter2-1.png
  10. BIN
      src/assets/images/ter2.png
  11. BIN
      src/assets/images/ter3-1.png
  12. BIN
      src/assets/images/ter3.png
  13. BIN
      src/assets/images/ter4-1.png
  14. BIN
      src/assets/images/ter4.png
  15. BIN
      src/assets/images/ter5-1.png
  16. BIN
      src/assets/images/ter5.png
  17. 31
      src/assets/styles/archives-manage.scss
  18. 1
      src/assets/styles/index.scss
  19. 4
      src/assets/styles/sidebar.scss
  20. 11
      src/layout/components/Navbar.vue
  21. 2
      src/views/archivesManage/managementLibrary/anjuan/index.vue
  22. 14
      src/views/archivesManage/managementLibrary/anjuan/tableList.vue
  23. 3
      src/views/archivesManage/managementLibrary/file/index.vue
  24. 43
      src/views/archivesManage/managementLibrary/index.vue
  25. 25
      src/views/archivesManage/managementLibrary/juannei/index.vue
  26. 6
      src/views/archivesManage/managementLibrary/mixins/index.js
  27. 42
      src/views/archivesManage/managementLibrary/module/collectHeader.vue
  28. 4
      src/views/archivesStatistics/customDefinedStatistics/index.vue
  29. 6
      src/views/collectReorganizi/batchConnection/index.vue
  30. 6
      src/views/collectReorganizi/collectionLibrary/anjuan/index.vue
  31. 59
      src/views/collectReorganizi/collectionLibrary/file/index.vue
  32. 4
      src/views/collectReorganizi/collectionLibrary/index.vue
  33. 178
      src/views/collectReorganizi/collectionLibrary/juannei/index.vue
  34. 2
      src/views/components/category/PreviewForm.vue
  35. 60
      src/views/components/categoryTree.vue
  36. 220
      src/views/components/echarts/serverGpu.vue
  37. 237
      src/views/components/echarts/serverGpuOther.vue
  38. 219
      src/views/components/echarts/serverGpuUse.vue
  39. 8
      src/views/components/echarts/serverProgress.vue
  40. 275
      src/views/components/echarts/serverProgress2.vue
  41. 314
      src/views/components/serveTerminal.vue
  42. 111
      src/views/home.vue
  43. 12
      src/views/login.vue
  44. 492
      src/views/system/paramSetting/index.vue

5
public/static/config.js

@ -1,7 +1,8 @@
window.g = {
AXIOS_TIMEOUT: 10000,
// ApiUrl: 'http://27.16.212.58:11100', // 配置服务器地址,
ApiUrl: 'http://192.168.99.71:11110',
ApiUrl: 'http://27.19.50.212:11100',
// ApiUrl: 'http://27.16.212.58:11100',
// ApiUrl: 'http://192.168.99.71:11110',
// ApiUrl: 'http://192.168.99.107:11100',
AIDeepSeekUrl:'http://192.168.99.86:12123',
ProcessModelUrl:'http://192.168.99.72:11200',

34
src/api/ai/ai.js

@ -68,4 +68,36 @@ export function FetchDelResearchAI(data) {
})
}
export default { FetchInitAssistEnter, FetchDoHandleEnterAnalysis, FetchInitAssistEnterTemp, FetchDelAssistEnter, FetchHandleEnterAnalysis, FetchInitShowByCategory, FetchEditResearchAI, FetchDelResearchAI }
// AI处理终端 初始化
export function FetchInitSetting(params) {
return request({
url: 'api/ai/initSetting' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export function FetchEditSetting(data) {
return request({
url: 'api/ai/editSetting',
method: 'post',
data
})
}
// AI处理终端状态查询
export function FetchAITerminalStatusQuery(params) {
return request({
url: 'api/ai/AITerminalStatusQuery' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
// 运行/停止图书AI识别程序
export function FetchStartStopBookAIService(params) {
return request({
url: 'api/ai/startStopBookAIService' + '?' + qs.stringify(params, { indices: false }),
method: 'get'
})
}
export default { FetchInitAssistEnter, FetchDoHandleEnterAnalysis, FetchInitAssistEnterTemp, FetchDelAssistEnter, FetchHandleEnterAnalysis, FetchInitShowByCategory, FetchEditResearchAI, FetchDelResearchAI, FetchInitSetting, FetchEditSetting, FetchAITerminalStatusQuery, FetchStartStopBookAIService }

BIN
src/assets/images/serve1-1.png

After

Width: 200  |  Height: 200  |  Size: 3.5 KiB

BIN
src/assets/images/serve1-2.png

After

Width: 200  |  Height: 200  |  Size: 3.1 KiB

BIN
src/assets/images/serve1-3.png

After

Width: 200  |  Height: 200  |  Size: 4.8 KiB

BIN
src/assets/images/serve1.png

After

Width: 200  |  Height: 200  |  Size: 3.5 KiB

BIN
src/assets/images/ter1-1.png

After

Width: 200  |  Height: 200  |  Size: 4.7 KiB

BIN
src/assets/images/ter1.png

After

Width: 200  |  Height: 200  |  Size: 4.7 KiB

BIN
src/assets/images/ter2-1.png

After

Width: 222  |  Height: 200  |  Size: 3.8 KiB

BIN
src/assets/images/ter2.png

After

Width: 222  |  Height: 200  |  Size: 3.8 KiB

BIN
src/assets/images/ter3-1.png

After

Width: 200  |  Height: 200  |  Size: 1.8 KiB

BIN
src/assets/images/ter3.png

After

Width: 200  |  Height: 200  |  Size: 1.8 KiB

BIN
src/assets/images/ter4-1.png

After

Width: 200  |  Height: 200  |  Size: 4.0 KiB

BIN
src/assets/images/ter4.png

After

Width: 200  |  Height: 200  |  Size: 4.0 KiB

BIN
src/assets/images/ter5-1.png

After

Width: 200  |  Height: 200  |  Size: 2.8 KiB

BIN
src/assets/images/ter5.png

After

Width: 200  |  Height: 200  |  Size: 2.8 KiB

31
src/assets/styles/archives-manage.scss

@ -576,6 +576,7 @@
}
// 20230712 抽屉
.el-drawer__wrapper {
position: absolute;
top: -22px;
@ -603,6 +604,36 @@
height: calc(100vh - 173px);
}
.mask-modal{
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
opacity: 0.3;
background: #000;
width: 100%;
height: 100%;
overflow: hidden;
}
.level1-modal{
z-index: 2001;
}
.level2-modal{
z-index: 2003;
}
.level3-modal{
z-index: 2005;
}
.drawer1-modal{
z-index: 2002 !important;
}
.drawer2-modal{
z-index: 2004 !important;
}
.drawer3-modal{
z-index: 2008 !important;
}
.el-drawer{
overflow: visible;
}

1
src/assets/styles/index.scss

@ -133,6 +133,7 @@ ul{
//main-container全局样式
.app-wrapper{
background-color: $main-bg-light;
overflow: hidden;
}
.app-container {

4
src/assets/styles/sidebar.scss

@ -4,8 +4,10 @@
transition: margin-left .28s;
margin-left: $sideBarWidth;
position: relative;
padding-top: $headerHeight;
// padding-top: $headerHeight;
margin-top: 118px;
background-color: $main-bg-light;
z-index: 999;
}
.sidebar-container {

11
src/layout/components/Navbar.vue

@ -218,7 +218,16 @@ export default {
logout() {
this.$store.dispatch('LogOut').then(() => {
location.reload()
localStorage.clear()
// localStorage.clear()
this.clearLocalStorageExceptStatusBar()
})
},
clearLocalStorageExceptStatusBar() {
const keys = Object.keys(localStorage)
keys.forEach(key => {
if (key !== 'statusBarManagement') {
localStorage.removeItem(key)
}
})
},
handleClose(done) {

2
src/views/archivesManage/managementLibrary/anjuan/index.vue

@ -1,5 +1,6 @@
<template>
<div>
<!-- :wrapper-closable="true" -->
<AnjuanContent v-if="selectedCategory.arrangeType === 1 || selectedCategory.arrangeType === 2" ref="ajContent" class="ajContent" :selected-category="selectedCategory" :is-recycle="isRecycle" :smart-query="smartQuery" />
<el-drawer
v-else
@ -7,7 +8,6 @@
:with-header="false"
:visible.sync="anjuanDrawer"
:modal="false"
:wrapper-closable="true"
:show-close="false"
direction="rtl"
size="90%"

14
src/views/archivesManage/managementLibrary/anjuan/tableList.vue

@ -47,20 +47,20 @@
{{ scope.row[field.fieldName] }}
</template>
</el-table-column>
<el-table-column v-if="!isRecycle && selectedCategory.arrangeType===1" label="标签" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle && selectedCategory.arrangeType===1" label="标签" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(1) ? 'right' : false">
<template slot-scope="scope">
<!-- 未绑 / 已绑 -->
<span :class="['row-state', 'row-binding', scope.row.tid ? 'state-active' : '' ]">{{ scope.row.tid ? '已绑': '未绑' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(2) ? 'right' : false">
<!-- state-active 已装/已入/已借/已绑 -->
<template slot-scope="scope">
<!-- 未装 / 已装 -->
<span :class="['row-state', 'row-packing', scope.row.case_no ? 'state-active' : '' ]">{{ scope.row.case_no ? '已装': '未装' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="入库" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="入库" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(3) ? 'right' : false">
<template slot-scope="scope">
<!-- <span class="row-state row-warehousing state-active">已入</span> -->
<span :class="['row-state', 'row-warehousing', scope.row.folder_location ? 'state-active' : '' ]">{{ scope.row.folder_location ? '已入': '未入' }}</span>
@ -68,7 +68,7 @@
<!-- <span :class="['row-state', 'row-warehousing', (storageTxt[scope.$index] === '已入' )? 'state-active' : '' ]">{{ storageTxt[scope.$index] }}</span> -->
</template>
</el-table-column>
<el-table-column v-if="!isRecycle && selectedCategory.arrangeType===1" label="借阅" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle && selectedCategory.arrangeType===1" label="借阅" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(4) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-lending', scope.row.is_borrow ? 'state-active' : '' ]">{{ scope.row.is_borrow ? '已借': '未借' }}</span>
<!-- <span class="row-state row-lending state-active">已借</span> -->
@ -76,17 +76,17 @@
<!-- <span :class="['row-state', 'row-lending', (borrowTxt[scope.$index] === '已借' )? 'state-active' : '' ]">{{ borrowTxt[scope.$index] }}</span> -->
</template>
</el-table-column>
<el-table-column v-if="!isRecycle " label="开放" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle " label="开放" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(5) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-open', scope.row.open_state ? 'state-active' : '' ]">{{ scope.row.open_state ? '已开放': '未开放' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="实体" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="实体" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(6) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-physical', scope.row.is_entity === 1 ? 'state-active' : '' ]">{{ scope.row.is_entity === 1 ? '有': '无' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(7) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-warehousing', scope.row.process_status !== 1 ? 'state-active' : '' ]">{{ processedStatusText(scope.row.process_status) }}</span>
</template>

3
src/views/archivesManage/managementLibrary/file/index.vue

@ -1,11 +1,12 @@
<template>
<div>
<!-- :wrapper-closable="false" -->
<el-drawer
class="management-drawer"
:with-header="false"
:visible.sync="fileDrawer"
:modal="false"
:wrapper-closable="false"
:show-close="false"
direction="rtl"
:size="((selectedCategory.arrangeType === 2 && isAjNo === 0) || (selectedCategory.arrangeType === 3 && isAjNo === 1)) ? '80%' : (isAjNo === 1) ? '90%' : (selectedCategory.arrangeType === 1) ? '90%' : '70%'"

43
src/views/archivesManage/managementLibrary/index.vue

@ -156,7 +156,17 @@ export default {
'print': false,
'endTime': null,
'startTime': null
}
},
fixedStatusSelect: [],
fixedStatusOptions: [
{ value: 1, label: '标签' },
{ value: 2, label: '装盒' },
{ value: 3, label: '入库' },
{ value: 4, label: '借阅' },
{ value: 5, label: '开放' },
{ value: 6, label: '实体' },
{ value: 7, label: '审批锁定' }
]
}
},
computed: {
@ -171,8 +181,19 @@ export default {
created() {
},
mounted() {
this.initStatusBarManagement()
},
methods: {
initStatusBarManagement() {
console.log(localStorage.getItem('statusBarManagement'))
if (!localStorage.getItem('statusBarManagement')) {
this.fixedStatusSelect = [1, 2, 3, 4, 5, 6, 7]
localStorage.setItem('statusBarManagement', JSON.stringify(this.fixedStatusSelect))
} else {
const savedStatuses = JSON.parse(localStorage.getItem('statusBarManagement'))
this.fixedStatusSelect = savedStatuses
}
},
//
getIsAuthByLookType(id) {
const params = {
@ -371,6 +392,26 @@ export default {
this.classifyTree = []
}
this.$nextTick(() => {
if (this.selectedCategory.arrangeType === 1) {
this.fixedStatusOptions = [
{ value: 1, label: '标签' },
{ value: 2, label: '装盒' },
{ value: 3, label: '入库' },
{ value: 4, label: '借阅' },
{ value: 5, label: '开放' },
{ value: 6, label: '实体' },
{ value: 7, label: '审批锁定' }
]
} else {
this.fixedStatusOptions = [
{ value: 2, label: '装盒' },
{ value: 3, label: '入库' },
{ value: 5, label: '开放' },
{ value: 6, label: '实体' },
{ value: 7, label: '审批锁定' }
]
}
this.smartQuery.fonds_no = this.selectedCategory.fondsId
this.getDictsList()
// FetchInitSearchFonds().then(res => {

25
src/views/archivesManage/managementLibrary/juannei/index.vue

@ -1,10 +1,11 @@
<template>
<!-- :wrapper-closable="false" -->
<el-drawer
class="management-drawer"
:with-header="false"
:visible.sync="juanneiDrawer"
:modal="false"
:wrapper-closable="false"
:show-close="false"
direction="rtl"
:size="selectedCategory.arrangeType === 2 ? '90%' :'80%'"
@ -57,46 +58,38 @@
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="标签" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="标签" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(1) ? 'right' : false">
<template slot-scope="scope">
<!-- 未绑 / 已绑 -->
<span :class="['row-state', 'row-binding', scope.row.tid ? 'state-active' : '' ]">{{ scope.row.tid ? '已绑': '未绑' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<!-- state-active 已装/已入/已借/已绑 -->
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(2) ? 'right' : false">
<template slot-scope="scope">
<!-- 未装 / 已装 -->
<span :class="['row-state', 'row-packing', scope.row.case_no ? 'state-active' : '' ]">{{ scope.row.case_no ? '已装': '未装' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="入库" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="入库" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(3) ? 'right' : false">
<template slot-scope="scope">
<!-- <span class="row-state row-warehousing state-active">已入</span> -->
<span :class="['row-state', 'row-warehousing', scope.row.folder_location ? 'state-active' : '' ]">{{ scope.row.folder_location ? '已入': '未入' }}</span>
<!-- is_storage 为空的情况下即没装盒 / 0 未入 / 1 待入 / 2 已入 / 3 待出-->
<!-- <span :class="['row-state', 'row-warehousing', (storageTxt[scope.$index] === '已入' )? 'state-active' : '' ]">{{ storageTxt[scope.$index] }}</span> -->
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="借阅" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="借阅" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(4) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-lending', scope.row.is_borrow ? 'state-active' : '' ]">{{ scope.row.is_borrow ? '已借': '未借' }}</span>
<!-- <span class="row-state row-lending state-active">已借</span> -->
<!-- is_borrow 4 已归还 / 为空 - 未加入待借列表 - 在库 / 2 待借阅在待借列表/借出确认列表 - 待借 / 1待登记 - 不可借- 表示 / 3 待归还 - 已借 -->
<!-- <span :class="['row-state', 'row-lending', (borrowTxt[scope.$index] === '已借' )? 'state-active' : '' ]">{{ borrowTxt[scope.$index] }}</span> -->
</template>
</el-table-column>
<el-table-column v-if="!isRecycle " label="开放" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle " label="开放" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(5) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-open', scope.row.open_state ? 'state-active' : '' ]">{{ scope.row.open_state ? '已开放': '未开放' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="实体" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="实体" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(6) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-physical', scope.row.is_entity === 1 ? 'state-active' : '' ]">{{ scope.row.is_entity === 1 ? '有': '无' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusSelect.includes(7) ? 'right' : false">
<template slot-scope="scope">
<span :class="['row-state', 'row-warehousing', scope.row.process_status !== 1 ? 'state-active' : '' ]">{{ processedStatusText(scope.row.process_status) }}</span>
</template>

6
src/views/archivesManage/managementLibrary/mixins/index.js

@ -29,6 +29,7 @@ export const manageLibraryCrud = {
classifyTree: [],
classifyLoading: false,
parentsId: null
}
},
// 组件挂载时的共用方法
@ -47,6 +48,11 @@ export const manageLibraryCrud = {
this.fixedStatusBar = val
localStorage.setItem('statusBarFixedType', val)
},
handleStatusChange(val) {
this.fixedStatusSelect = val
console.log('val', val)
localStorage.setItem('statusBarManagement', JSON.stringify(val))
},
hasValue(obj) {
for (const key in obj) {
if (obj.hasOwnProperty(key) && obj[key] !== null && obj[key] !== '') {

42
src/views/archivesManage/managementLibrary/module/collectHeader.vue

@ -202,8 +202,26 @@
<el-checkbox-group v-model="parentsData.checklist" class="checkbox-style" @change="handleFilterChange">
<el-checkbox v-for="item in filterlist" :key="item.value" :label="item.value">{{ item.label }}</el-checkbox>
</el-checkbox-group>
<div style="margin-left:30px;">
<el-checkbox v-model="parentsData.fixedStatusBar" @change="statusBarChecked">隐藏状态栏</el-checkbox>
<div style="position: relative;margin-left:30px;">
<!-- <el-checkbox v-model="parentsData.fixedStatusBar" @change="statusBarChecked">状态栏管理</el-checkbox> -->
<el-button class="filter-item filter-refresh" style="border: none; font-weight: normal; padding: 0; cursor: pointer;" size="mini" type="warning" icon="el-icon-setting">状态栏管理</el-button>
<el-select
v-model="parentsData.fixedStatusSelect"
class="select-style-multiple"
multiple
collapse-tags
:clearable="false"
style="position: absolute; right: 0; top:0; width: 80px; opacity: 0; cursor: pointer;"
placeholder="请选择"
@change="handleStatusChange"
>
<el-option
v-for="item in parentsData.fixedStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
</div>
@ -486,8 +504,18 @@ export default {
},
mounted() {
this.getInitArchivesClass()
if (localStorage.getItem('statusBarFixedType') !== 'undefined') {
this.parentsData.fixedStatusBar = JSON.parse(localStorage.getItem('statusBarFixedType')) === true
// if (localStorage.getItem('statusBarFixedType') !== 'undefined') {
// this.parentsData.fixedStatusBar = JSON.parse(localStorage.getItem('statusBarFixedType')) === true
// }
const statusBarManagement = localStorage.getItem('statusBarManagement')
if (statusBarManagement && statusBarManagement !== 'undefined') {
try {
this.parentsData.fixedStatusSelect = JSON.parse(statusBarManagement)
} catch (error) {
this.parentsData.fixedStatusSelect = []
}
} else {
this.parentsData.fixedStatusSelect = []
}
this.getCategoryDataTree()
},
@ -962,4 +990,10 @@ export default {
::v-deep.vue-treeselect--has-value .vue-treeselect__single-value{
font-size: 14px;
}
.select-style-multiple{
::v-deep .el-tag__close {
display: none;
}
}
</style>

4
src/views/archivesStatistics/customDefinedStatistics/index.vue

@ -26,7 +26,7 @@
<!-- <div v-katex:auto class="mdTextBox" v-html="renderMdText(markDownText)" /> -->
<mavon-editor
<!-- <mavon-editor
class="md"
:value="markDownText"
:subfield="false"
@ -35,7 +35,7 @@
:editable="false"
:scroll-style="true"
:ishljs="true"
/>
/> -->
</div>
</div>

6
src/views/collectReorganizi/batchConnection/index.vue

@ -31,7 +31,7 @@
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="id" label="编号" width="120" show-overflow-tooltip />
<el-table-column prop="createBy" label="操作人" />
<el-table-column prop="createTime" label="操作时间" width="200">
<el-table-column prop="createTime" label="操作时间" width="160">
<template slot-scope="scope">
<div>{{ scope.row.createTime | parseTime }}</div>
</template>
@ -41,7 +41,7 @@
{{ scope.row.checkRepeatType === 1 ? '跳过' : (scope.row.checkRepeatType === 2 ? '覆盖' : '追加') }}
</template>
</el-table-column>
<el-table-column prop="queryDetails" label="挂接字段" min-width="200">
<el-table-column prop="queryDetails" label="挂接字段" min-width="200" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.queryDetails.split(",").map(item => "$" + item + "$").join("") }}
</template>
@ -51,7 +51,7 @@
{{ scope.row.matchingMode === 1 ? '全量匹配' : (scope.row.matchingMode === 2 ? '前缀模糊匹配' : '后缀模糊匹配') }}
</template>
</el-table-column>
<el-table-column prop="total" label="挂接结果" width="240">
<el-table-column prop="total" label="挂接结果" min-width="240">
<template slot-scope="scope">
<div> {{ scope.row.total }} 条原文成功<span class="success-status"> {{ scope.row.successNum }} </span>失败<span class="error-status"> {{ scope.row.failNum }} </span></div>
</template>

6
src/views/collectReorganizi/collectionLibrary/anjuan/index.vue

@ -1,20 +1,22 @@
<template>
<div>
<AnjuanContent v-if="selectedCategory.arrangeType === 1 || selectedCategory.arrangeType === 2" ref="ajContent" class="ajContent" :selected-category="selectedCategory" :is-recycle="isRecycle" :smart-query="smartQuery" />
<!-- :wrapper-closable="true" -->
<el-drawer
v-else
class="anjuan-drawer"
class="anjuan-drawer drawer1-modal"
:with-header="false"
:visible.sync="anjuanDrawer"
:modal="false"
:wrapper-closable="true"
:show-close="false"
direction="rtl"
size="90%"
>
<AnjuanContent ref="ajContent" :selected-category="selectedCategory" :is-recycle="isRecycle" :smart-query="smartQuery" />
<span class="closed-btn" @click="closeDrawer" />
</el-drawer>
<div v-if="anjuanDrawer" class="mask-modal level1-modal" @click="closeDrawer" />
</div>
</template>

59
src/views/collectReorganizi/collectionLibrary/file/index.vue

@ -1,12 +1,13 @@
<template>
<div>
<!-- :wrapper-closable="false" -->
<el-drawer
:with-header="false"
:visible.sync="fileDrawer"
:modal="false"
:wrapper-closable="false"
:show-close="false"
direction="rtl"
:class="((selectedCategory.arrangeType === 2 && isAjNo === 0) || (selectedCategory.arrangeType === 3 && isAjNo === 1)) ? 'drawer2-modal' : (isAjNo === 1) ? 'drawer1-modal' : (selectedCategory.arrangeType === 1) ? 'drawer1-modal' : 'drawer3-modal'"
:size="((selectedCategory.arrangeType === 2 && isAjNo === 0) || (selectedCategory.arrangeType === 3 && isAjNo === 1)) ? '80%' : (isAjNo === 1) ? '90%' : (selectedCategory.arrangeType === 1) ? '90%' : '70%'"
>
<CollectHeader ref="collectHeaderRef" :is-title-type="isTitleType" :selected-category="selectedCategory" :selections="selections" :test="test" :is-recycle="isRecycle" />
@ -37,12 +38,12 @@
<!-- <el-table-column type="index" label="序号" width="55" align="center" /> -->
<el-table-column prop="file_name" label="原文名称" show-overflow-tooltip min-width="140" />
<el-table-column prop="file_type" label="格式" min-width="60" align="center" />
<el-table-column prop="file_size" label="大小" min-width="85" align="right">
<el-table-column prop="file_size" label="大小" min-width="80" align="right" show-overflow-tooltip>
<template slot-scope="scope">
{{ getFileSize(scope.row.file_size) }}
</template>
</el-table-column>
<el-table-column prop="file_dpi" label="尺寸" min-width="85" align="center">
<el-table-column prop="file_dpi" label="尺寸" min-width="100" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<div v-if="!scope.row.file_dpi || scope.row.file_dpi === 'null'"> - </div>
<div v-else> {{ scope.row.file_dpi }} </div>
@ -80,7 +81,17 @@
</div>
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" min-width="110" align="center" />
<el-table-column prop="create_time" label="创建时间" min-width="120" align="center" />
<!-- && !recycleMain.isRecycle -->
<el-table-column v-if=" !parentsData.isRecycle" label="操作" min-width="80" align="center">
<template slot-scope="scope">
<div class="handle-btn">
<el-button class="iconfont icon-sulan" @click="toPreview(scope.row)" />
<el-button class="iconfont icon-xiazai" @click="downloadFile(scope.row)" />
<!-- <el-button class="iconfont icon-dayin" /> -->
</div>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
@ -104,6 +115,7 @@
<img style="max-width:100%; object-fit: contain;" :src="previewSrc" :onerror="defaultImg">
</div>
</el-dialog>
<div v-if="fileDrawer" :class="['mask-modal',((selectedCategory.arrangeType === 2 && isAjNo === 0) || (selectedCategory.arrangeType === 3 && isAjNo === 1)) ? 'level2-modal' : (isAjNo === 1) ? 'level1-modal' : (selectedCategory.arrangeType === 1) ? 'level1-modal' : 'level3-modal']" @click="closeDrawer" />
</div>
</template>
@ -112,6 +124,7 @@ import { collectionLibraryCrud } from '../mixins/index'
import { header, form } from '@crud/crud'
import CollectHeader from '../module/collectHeader'
import { mapGetters } from 'vuex'
import { downloadFile } from '@/utils/index'
export default {
name: 'File',
components: { CollectHeader },
@ -149,7 +162,8 @@ export default {
selections: [],
showCoverVisible: false,
previewSrc: null,
currentPage: 1
currentPage: 1,
parentInfo: null
}
},
computed: {
@ -175,6 +189,7 @@ export default {
this.getViewTable(categoryLevel, parentId, type)
},
closeDrawer() {
console.log('关闭文件annnn')
localStorage.removeItem('currentPageSize')
localStorage.removeItem('currentPage')
this.fileDrawer = false
@ -247,6 +262,39 @@ export default {
showCoverPreview(row) {
this.showCoverVisible = true
this.previewSrc = this.baseApi + '/downloadFile' + row.file_path
},
toPreview(row) {
console.log('row', row)
console.log('selectedCategory', row)
console.log('parentsData', this.parentsData)
if (this.selectedCategory.arrangeType === 1) {
this.parentInfo = this.parentsData.parentsAnjuanRow
} else {
this.parentInfo = this.parentsData.parentsJuanneiRow
}
console.log('this.parentInfo', this.parentInfo)
const routeData = this.$router.resolve({
path: '/preview',
query: {
'archiveNo': this.parentInfo.archive_no
}})
window.open(routeData.href, '_blank')
if (localStorage.getItem('documentId')) {
localStorage.removeItem('documentId')
}
localStorage.setItem('fileParentInfo', JSON.stringify(this.parentInfo))
localStorage.setItem('fileTables', JSON.stringify(this.fileData))
localStorage.setItem('fileCurrent', JSON.stringify(row))
},
//
downloadFile(row) {
const url = this.baseApi + '/downloadFile' + row.file_path
fetch(url).then(res => res.blob()).then(blob => {
downloadFile(blob, row.file_name.split('.')[0], row.file_type)
}).catch(() => {
this.$message({ message: '下载文件失败!', type: 'error', offset: 8 })
})
}
}
}
@ -257,4 +305,5 @@ export default {
width: 60px;
height: 32px;
}
</style>

4
src/views/collectReorganizi/collectionLibrary/index.vue

@ -133,6 +133,7 @@ export default {
selectedCategory: {},
yearChildData: '',
parentsAnjuanRow: null,
parentsJuanneiRow: null,
parentsProjectRow: null,
parentsProjectId: null,
parentsAnjuanId: null,
@ -664,9 +665,10 @@ export default {
})
}
},
handleOpenFile(data, parentId) {
handleOpenFile(data, parentId, parentsRow) {
localStorage.removeItem('savePrevFromData')
this.parentsJuanneiId = parentId
this.parentsJuanneiRow = parentsRow
this.$refs.fileEle.fileDrawer = true
this.$nextTick(() => {
this.$refs.fileEle.currentPage = 1

178
src/views/collectReorganizi/collectionLibrary/juannei/index.vue

@ -1,88 +1,92 @@
<template>
<el-drawer
:with-header="false"
:visible.sync="juanneiDrawer"
:modal="false"
:wrapper-closable="false"
:show-close="false"
direction="rtl"
:size="selectedCategory.arrangeType === 2 ? '90%' :'80%'"
>
<collectHeader ref="collectHeaderRef" :is-title-type="isTitleType" :selected-category="selectedCategory" :selections="selections" :test="test" :is-recycle="isRecycle" />
<div class="collect-table">
<el-table
ref="table"
v-loading="crud.loading || getTableDisplayFieldsLoading"
class="archives-table"
:data="junneiData"
highlight-current-row
style="width: 100%;"
height="calc(100vh - 418px)"
:row-class-name="tableRowClassName"
:row-key="rowKey"
@select-all="selectAll"
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
@row-dblclick="tableDoubleClick"
@select="handleCurrentChange"
@mousedown.native="onMouseDown"
@mouseup.native="onMouseUp"
>
<el-table-column type="selection" width="55" :reserve-selection="true" align="center" />
<el-table-column label="序号" width="55" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ page.page * page.size + scope.$index + 1 }}</span>
</template>
</el-table-column>
<!-- <el-table-column type="index" label="序号" width="55" align="center" /> -->
<el-table-column label="原文" prop="child" width="55" align="center">
<template slot-scope="scope">
{{ scope.row.child === '' ? 0 : scope.row.child }}
</template>
</el-table-column>
<el-table-column v-for="field in tableDisplayFields" :key="field.id" :label="field.fieldCnName" :align="field.displayformatType" :width="field.displayLength" show-overflow-tooltip>
<template slot="header">
<el-tooltip
class="item"
effect="dark"
:content="field.fieldCnName"
placement="top-start"
>
<span>{{ field.fieldCnName }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
{{ scope.row[field.fieldName] }}
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<template slot-scope="scope">
<!-- 未装 / 已装 -->
<span :class="['row-state', 'row-packing', scope.row.case_no ? 'state-active' : '' ]">{{ scope.row.case_no ? '已装': '未装' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<template slot-scope="scope">
<span :class="['row-state', 'row-warehousing', scope.row.collect_formal===2 ? 'state-active' : '' ]">{{ scope.row.collect_formal===2 ? '归档': '空闲' }}</span>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
v-if="junneiData.length !== 0"
:current-page="currentPage"
:total="page.total"
:page-size="page.size"
:pager-count="5"
layout="total, prev, pager, next, sizes"
@size-change="handleSizeChange"
@current-change="handleCurrentPage"
/>
</div>
<!-- 档案详情 -->
<ArchivesInfo ref="archivesInfo" :selected-category="selectedCategory" :arc-id="arcId" :is-title-type="isTitleType" :is-collect="true" />
<span class="closed-btn" @click="closeDrawer" />
</el-drawer>
<div>
<!-- :wrapper-closable="false" -->
<el-drawer
:with-header="false"
:visible.sync="juanneiDrawer"
:modal="false"
:show-close="false"
direction="rtl"
:class="selectedCategory.arrangeType === 2 ? 'drawer1-modal' : 'drawer2-modal'"
:size="selectedCategory.arrangeType === 2 ? '90%' :'80%'"
>
<collectHeader ref="collectHeaderRef" :is-title-type="isTitleType" :selected-category="selectedCategory" :selections="selections" :test="test" :is-recycle="isRecycle" />
<div class="collect-table">
<el-table
ref="table"
v-loading="crud.loading || getTableDisplayFieldsLoading"
class="archives-table"
:data="junneiData"
highlight-current-row
style="width: 100%;"
height="calc(100vh - 418px)"
:row-class-name="tableRowClassName"
:row-key="rowKey"
@select-all="selectAll"
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
@row-dblclick="tableDoubleClick"
@select="handleCurrentChange"
@mousedown.native="onMouseDown"
@mouseup.native="onMouseUp"
>
<el-table-column type="selection" width="55" :reserve-selection="true" align="center" />
<el-table-column label="序号" width="55" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ page.page * page.size + scope.$index + 1 }}</span>
</template>
</el-table-column>
<!-- <el-table-column type="index" label="序号" width="55" align="center" /> -->
<el-table-column label="原文" prop="child" width="55" align="center">
<template slot-scope="scope">
{{ scope.row.child === '' ? 0 : scope.row.child }}
</template>
</el-table-column>
<el-table-column v-for="field in tableDisplayFields" :key="field.id" :label="field.fieldCnName" :align="field.displayformatType" :width="field.displayLength" show-overflow-tooltip>
<template slot="header">
<el-tooltip
class="item"
effect="dark"
:content="field.fieldCnName"
placement="top-start"
>
<span>{{ field.fieldCnName }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
{{ scope.row[field.fieldName] }}
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="装盒" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<template slot-scope="scope">
<!-- 未装 / 已装 -->
<span :class="['row-state', 'row-packing', scope.row.case_no ? 'state-active' : '' ]">{{ scope.row.case_no ? '已装': '未装' }}</span>
</template>
</el-table-column>
<el-table-column v-if="!isRecycle" label="审批锁定" width="88" align="center" :fixed="parentsData.fixedStatusBar ? false : 'right' ">
<template slot-scope="scope">
<span :class="['row-state', 'row-warehousing', scope.row.collect_formal===2 ? 'state-active' : '' ]">{{ scope.row.collect_formal===2 ? '归档': '空闲' }}</span>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
v-if="junneiData.length !== 0"
:current-page="currentPage"
:total="page.total"
:page-size="page.size"
:pager-count="5"
layout="total, prev, pager, next, sizes"
@size-change="handleSizeChange"
@current-change="handleCurrentPage"
/>
</div>
<!-- 档案详情 -->
<ArchivesInfo ref="archivesInfo" :selected-category="selectedCategory" :arc-id="arcId" :is-title-type="isTitleType" :is-collect="true" />
<span class="closed-btn" @click="closeDrawer" />
</el-drawer>
<div v-if="juanneiDrawer" :class="['mask-modal',selectedCategory.arrangeType === 2 ? 'level1-modal': 'level2-modal']" @click="closeDrawer" />
</div>
</template>
<script>
@ -147,9 +151,9 @@ export default {
getCommonData(categoryLevel, parentId, type) {
this.getViewTable(categoryLevel, parentId, type)
},
openFile(data, parentId) {
openFile(data, parentId, parentRow) {
// this.$emit('openFile', '')
this.$emit('openFile', data, parentId)
this.$emit('openFile', data, parentId, parentRow)
},
closeDrawer() {
this.juanneiDrawer = false
@ -223,7 +227,7 @@ export default {
this.timer = setTimeout(() => {
this.parentId = row.id
localStorage.removeItem('currentPageSize')
this.openFile('所属卷内:' + row.archive_no, this.parentId)
this.openFile('所属卷内:' + row.archive_no, this.parentId, row)
}, 300)
}
},

2
src/views/components/category/PreviewForm.vue

@ -458,7 +458,6 @@ export default {
// archive_year
if (item.fieldName === 'archive_no') {
const rule = {}
const validateArchiveNo = async(value) => {
let errorMessage = null
if (value === '') {
@ -1197,7 +1196,6 @@ export default {
}
}
}
return false
}
})

60
src/views/components/categoryTree.vue

@ -99,24 +99,37 @@ export default {
this.$nextTick(() => {
let currentKey
if (this.categroyTree[0].isType === 0) {
currentKey = this.findNode(this.categroyTree[0].children, (node) => {
return node.isType !== 1
})
if (localStorage.getItem('currentArchivesKey') !== null) {
currentKey = JSON.parse(localStorage.getItem('currentArchivesKey'))
//
if (this.$refs.categroyTree.getCurrentKey(currentKey.id) == null) {
localStorage.removeItem('currentArchivesKey')
}
this.topLevelNode = this.findTopLevelNode(this.categroyTree, currentKey.fondsId)
//
if (this.topLevelNode) {
if (currentKey) {
//
if (currentKey.isType === 1) {
currentKey = this.findNode(this.categroyTree[0].children, (node) => {
return node.isType !== 1
})
}
this.expandAllChildren(this.$refs.categroyTree.getNode(this.topLevelNode), currentKey)
} else {
this.defaultSetting(currentKey)
}
} else {
this.defaultSetting(currentKey)
}
} else {
currentKey = this.categroyTree[0]
this.defaultSetting(currentKey)
}
if (currentKey.id) {
//
this.$refs.categroyTree.setCurrentKey(currentKey.id)
if (currentKey && currentKey.id) {
this.$nextTick(() => {
//
const selectedKey = this.$refs.categroyTree.getCurrentNode()
if (this.$refs.categroyTree.getNode(selectedKey) && this.$refs.categroyTree.getNode(selectedKey).parent) {
this.expandParents(this.$refs.categroyTree.getNode(selectedKey).parent)
}
//
this.handleNodeClick(selectedKey)
//
console.log('444')
this.handleNodeClick(currentKey)
})
}
})
@ -217,14 +230,21 @@ export default {
return null
},
defaultSetting(currentKey) {
if (this.crud.data[0].isType === 0) {
currentKey = this.findNode(this.crud.data[0].children, (node) => {
if (this.categroyTree[0].isType === 0) {
currentKey = this.findNode(this.categroyTree[0].children, (node) => {
return node.isType !== 1
})
this.expandAllChildren(this.$refs.categroyTree.getNode(this.crud.data[0]), currentKey)
this.expandAllChildren(this.$refs.categroyTree.getNode(this.categroyTree[0]), currentKey)
console.log('currentKey', currentKey)
} else {
currentKey = this.crud.data[0]
this.expandAllChildren(this.$refs.categroyTree.getNode(this.crud.data[0]), currentKey)
currentKey = this.categroyTree[0]
this.expandAllChildren(this.$refs.categroyTree.getNode(this.categroyTree[0]), currentKey)
}
if (currentKey && currentKey.id) {
this.$nextTick(() => {
this.handleNodeClick(currentKey)
})
}
}
}

220
src/views/components/echarts/serverGpu.vue

@ -0,0 +1,220 @@
<template>
<div id="main" :style="{height:height,width:width}" style="margin-top: -20px;" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
temperature: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'temperature': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('main')
const myChart = echarts.init(chartDom)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 60,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(this.temperature)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 14,
color: axisLineHandler(this.temperature)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '50%'],
fontSize: 14,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 26,
fontWeight: 'bolder',
formatter: '{value} °C',
color: 'auto'
},
data: [
{
value: this.temperature,
// name: dataNameHandler(dataValue)
name: '温度'
}
]
},
//
{
type: 'gauge',
radius: 66, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 2,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 7,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

237
src/views/components/echarts/serverGpuOther.vue

@ -0,0 +1,237 @@
<template>
<div id="mainOther" :style="{height:height,width:width}" style="margin-top: -20px;" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
memoryTotal: {
type: Number,
require: true,
default: function() {
return 0
}
},
memoryFree: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'memoryTotal': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
},
'memoryFree': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
// window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('mainOther')
const myChart = echarts.init(chartDom)
const dataValue = this.memoryTotal === 0 ? 0 : ((this.memoryTotal - this.memoryFree) / this.memoryTotal * 100).toFixed(0)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 60,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(dataValue)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 14,
color: axisLineHandler(dataValue)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '50%'],
fontSize: 14,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 26,
fontWeight: 'bolder',
formatter: '{value} %',
color: 'auto'
},
data: [
{
value: dataValue,
name: ((this.memoryTotal - this.memoryFree) / 1024).toFixed(2) + 'G' + ' / ' + (this.memoryTotal / 1024).toFixed(0) + 'G'
}
]
},
//
{
type: 'gauge',
radius: 66, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 1,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 8,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

219
src/views/components/echarts/serverGpuUse.vue

@ -0,0 +1,219 @@
<template>
<div id="mainUse" :style="{height:height,width:width}" />
</template>
<script>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
export default {
name: 'EchartsComponent',
mixins: [resize],
props: {
utilization: {
type: Number,
require: true,
default: function() {
return 0
}
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
}
},
watch: {
'utilization': {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
// window.addEventListener('resize', this.__resizeHandler)
},
methods: {
initChart() {
const chartDom = document.getElementById('mainUse')
const myChart = echarts.init(chartDom)
const axisLineHandler = (value) => {
const ratio = Number(value / 100)
if (ratio <= 0.7) {
return [
[ratio, '#56BC91'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 0.9) {
return [
[ratio, '#FF973E'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
} else if (ratio <= 1) {
return [
[ratio, '#fd666d'], //
[1, 'rgba(216, 216, 216, 1)'] //
]
}
}
const itemStyleHandler = (value) => {
if (value <= 70) {
return `#56BC91`
} else if (value <= 90) {
return `#FF973E`
} else if (value <= 100) {
return `#fd666d`
}
return ''
}
// const dataNameHandler = (value) => {
// if (value <= 60) {
// return value + '°C'
// } else if (value <= 80) {
// return value + '°C'
// } else if (value <= 100) {
// return value + '°C'
// }
// return ''
// }
const option = {
series: [
{
type: 'gauge',
center: ['40%', '38%'],
radius: 120,
startAngle: 200,
endAngle: -20,
min: 0,
max: 100,
splitNumber: 10,
itemStyle: {
color: itemStyleHandler(this.utilization)
},
progress: {
show: true,
width: 20
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 26,
color: axisLineHandler(this.utilization)
}
},
axisTick: {
show: false,
distance: -35,
splitNumber: 5,
lineStyle: {
width: 2,
color: 'auto'
}
},
splitLine: {
show: false,
distance: -42,
length: 14,
lineStyle: {
width: 3,
color: 'auto'
}
},
axisLabel: {
show: false,
distance: -40,
color: 'inherit',
fontSize: 14
},
anchor: {
show: false
},
title: {
show: true,
offsetCenter: [0, '40%'],
fontSize: 18,
color: '#000'
},
detail: {
valueAnimation: true,
width: '60%',
lineHeight: 40,
borderRadius: 8,
offsetCenter: [0, '0'],
fontSize: 40,
fontWeight: 'bolder',
formatter: '{value} %',
color: 'auto'
},
data: [
{
value: this.utilization,
name: '占用率'
}
]
},
//
{
type: 'gauge',
radius: 130, //
center: ['40%', '38%'], //
min: 0,
max: 100,
startAngle: 200,
endAngle: -20,
axisLine: {
show: false,
lineStyle: {
width: 1,
color: '#999'
}
},
axisTick: {
show: true,
splitNumber: 8,
length: 2,
lineStyle: {
width: 1,
color: '#999'
}
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
pointer: {
show: false
},
detail: {
show: false
}
}
]
}
if (option) {
myChart.setOption(option)
}
}
}
}
</script>
<style scoped>
</style>

8
src/views/components/echarts/serverProgress.vue

@ -51,7 +51,7 @@
<p>磁盘占比</p>
<span>{{ systemData.sysFilesPercentage }}<i>%</i></span>
</div>
<div class="progress-class3">
<div class="progress-class3" style="margin-top: -20px;">
<el-progress :show-text="false" type="circle" stroke-linecap="butt" :percentage="systemData.sysFilesPercentage" :stroke-width="20" :width="100" :format="formatterSame" />
<svg width="100%" height="100%">
<defs>
@ -111,7 +111,7 @@ export default {
position: relative;
.chart-wrapper {
height: calc(100% - 55px);
height: calc(100% - 92px);
}
}
@media (max-width: 1024px) {
@ -184,7 +184,7 @@ export default {
.progress-class2{
position: relative;
width: 100px;
height: 100px;
height: 85px;
::v-deep svg > path:nth-child(2) {
stroke: url(#yellow);
}
@ -197,7 +197,7 @@ export default {
.progress-class3{
position: relative;
width: 100px;
height: 100px;
height: 85px;
::v-deep svg > path:nth-child(2) {
stroke: url(#green);
}

275
src/views/components/echarts/serverProgress2.vue

@ -1,275 +0,0 @@
<template>
<div id="main4" :style="{height:height}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons')
import resize from '@/views/dashboard/mixins/resize'
// const gaugeData = [
// {
// value: 20,
// name: 'Perfect',
// title: {
// offsetCenter: ['0%', '-30%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '-20%']
// }
// },
// {
// value: 40,
// name: 'Good',
// title: {
// offsetCenter: ['0%', '0%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '10%']
// }
// },
// {
// value: 60,
// name: 'Commonly',
// title: {
// offsetCenter: ['0%', '30%']
// },
// detail: {
// valueAnimation: true,
// offsetCenter: ['0%', '40%']
// }
// }
// ]
// var ROOT_PATH = 'https://echarts.apache.org/examples/data/asset/img/custom-gauge-panel.png'
// var _panelImageURL = ROOT_PATH + '/data/asset/img/custom-gauge-panel.png'
// var _animationDuration = 1000
// var _animationDurationUpdate = 1000
// var _animationEasingUpdate = 'quarticInOut'
// var _valOnRadianMax = 80
// var _outerRadius = 80
// var _innerRadius = 50
// var _pointerInnerRadius = 50
// var _insidePanelRadius = 30
// var _currentDataIndex = 0
export default {
name: 'AcrossEcharts',
mixins: [resize],
props: {
addArcivesData: {
type: Object,
require: true,
default: function() {
return {}
}
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null,
panelImageURL: 'https://echarts.apache.org/examples/data/asset/img/custom-gauge-panel.png',
animationDuration: 1000,
animationDurationUpdate: 1000,
animationEasingUpdate: 'quarticInOut',
valOnRadianMax: 200,
outerRadius: 200,
innerRadius: 170,
pointerInnerRadius: 40,
insidePanelRadius: 140
}
},
watch: {
// 'addArcivesData': {
// handler(val) {
// setTimeout(() => {
// this.drawChart()
// }, 100)
// },
// immediate: true,
// deep: true
// }
},
mounted() {
this.drawChart()
window.addEventListener('resize', this.__resizeHandler)
},
methods: {
renderItem(params, api) {
var valOnRadian = api.value(1)
var coords = api.coord([api.value(0), valOnRadian])
var polarEndRadian = coords[3]
var imageStyle = {
image: this.panelImageURL,
x: params.coordSys.cx - this.outerRadius,
y: params.coordSys.cy - this.outerRadius,
width: this.outerRadius * 2,
height: this.outerRadius * 2
}
return {
type: 'group',
children: [
{
type: 'image',
style: imageStyle,
clipPath: {
type: 'sector',
shape: {
cx: params.coordSys.cx,
cy: params.coordSys.cy,
r: this.uterRadius,
r0: this.innerRadius,
startAngle: 0,
endAngle: -polarEndRadian,
transition: 'endAngle',
enterFrom: { endAngle: 0 }
}
}
},
{
type: 'image',
style: imageStyle,
clipPath: {
type: 'polygon',
shape: {
points: this.makePionterPoints(params, polarEndRadian)
},
extra: {
polarEndRadian: polarEndRadian,
transition: 'polarEndRadian',
enterFrom: { polarEndRadian: 0 }
},
during: function(apiDuring) {
apiDuring.setShape(
'points',
this.makePionterPoints(params, apiDuring.getExtra('polarEndRadian'))
)
}
}
},
{
type: 'circle',
shape: {
cx: params.coordSys.cx,
cy: params.coordSys.cy,
r: this.insidePanelRadius
},
style: {
fill: '#fff',
shadowBlur: 25,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(76,107,167,0.4)'
}
},
{
type: 'text',
extra: {
valOnRadian: valOnRadian,
transition: 'valOnRadian',
enterFrom: { valOnRadian: 0 }
},
style: {
text: this.makeText(valOnRadian),
fontSize: 30,
fontWeight: 700,
x: params.coordSys.cx,
y: params.coordSys.cy,
fill: 'rgb(0,50,190)',
align: 'center',
verticalAlign: 'middle',
enterFrom: { opacity: 0 }
},
during: function(apiDuring) {
apiDuring.setStyle(
'text',
this.makeText(apiDuring.getExtra('valOnRadian'))
)
}
}
]
}
},
makeText(valOnRadian) {
// Validate additive animation calc.
if (valOnRadian < -10) {
alert('illegal during val: ' + valOnRadian)
}
return ((valOnRadian / this.valOnRadianMax) * 100).toFixed(0) + '%'
},
convertToPolarPoint(renderItemParams, radius, radian) {
return [
Math.cos(radian) * radius + renderItemParams.coordSys.cx,
-Math.sin(radian) * radius + renderItemParams.coordSys.cy
]
},
makePionterPoints(renderItemParams, polarEndRadian) {
return [
this.convertToPolarPoint(renderItemParams, this.outerRadius, polarEndRadian),
this.convertToPolarPoint(
renderItemParams,
this.outerRadius,
polarEndRadian + Math.PI * 0.03
),
this.convertToPolarPoint(renderItemParams, this.pointerInnerRadius, polarEndRadian)
]
},
drawChart() {
const chartDom = document.getElementById('main4')
this.chart = echarts.init(chartDom)
let option = null
option = {
animationEasing: this.animationEasingUpdate,
animationDuration: this.animationDuration,
animationDurationUpdate: this.animationDurationUpdate,
animationEasingUpdate: this.animationEasingUpdate,
dataset: {
source: [[1, 156]]
},
tooltip: {},
angleAxis: {
type: 'value',
startAngle: 0,
show: false,
min: 0,
max: this.valOnRadianMax
},
radiusAxis: {
type: 'value',
show: false
},
polar: {},
series: [
{
type: 'custom',
coordinateSystem: 'polar',
renderItem: this.renderItem
}
]
}
var _this = this
setInterval(function() {
var nextSource = [[1, Math.round(Math.random() * this.valOnRadianMax)]]
_this.chart.setOption({
dataset: {
source: nextSource
}
})
}, 3000)
option && this.chart.setOption(option)
}
}
}
</script>
<style lang="scss" scoped>
</style>

314
src/views/components/serveTerminal.vue

@ -0,0 +1,314 @@
<template>
<div class="service-all">
<div v-if="serviceTop" class="service-top-text" :class="!serviceTop ? 'false-active' : 'true-active'">AI处理终端
<div class="service-left" />
<div class="service-right" />
</div>
<ul v-if="serviceTop" class="service-list">
<li v-for="(item, index) in serviceItems" :key="index">
<p :class="index <= currentIndex && item.status === 'running'? 'true-active' : 'false-active' ">
{{ item.serviceName }}
</p>
</li>
</ul>
<div v-if="servicesDisplayed && isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed && isAllServicesRunning }" style="color: rgb(18, 196, 122);">所有服务均正常运行请放心使用</div>
<div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div>
<div v-if="!serviceTop" class="tip-service" :class="{ 'fade-in': !serviceTop }">
<i class="iconfont icon-lianjieduankai" />
<div class="tip-service-content">
<p>AI处理终端连接超时请检查配置是否正确或终端是否运行成功!</p>
<p>请尽快联系系统维护人员进行恢复</p>
</div>
</div>
</div></template>
<script>
import crudAiTask, { FetchAITerminalStatusQuery } from '@/api/ai/ai'
import { mapGetters } from 'vuex'
export default {
name: 'ServeTerminal',
components: { },
props: {
},
data() {
return {
service: {
'service_FileParsing_v1': { 'last_heartbeat': 1736496962.2368362, 'status': '' },
'service_fileParsing': { 'last_heartbeat': 1736496961.953832, 'status': '' },
'service_imgOCR': { 'last_heartbeat': 1736496961.6238313, 'status': '' },
'service_aiResult': { 'last_heartbeat': 1736496960.8598323, 'status': '' }
},
serviceItems: [],
currentIndex: -1,
timer: null,
servicesDisplayed: false,
serviceTop: false
}
},
computed: {
...mapGetters([
'baseApi'
]),
isAllServicesRunning() {
return Object.values(this.service).every(service => service.status === 'running')
}
},
mounted() {
},
methods: {
initData() {
crudAiTask.FetchInitSetting().then(res => {
if (res) {
this.handleService(res.ip)
}
}).catch(() => {
})
},
handleService(ip) {
this.servicesDisplayed = false
FetchAITerminalStatusQuery({ 'ip': ip }).then(res => {
// {
// "service_FileParsing_v1":{"last_heartbeat":1736496962.2368362,"status":"running"},
// "service_fileParsing":{"last_heartbeat":1736496961.953832,"status":"running"}
// "service_imgOCR":{"last_heartbeat":1736496961.6238313,"status":"running"},
// "service_aiResult":{"last_heartbeat":1736496960.8598323,"status":"running"},
// }
if (res) {
this.serviceTop = true
this.service = JSON.parse(res)
this.serviceItems = []
const keysOrder = ['service_FileParsing_v1', 'service_fileParsing', 'service_imgOCR', 'service_aiResult']
keysOrder.forEach(key => {
let serviceName = ''
switch (key) {
case 'service_FileParsing_v1':
serviceName = '文件解析V1'
break
case 'service_fileParsing':
serviceName = '文件解析'
break
case 'service_imgOCR':
serviceName = '文字识别'
break
case 'service_aiResult':
serviceName = '数据同步'
break
}
this.serviceItems.push({
serviceName: serviceName,
status: this.service[key].status
})
})
this.showServicesSequentially()
} else {
this.serviceTop = false
}
}).catch(() => {
})
},
showServicesSequentially() {
let index = 0
const interval = 300
this.timer = setInterval(() => {
this.currentIndex = index
index++
if (index >= this.serviceItems.length) {
clearInterval(this.timer)
setTimeout(() => {
this.servicesDisplayed = true
}, 500)
}
}, interval)
}
}
}
</script>
<style lang="scss" scoped>
.tip-service{
display: flex;
justify-content: center;
color: #0C0E1E;
font-size: 16px;
line-height: 40px;
padding: 40px 0;
.iconfont{
font-size: 30px;
margin-right: 10px;
color: #ED4A41;
}
p{
&:first-child{
color: #ED4A41;
}
}
}
.service-all{
position: relative;
height: 230px;
color: #0C0E1E;
}
.service-top-text{
position: relative;
font-size: 12px;
margin: 0 77px;
height: 72px;
text-align: center;
background: url('~@/assets/images/serve1.png') no-repeat center center;
background-size: 40px auto;
&.false-active{
background: url('~@/assets/images/serve1-1.png') no-repeat center center;
background-size: 40px auto;
}
&.true-active{
&::after{
content: "";
position: absolute;
right: 0;
bottom: -10px;
width: 67%;
height: 1px;
background-color: #9098a4;
margin-left: -1px;
}
}
}
.service-left{
position: relative;
position: absolute;
left: -1px;
top: 40px;
width: 45%;
height: 82%;
border-top: 1px solid #9098a4;
border-left: 1px solid #9098a4;
}
.service-right{
position: relative;
position: absolute;
right: 33%;
top: 40px;
width: 13%;
height: 74%;
border-top: 1px solid #9098a4;
border-right: 1px solid #9098a4;
}
.service-list{
display: flex;
justify-content: space-between;
align-items: center;
padding: 30px 40px 10px 40px;
li{
position: relative;
&::before{
content: "";
position: absolute;
left: 50%;
top: -20px;
width: 1px;
height: 10px;
background-color: #9098a4;
margin-left: -1px;
}
p{
width: 74px;
height: 70px;
font-size: 12px;
text-align: center;
}
&:nth-child(1){
&::before{
background-color: transparent;
}
p{
&.false-active{
background: url('~@/assets/images/ter1-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter1.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(2){
p{
&.false-active{
background: url('~@/assets/images/ter1-1.png') no-repeat center center;
background-size: 32px auto;
}
&.true-active{
background: url('~@/assets/images/ter1.png') no-repeat center center;
background-size: 32px auto;
}
}
}
&:nth-child(3){
&::before{
background-color: transparent;
}
p{
&.false-active{
background: url('~@/assets/images/ter3-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter3.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(4){
p{
&.false-active{
background: url('~@/assets/images/ter4-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter4.png') no-repeat center center;
background-size: 36px auto;
}
}
}
&:nth-child(5){
p{
&.false-active{
background: url('~@/assets/images/ter5-1.png') no-repeat center center;
background-size: 36px auto;
}
&.true-active{
background: url('~@/assets/images/ter5.png') no-repeat center center;
background-size: 36px auto;
}
}
}
}
}
.service-bottom-text{
font-size: 12px;
text-align: center;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.5s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
.fade-in {
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>

111
src/views/home.vue

@ -39,10 +39,35 @@
<span class="left-bottom-line" />
<h3 class="home-item-title">
服务器监控
<div style="position: absolute; right: 20px; top: 20px; color: #999; cursor: pointer;" class="el-icon-refresh" @click="refreshSystemData" />
</h3>
<!-- <div class="chart-wrapper"> -->
<serverProgress :system-data="systemData" />
<!-- </div> -->
<!-- <serverProgress :system-data="systemData" /> -->
<!-- <serveTerminal ref="serveTerminalRefs" /> -->
<swiper
ref="swiperServer"
class="swiper-server"
:options="swiperOptionServer"
:auto-update="true"
:auto-destroy="true"
:delete-instance-on-destroy="true"
:cleanup-styles-on-destroy="true"
>
<swiper-slide class="swiper-slide-server">
<serverProgress :system-data="systemData" />
</swiper-slide>
<swiper-slide class="swiper-slide-server cpu-echarts">
<serverGpuUse :utilization="utilization" />
<div class="cpu-right">
<serverGpu :temperature="temperature" />
<serverGpuOther :memory-total="memoryTotal" :memory-free="memoryFree" />
</div>
<div style="position: absolute; bottom: 136px; right: 70px; font-weight: bold;">{{ GPUName }}</div>
</swiper-slide>
<swiper-slide class="swiper-slide-server">
<serveTerminal ref="serveTerminalRefs" />
</swiper-slide>
<div slot="pagination" class="swiper-pagination" />
</swiper>
</div>
</el-col>
</el-row>
@ -105,9 +130,15 @@ import lendAcross from '@/views/components/echarts/lendAcross.vue'
import catePie from '@/views/components/echarts/catePie.vue'
import typePie from '@/views/components/echarts/typePie.vue'
import serverProgress from '@/views/components/echarts/serverProgress.vue'
import serverGpu from '@/views/components/echarts/serverGpu.vue'
import serverGpuUse from '@/views/components/echarts/serverGpuUse.vue'
import serverGpuOther from '@/views/components/echarts/serverGpuOther.vue'
import serveTerminal from '@/views/components/serveTerminal.vue'
import { FetchMainData } from '@/api/archivesManage/library'
import { FetchSystemInfo } from '@/api/home/cpu/index'
import { mapGetters } from 'vuex'
import { swiper, swiperSlide } from 'vue-awesome-swiper'
import 'swiper/css/swiper.css'
export default {
name: 'Dashboard',
@ -116,7 +147,13 @@ export default {
lendAcross,
catePie,
typePie,
serverProgress
serverProgress,
serveTerminal,
serverGpu,
serverGpuUse,
serverGpuOther,
swiper,
swiperSlide
},
data() {
return {
@ -148,7 +185,20 @@ export default {
cpuPercentage: 0,
memPercentage: 0,
sysFilesPercentage: 0
}
},
swiperOptionServer: {
autoplay: false,
slidesPerView: 'auto',
pagination: {
el: '.swiper-pagination',
clickable: true
}
},
memoryFree: 0,
memoryTotal: 0,
GPUName: '',
temperature: 0,
utilization: 0
}
},
computed: {
@ -159,7 +209,9 @@ export default {
created() {
this.handleMainData()
this.getSystemInfo()
// this.get()
this.$nextTick(() => {
this.$refs.serveTerminalRefs.initData()
})
},
mounted() {
// const _this = this
@ -191,6 +243,21 @@ export default {
// }, 3000)
},
methods: {
refreshSystemData() {
this.systemData = {
cpuPercentage: 0,
memPercentage: 0,
sysFilesPercentage: 0
}
this.memoryFree = 0
this.memoryTotal = 0
this.GPUName = ''
this.temperature = 0
this.utilization = 0
this.getSystemInfo()
this.$refs.serveTerminalRefs.initData()
},
getSystemInfo() {
FetchSystemInfo().then(res => {
// cpu cpuTotal-cpuFree/cpuTotal
@ -207,6 +274,12 @@ export default {
sysFilesTotal += parseFloat(item.total)
})
this.systemData.sysFilesPercentage = Math.round((sysFilesTotalUsed / sysFilesTotal) * 100)
this.memoryFree = res.memoryFree
this.memoryTotal = res.memoryTotal
this.GPUName = res.GPUName
this.temperature = res.temperature
this.utilization = res.utilization
})
},
toMoreProcess() {
@ -312,7 +385,7 @@ export default {
position: relative;
.chart-wrapper {
height: calc(100% - 55px);
height: calc(100% - 92px);
}
}
@media (max-width: 1024px) {
@ -386,4 +459,28 @@ export default {
::v-deep .home-flowable-list .el-table__body-wrapper::-webkit-scrollbar-corner {
background-color: #DDE8FB !important;
}
.swiper-server{
position: relative;
height: 300px;
::v-deep .swiper-wrapper{
height: 344px;
}
.swiper-pagination{
bottom: 80px;
}
}
.cpu-echarts{
position: relative;
display: flex;
justify-content: flex-start;
align-items: center;
.cpu-right{
flex: 1;
height: 100%;
display: flex;
justify-content: flex-start;
}
}
</style>

12
src/views/login.vue

@ -124,7 +124,9 @@ export default {
}
},
created() {
localStorage.clear()
// localStorage.clear()
//
this.clearLocalStorageExceptStatusBar()
//
this.getCode()
// Cookie
@ -133,6 +135,14 @@ export default {
this.point()
},
methods: {
clearLocalStorageExceptStatusBar() {
const keys = Object.keys(localStorage)
keys.forEach(key => {
if (key !== 'statusBarManagement') {
localStorage.removeItem(key)
}
})
},
getCode() {
getCodeImg().then((res) => {
this.codeUrl = res.img

492
src/views/system/paramSetting/index.vue

@ -0,0 +1,492 @@
<template>
<div class="app-container row-container">
<div class="container-wrap" style="height: calc(100vh - 200px);">
<span class="right-top-line" />
<span class="left-bottom-line" />
<el-form ref="form" :rules="rules" :model="form" size="small" label-width="120px">
<el-row style="display: flex; justify-content: flex-start;">
<el-form-item label="AI处理终端IP" prop="ip">
<el-input v-model="form.ip" placeholder="请输入IP地址,如:192.168.1.1" style="width: 300px;" />
</el-form-item>
<div v-if="form.ip" style="margin-left: 20px; margin-top: 6px; cursor: pointer;" @click="handleService"><i class="iconfont icon-bendiguajie" /></div>
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后方可执行视觉盘点任务</p>
<div style="margin-left: 20px;">
<el-button :loading="resetLoading" @click="toVerify('reset')">重启服务</el-button>
<!-- <el-button>关闭</el-button> -->
</div>
</el-row>
<!-- <el-row style="display: flex; justify-content: flex-start;">
<el-form-item label="层位占用上限" prop="maxNum">
<el-input v-model="form.maxNum" type="number" placeholder="请输入" style="width: 300px;" />
</el-form-item>
<p style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置成功后方可在倒架建议中给出正确的数据通常情况下上限为 50 </p>
</el-row> -->
</el-form>
<div>
<el-button style="margin-left: 30px;" :loading="crud.status.cu === 2" type="primary" @click="toVerify('add')">保存</el-button>
<span style="line-height: 32px; margin-left: 20px; font-size: 12px;">设置需要超级管理员权限授权</span>
</div>
</div>
<el-dialog class="tip-dialog tip-middle-dialog" title="操作提示" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="verifyDialogVisible" :before-close="handleClose">
<div class="setting-dialog">
<div class="tip-content">
<p class="tipMsg">这里为技术人员维护系统时使用普通用户无需设置</p>
<p class="delt-tip"><span>注意强行修改会导致系统数据异常或丢失如因用户强行修改本系统不负责因此导致的相关后果</span></p>
</div>
<el-form ref="verfiyForm" :model="verfiyForm" style="margin-top:30px;" @submit.native.prevent>
<el-form-item label="维护验证码" label-width="110px">
<el-input v-model="verfiyForm.verifyCode" show-password style="width: 480px;" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">取消 </el-button>
<el-button type="primary" @click.native="handleConfirm">确定</el-button>
</div>
</div>
</el-dialog>
<el-dialog class="tip-dialog tip-middle-dialog" title="AI处理终端连接测试" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="serviceDialogVisible" :before-close="handleClose">
<div class="setting-dialog tip-service">
<i class="iconfont icon-lianjieduankai" />
<div class="tip-service-content">
<p>终端连接超时请检查配置是否正确或终端是否运行成功!</p>
<p>请尽快联系系统维护人员进行恢复</p>
</div>
</div>
</el-dialog>
<el-dialog class="tip-dialog tip-middle-dialog" title="AI处理终端连接测试" :close-on-click-modal="false" :modal-append-to-body="false" append-to-body :visible.sync="serviceContentDialogVisible" :before-close="handleClose">
<div class="setting-dialog service-all">
<div class="service-top-text"><i class="iconfont icon-zhongduanjiankong" />终端连接正常</div>
<!-- <ul>
<li v-for="(item, index) in serviceItems" :key="index" :style="{animationDelay: index * 300 + 'ms'}">
<p :class="item.status === 'running'? 'true-active' : 'false-active' ">{{ item.serviceName }}</p>
<i v-if="item.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
</ul> -->
<ul>
<li v-for="(item, index) in serviceItems" :key="index">
<p :class="index <= currentIndex && item.status === 'running'? 'true-active' : 'false-active' ">{{ item.serviceName }}</p>
<i v-if="index <= currentIndex && item.status === 'running'" class="iconfont icon-shi" />
<i v-else-if="index <= currentIndex" class="iconfont icon-cuowu1" />
</li>
</ul>
<!-- <ul>
<li>
<p :class="service.service_imgCamera.status === 'running' ? 'true-active' : 'false-active' ">图像采集</p>
<i v-if="service.service_imgCamera.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
<li>
<p :class="service.service_imgProcess.status === 'running' ? 'true-active' : 'false-active' ">图像处理</p>
<i v-if="service.service_imgProcess.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
<li>
<p :class="service.service_imgYolo.status === 'running' ? 'true-active' : 'false-active' ">图像识别</p>
<i v-if="service.service_imgYolo.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
<li>
<p :class="service.service_imgOcr.status === 'running' ? 'true-active' : 'false-active' ">文字识别</p>
<i v-if="service.service_imgOcr.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
<li>
<p :class="service.service_imgResult.status === 'running' ? 'true-active' : 'false-active' ">同步服务</p>
<i v-if="service.service_imgResult.status === 'running'" class="iconfont icon-shi" />
<i v-else class="iconfont icon-cuowu1" />
</li>
</ul> -->
<div v-if="servicesDisplayed && isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed && isAllServicesRunning }" style="color: rgb(18, 196, 122);">所有服务均正常运行请放心使用</div>
<div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div>
</div>
</el-dialog>
</div>
</template>
<script>
import crudAiTask, { FetchAITerminalStatusQuery, FetchStartStopBookAIService } from '@/api/ai/ai'
import { encrypt } from '@/utils/rsaEncrypt'
import { verifyMaintenance } from '@/api/system/field'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import { mapGetters } from 'vuex'
const defaultForm = { ip: '', maxNum: null }
export default {
name: 'ParamSetting',
components: { },
cruds() {
return CRUD({
title: '参数设置',
url: 'api/ai/initSetting',
crudMethod: { ...crudAiTask },
sort: [],
query: {
size: null,
page: null
},
optShow: {
add: true,
edit: false,
del: false,
download: false,
group: false,
reset: false
},
queryOnPresenterCreated: false
})
},
mixins: [presenter(), header(), form(defaultForm), crud()],
data() {
return {
permission: {
add: ['admin', 'paramSetting:add'],
edit: ['admin', 'paramSetting:edit'],
del: ['admin', 'paramSetting:del']
},
verifyDialogVisible: false,
verfiyForm: {
verifyCode: ''
},
verifyStatus: '',
showVerifyDialog: true,
resetLoading: false,
rules: {
ip: [
{ required: true, message: 'AI处理终端IP不可为空', trigger: 'blur' }
],
maxNum: [
{ required: true, message: '层位占用上限不可为空', trigger: 'blur' }
]
},
serviceDialogVisible: false,
serviceContentDialogVisible: false,
service: {
'service_FileParsing_v1': { 'last_heartbeat': 1736496962.2368362, 'status': '' },
'service_fileParsing': { 'last_heartbeat': 1736496961.953832, 'status': '' },
'service_imgOCR': { 'last_heartbeat': 1736496961.6238313, 'status': '' },
'service_aiResult': { 'last_heartbeat': 1736496960.8598323, 'status': '' }
},
serviceItems: [],
currentIndex: -1,
timer: null,
servicesDisplayed: false,
formValidate: {
mainImage: ''
},
ruleValidate: {
mainImage: [
{ required: true, message: '请上传照片', trigger: 'blur' }
]
}
}
},
computed: {
...mapGetters([
'baseApi'
]),
isAllServicesRunning() {
return Object.values(this.service).every(service => service.status === 'running')
}
},
created() {
this.initData()
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer)
}
},
methods: {
initData() {
crudAiTask.FetchInitSetting().then(res => {
this.crud.form.ip = res.ip
this.maxNum = res.maxNum
this.crud.form.maxNum = res.maxNum
}).catch(() => {
})
},
handleService() {
this.servicesDisplayed = false
FetchAITerminalStatusQuery({ 'ip': this.crud.form.ip }).then(res => {
// {
// "service_FileParsing_v1":{"last_heartbeat":1736496962.2368362,"status":"running"},
// "service_fileParsing":{"last_heartbeat":1736496961.953832,"status":"running"}
// "service_imgOCR":{"last_heartbeat":1736496961.6238313,"status":"running"},
// "service_aiResult":{"last_heartbeat":1736496960.8598323,"status":"running"},
// }
if (res) {
this.serviceContentDialogVisible = true
this.service = JSON.parse(res)
this.serviceItems = []
const keysOrder = ['service_FileParsing_v1', 'service_fileParsing', 'service_imgOCR', 'service_aiResult']
keysOrder.forEach(key => {
let serviceName = ''
switch (key) {
case 'service_FileParsing_v1':
serviceName = '文件解析V1'
break
case 'service_fileParsing':
serviceName = '文件解析'
break
case 'service_imgOCR':
serviceName = '文字识别'
break
case 'service_aiResult':
serviceName = '数据同步'
break
}
this.serviceItems.push({
serviceName: serviceName,
status: this.service[key].status
})
})
this.showServicesSequentially()
} else {
this.serviceDialogVisible = true
}
}).catch(() => {
})
},
showServicesSequentially() {
// let delay = 0
// this.serviceItems.forEach((item, index) => {
// setTimeout(() => {
// this.$set(this.serviceItems, index, {
// ...item,
// opacity: 1
// })
// }, delay)
// delay += 300
// })
let index = 0
const interval = 300
this.timer = setInterval(() => {
this.currentIndex = index
index++
if (index >= this.serviceItems.length) {
clearInterval(this.timer)
setTimeout(() => {
this.servicesDisplayed = true
}, 500)
}
}, interval)
},
[CRUD.HOOK.beforeToCU](crud, form, btn) {
if (this.showVerifyDialog) {
//
this.verifyDialogVisible = true
return false
}
},
[CRUD.HOOK.beforeRefresh]() {
},
//
[CRUD.HOOK.afterValidateCU](crud) {
console.log(crud.form)
return false
},
toVerify(btn) {
this.verifyStatus = btn
if (btn === 'reset') {
this.verifyDialogVisible = true
} else {
if (this.form.ip) {
if (this.showVerifyDialog) {
this.verifyDialogVisible = true
return false
}
} else {
this.$refs.form.validateField(['ip'], err => {
console.log('err', err)
if (err) {
return
}
})
}
}
},
handleConfirm() {
verifyMaintenance(encrypt(this.verfiyForm.verifyCode)).then((res) => {
if (res) {
this.verifyDialogVisible = false
this.verfiyForm.verifyCode = ''
this.showVerifyDialog = false
if (this.verifyStatus === 'add') {
crudAiTask.FetchEditSetting(this.crud.form).then(res => {
this.$message({ message: '修改成功', type: 'success', offset: 8 })
this.initData()
}).catch(() => {
})
} else {
this.resetLoading = true
//
this.handleConnectAIService()
}
} else {
this.$message({ message: '验证码错误!', type: 'error', offset: 8 })
}
})
},
async handleConnectAIService() {
try {
// //
// const firstRes = await FetchStartStopBookAIService({ runType: 0 })
// console.log('', firstRes)
// this.$message({ message: '', type: 'success', offset: 8 })
//
// 1 2 ()
const secondRes = await FetchStartStopBookAIService({ runType: 1 })
console.log('后开启', secondRes)
this.$message({ message: '重启服务成功', type: 'success', offset: 8 })
this.resetLoading = false
} catch (error) {
this.$message({ message: '请求失败', type: 'error', offset: 8 })
this.resetLoading = false
}
},
handleClose() {
if (this.$refs.verfiyForm) {
this.verfiyForm.verifyCode = ''
this.$refs.verfiyForm.resetFields()
this.verifyDialogVisible = false
}
this.serviceContentDialogVisible = false
this.serviceDialogVisible = false
}
}
}
</script>
<style lang="scss" scoped>
::v-deep div.el-dialog__footer {
text-align: center;
}
.tip-service{
display: flex;
justify-content: center;
color: #0C0E1E;
font-size: 16px;
line-height: 40px;
padding: 40px !important;
.iconfont{
font-size: 30px;
margin-right: 10px;
color: #ED4A41;
}
p{
&:first-child{
color: #ED4A41;
}
}
}
.service-all{
text-align: center;
padding: 30px 0 30px 0 !important;
color: #0C0E1E;
ul{
display: flex;
justify-content: space-between;
padding: 60px 0 40px 0;
li{
position: relative;
&::before{
content: "";
position: absolute;
left: 50%;
top: -30px;
width: 1px;
height: 20px;
background-color: #9098a4;
margin-left: -1px;
}
p{
padding: 5px;
border: 1px solid #9098a4;
margin-bottom: 10px;
border-radius: 4px;
&.false-active{
border-color: #ED4A41;
color: #ED4A41;
}
&.true-active{
border-color: rgb(18, 196, 122);
color: rgb(18, 196, 122);
}
}
.iconfont::before{
margin-right: 0 !important;
}
.icon-cuowu1{
color: #ED4A41;
}
.icon-shi{
color: rgb(18, 196, 122);
}
}
}
.service-top-text{
position: relative;
font-size: 18px;
margin: 0 33px 0 43px;
color: rgb(18, 196, 122);
i.iconfont{
font-size: 18px;
margin-right: 6px;
}
&::before{
content: "";
position: absolute;
left: 50%;
bottom: -30px;
width: 1px;
height: 20px;
background-color:#9098a4;
margin-left: -1px;
}
&::after{
content: "";
position: absolute;
left: 0;
bottom: -30px;
width: 100%;
height: 1px;
background-color: #9098a4;
margin-left: -1px;
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.5s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
.fade-in {
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
Loading…
Cancel
Save