mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-03 12:29:14 +08:00
升级前端剩余功能
This commit is contained in:
parent
36461e207e
commit
d50f857946
@ -1,5 +1,20 @@
|
|||||||
# 🚀 版本日志
|
# 🚀 版本日志
|
||||||
|
|
||||||
|
### 2.11.0.7-beta
|
||||||
|
|
||||||
|
### 🐞 解决BUG、优化功能
|
||||||
|
|
||||||
|
### 注意
|
||||||
|
|
||||||
|
1. 取消全局 loading(局部loading)
|
||||||
|
2. 编辑器延迟 1 秒加载(避免样式错乱)
|
||||||
|
3. 所有快捷复制区域变小为一个点击复制图标
|
||||||
|
4. 弹窗、抽屉样式变动
|
||||||
|
5. 取消操作引导(临时)
|
||||||
|
6. 表格将跟随列内容长度自动拉伸出现横向滚动(不会折叠)
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
### 2.11.0.6-beta (2024-01-05)
|
### 2.11.0.6-beta (2024-01-05)
|
||||||
|
|
||||||
### 🐞 解决BUG、优化功能
|
### 🐞 解决BUG、优化功能
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:width="style.width"
|
|
||||||
v-model:open="visibleModel"
|
v-model:open="visibleModel"
|
||||||
|
:width="style.width"
|
||||||
:bodyStyle="style.bodyStyle"
|
:bodyStyle="style.bodyStyle"
|
||||||
:style="style.style"
|
:style="style.style"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -69,6 +69,9 @@ export default {
|
|||||||
...mapState(useGuideStore, ['getFullscreenViewLogStyle']),
|
...mapState(useGuideStore, ['getFullscreenViewLogStyle']),
|
||||||
regModifier() {
|
regModifier() {
|
||||||
return this.regModifiers.join('')
|
return this.regModifiers.join('')
|
||||||
|
},
|
||||||
|
style() {
|
||||||
|
return this.getFullscreenViewLogStyle()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@ -96,12 +99,10 @@ export default {
|
|||||||
// 自动换行
|
// 自动换行
|
||||||
wordBreak: false
|
wordBreak: false
|
||||||
},
|
},
|
||||||
visibleModel: false,
|
visibleModel: false
|
||||||
style: {}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.style = this.getFullscreenViewLogStyle()
|
|
||||||
this.visibleModel = this.visible
|
this.visibleModel = this.visible
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -42,8 +42,9 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
created() {
|
created() {
|
||||||
|
console.log(this.$options._scopeId)
|
||||||
this.domId =
|
this.domId =
|
||||||
(this.$options._parentVnode?.tag || '' + '-' + this.$options._componentTag || '') + '-' + new Date().getTime()
|
(this.$options._parentVnode?.tag || '' + '-' + this.$options._scopeId || '') + '-' + new Date().getTime()
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -97,14 +98,15 @@ export default {
|
|||||||
// this.wp = 100;
|
// this.wp = 100;
|
||||||
//;
|
//;
|
||||||
this.rows = document.querySelector('#' + this.domId).offsetHeight / 16
|
this.rows = document.querySelector('#' + this.domId).offsetHeight / 16
|
||||||
this.cols = document.querySelector('#' + this.domId).offsetWidth / 8
|
this.cols = document.querySelector('#' + this.domId).offsetWidth / 8.4
|
||||||
this.hp = this.rows * 8
|
this.hp = this.rows * 8
|
||||||
this.wp = this.cols * 8
|
this.wp = this.cols * 8
|
||||||
//
|
//
|
||||||
this.terminal = new Terminal({
|
this.terminal = new Terminal({
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
rows: parseInt(this.rows), //行数
|
rows: parseInt(this.rows), //行数
|
||||||
cols: parseInt(this.cols), // 不指定行数,自动回车后光标从下一行开始
|
// 不指定行数,自动回车后光标从下一行开始
|
||||||
|
cols: parseInt(this.cols),
|
||||||
convertEol: true, //启用时,光标将设置为下一行的开头
|
convertEol: true, //启用时,光标将设置为下一行的开头
|
||||||
cursorBlink: true,
|
cursorBlink: true,
|
||||||
// Whether input should be disabled.
|
// Whether input should be disabled.
|
||||||
@ -164,8 +166,8 @@ export default {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.flex-100 {
|
.flex-100 {
|
||||||
display: flex;
|
/* display: flex; */
|
||||||
flex-flow: column;
|
/* flex-flow: column; */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
@ -173,3 +175,4 @@ export default {
|
|||||||
/* box-shadow: inset 0 0 10px 0 #e8e8e8; */
|
/* box-shadow: inset 0 0 10px 0 #e8e8e8; */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<style></style>
|
||||||
|
1
web-vue3/src/d.ts/components.d.ts
vendored
1
web-vue3/src/d.ts/components.d.ts
vendored
@ -168,5 +168,6 @@ declare module 'vue' {
|
|||||||
UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
|
UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
|
||||||
ViewPre: typeof import('./../components/logView/view-pre.vue')['default']
|
ViewPre: typeof import('./../components/logView/view-pre.vue')['default']
|
||||||
WarningOutlined: typeof import('@ant-design/icons-vue')['WarningOutlined']
|
WarningOutlined: typeof import('@ant-design/icons-vue')['WarningOutlined']
|
||||||
|
WarningTwoTone: typeof import('@ant-design/icons-vue')['WarningTwoTone']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,18 +822,6 @@
|
|||||||
placeholder="如果需要定时自动构建则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
placeholder="如果需要定时自动构建则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
||||||
:options="CRON_DATA_SOURCE"
|
:options="CRON_DATA_SOURCE"
|
||||||
>
|
>
|
||||||
<!-- <template v-slot:dataSource>
|
|
||||||
<a-select-opt-group v-for="group in CRON_DATA_SOURCE" :key="group.title">
|
|
||||||
<template v-slot:label>
|
|
||||||
<span>
|
|
||||||
{{ group.title }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.value">
|
|
||||||
{{ opt.title }} {{ opt.value }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select-opt-group>
|
|
||||||
</template> -->
|
|
||||||
<template #option="item"> {{ item.title }} {{ item.value }} </template>
|
<template #option="item"> {{ item.title }} {{ item.value }} </template>
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -1096,7 +1084,6 @@
|
|||||||
确认
|
确认
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
<!-- </div> -->
|
|
||||||
</template>
|
</template>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
<!-- 选择脚本 -->
|
<!-- 选择脚本 -->
|
||||||
@ -1104,17 +1091,19 @@
|
|||||||
destroyOnClose
|
destroyOnClose
|
||||||
:title="`选择脚本`"
|
:title="`选择脚本`"
|
||||||
placement="right"
|
placement="right"
|
||||||
:visible="chooseScriptVisible != 0"
|
:open="chooseScriptVisible != 0"
|
||||||
width="50vw"
|
width="70vw"
|
||||||
:zIndex="1009"
|
:zIndex="1009"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.chooseScriptVisible = 0
|
this.chooseScriptVisible = 0
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
>
|
>
|
||||||
<scriptPage
|
<scriptPage
|
||||||
v-if="chooseScriptVisible"
|
v-if="chooseScriptVisible"
|
||||||
|
ref="scriptPage"
|
||||||
:choose="this.chooseScriptVisible === 1 ? 'checkbox' : 'radio'"
|
:choose="this.chooseScriptVisible === 1 ? 'checkbox' : 'radio'"
|
||||||
:choose-val="
|
:choose-val="
|
||||||
this.chooseScriptVisible === 1
|
this.chooseScriptVisible === 1
|
||||||
@ -1140,13 +1129,36 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
></scriptPage>
|
></scriptPage>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseScriptVisible = false
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['scriptPage'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
|
|
||||||
<!-- 查看命令示例 -->
|
<!-- 查看命令示例 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
width="50vw"
|
width="50vw"
|
||||||
v-model:value="viewScriptTemplVisible"
|
v-model:open="viewScriptTemplVisible"
|
||||||
title="构建命令示例"
|
title="构建命令示例"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -1160,15 +1172,15 @@
|
|||||||
>
|
>
|
||||||
<a-collapse-panel v-for="(group, index) in buildScipts" :key="`${index}`" :header="group.title">
|
<a-collapse-panel v-for="(group, index) in buildScipts" :key="`${index}`" :header="group.title">
|
||||||
<a-list size="small" bordered :data-source="group.children">
|
<a-list size="small" bordered :data-source="group.children">
|
||||||
<template v-slot:renderItem="opt">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
<a-space>
|
<a-space>
|
||||||
{{ opt.title }}
|
{{ item.title }}
|
||||||
|
|
||||||
<SwapOutlined
|
<SwapOutlined
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
temp = { ...temp, script: opt.value }
|
temp = { ...temp, script: item.value }
|
||||||
viewScriptTemplVisible = false
|
viewScriptTemplVisible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
@ -181,7 +181,7 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<!-- 选择确认区域 -->
|
<!-- 选择确认区域
|
||||||
<div style="padding-top: 50px" v-if="this.choose">
|
<div style="padding-top: 50px" v-if="this.choose">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
@ -209,7 +209,7 @@
|
|||||||
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 选择确认区域 -->
|
<!-- 选择确认区域
|
||||||
<div style="padding-top: 50px" v-if="this.choose">
|
<div style="padding-top: 50px" v-if="this.choose">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
@ -709,7 +709,7 @@
|
|||||||
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -1319,7 +1319,7 @@ export default {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$emit(this, 'confirm', selectData)
|
this.$emit('confirm', selectData)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['cancel', 'confirm']
|
emits: ['cancel', 'confirm']
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="list"
|
:data-source="list"
|
||||||
@ -15,22 +15,26 @@
|
|||||||
"
|
"
|
||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
allowClear
|
allowClear
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
v-model="listQuery['%issuerDnName%']"
|
v-model:value="listQuery['%issuerDnName%']"
|
||||||
placeholder="颁发者"
|
placeholder="颁发者"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
allowClear
|
allowClear
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
v-model="listQuery['%subjectDnName%']"
|
v-model:value="listQuery['%subjectDnName%']"
|
||||||
placeholder="主题"
|
placeholder="主题"
|
||||||
/>
|
/>
|
||||||
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
||||||
@ -40,36 +44,43 @@
|
|||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #tooltip slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.tooltip">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-popover #name slot-scope="text, item" title="证书描述">
|
<span>{{ text }}</span>
|
||||||
<template #content>
|
</a-tooltip>
|
||||||
<p>描述:{{ item.description }}</p>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'name'">
|
||||||
|
<a-popover title="证书描述">
|
||||||
|
<template v-slot:content>
|
||||||
|
<p>描述:{{ record.description }}</p>
|
||||||
|
</template>
|
||||||
|
<!-- {{ text }} -->
|
||||||
|
<a-button type="link" style="padding: 0" @click="handleEdit(record)" size="small">{{ text }}</a-button>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'fileExists'">
|
||||||
|
<a-tag v-if="text" color="green">存在</a-tag>
|
||||||
|
<a-tag v-else color="red">丢失</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'workspaceId'">
|
||||||
|
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
||||||
|
<a-tag v-else>工作空间</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-space>
|
||||||
|
<a-button size="small" type="primary" @click="handleDeployFile(record)">部署</a-button>
|
||||||
|
<a-button size="small" type="primary" @click="handleDownload(record)">导出</a-button>
|
||||||
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<!-- {{ text }} -->
|
|
||||||
<a-button type="link" style="padding: 0" @click="handleEdit(item)" size="small">{{ text }}</a-button>
|
|
||||||
</a-popover>
|
|
||||||
<template #fileExists slot-scope="text">
|
|
||||||
<a-tag v-if="text" color="green">存在</a-tag>
|
|
||||||
<a-tag v-else color="red">丢失</a-tag>
|
|
||||||
</template>
|
|
||||||
<template #global slot-scope="text">
|
|
||||||
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
|
||||||
<a-tag v-else>工作空间</a-tag>
|
|
||||||
</template>
|
|
||||||
<template #operation slot-scope="text, record">
|
|
||||||
<a-space>
|
|
||||||
<a-button size="small" type="primary" @click="handleDeployFile(record)">部署</a-button>
|
|
||||||
<a-button size="small" type="primary" @click="handleDownload(record)">导出</a-button>
|
|
||||||
<a-button size="small" type="danger" @click="handleDelete(record)">删除</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 导入 -->
|
<!-- 导入 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editCertVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editCertVisible"
|
||||||
width="700px"
|
width="700px"
|
||||||
title="导入证书"
|
title="导入证书"
|
||||||
@ok="handleEditCertOk"
|
@ok="handleEditCertOk"
|
||||||
@ -77,7 +88,7 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="importCertForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form ref="importCertForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="证书类型" name="type">
|
<a-form-item label="证书类型" name="type">
|
||||||
<a-radio-group v-model="temp.type">
|
<a-radio-group v-model:value="temp.type">
|
||||||
<a-radio value="pkcs12"> pkcs12(pfx) </a-radio>
|
<a-radio value="pkcs12"> pkcs12(pfx) </a-radio>
|
||||||
<a-radio value="JKS"> JKS </a-radio>
|
<a-radio value="JKS"> JKS </a-radio>
|
||||||
<a-radio value="X.509"> X.509(pem、key、crt、cer) </a-radio>
|
<a-radio value="X.509"> X.509(pem、key、crt、cer) </a-radio>
|
||||||
@ -88,9 +99,10 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
v-if="temp.type"
|
v-if="temp.type"
|
||||||
:file-list="uploadFileList"
|
:file-list="uploadFileList"
|
||||||
:remove="
|
@remove="
|
||||||
() => {
|
() => {
|
||||||
uploadFileList = []
|
uploadFileList = []
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:before-upload="
|
:before-upload="
|
||||||
@ -101,7 +113,7 @@
|
|||||||
"
|
"
|
||||||
:accept="typeAccept[temp.type]"
|
:accept="typeAccept[temp.type]"
|
||||||
>
|
>
|
||||||
<a-button><a-icon type="upload" />选择文件</a-button>
|
<a-button><UploadOutlined />选择文件</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
<template v-else>请选选择类型</template>
|
<template v-else>请选选择类型</template>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -111,42 +123,46 @@
|
|||||||
name="password"
|
name="password"
|
||||||
help="如果未填写将解析压缩包里面的 txt"
|
help="如果未填写将解析压缩包里面的 txt"
|
||||||
>
|
>
|
||||||
<a-input v-model="temp.password" placeholder="证书密码" />
|
<a-input v-model:value="temp.password" placeholder="证书密码" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 编辑证书 -->
|
<!-- 编辑证书 -->
|
||||||
<a-modal destroyOnClose v-model:visible="editVisible" :title="`编辑证书`" @ok="handleEditOk" :maskClosable="false">
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editVisible"
|
||||||
|
:title="`编辑证书`"
|
||||||
|
@ok="handleEditOk"
|
||||||
|
:maskClosable="false"
|
||||||
|
>
|
||||||
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-form-item label="证书共享" name="global">
|
<a-form-item label="证书共享" name="global">
|
||||||
<a-radio-group v-model="temp.global">
|
<a-radio-group v-model:value="temp.global">
|
||||||
<a-radio :value="true"> 全局 </a-radio>
|
<a-radio :value="true"> 全局 </a-radio>
|
||||||
<a-radio :value="false"> 当前工作空间 </a-radio>
|
<a-radio :value="false"> 当前工作空间 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="证书描述" name="description">
|
<a-form-item label="证书描述" name="description">
|
||||||
<a-textarea v-model="temp.description" placeholder="请输入证书描述" />
|
<a-textarea v-model:value="temp.description" placeholder="请输入证书描述" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 发布文件 -->
|
<!-- 发布文件 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="releaseFileVisible"
|
v-model:open="releaseFileVisible"
|
||||||
title="部署证书"
|
title="部署证书"
|
||||||
width="50%"
|
width="50%"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ok="
|
@ok="releaseFileOk()"
|
||||||
() => {
|
|
||||||
this.$refs.releaseFile?.tryCommit()
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<a-alert message="证书将打包成 zip 文件上传到对应的文件夹" type="info" show-icon />
|
<a-alert message="证书将打包成 zip 文件上传到对应的文件夹" type="info" show-icon style="margin-bottom: 10px" />
|
||||||
<releaseFile ref="releaseFile" v-if="releaseFileVisible" @commit="handleCommitTask"></releaseFile>
|
<releaseFile ref="releaseFile" v-if="releaseFileVisible" @commit="handleCommitTask"></releaseFile>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
certificateImportFile,
|
certificateImportFile,
|
||||||
@ -183,28 +199,27 @@ export default {
|
|||||||
title: '序列号 (SN)',
|
title: '序列号 (SN)',
|
||||||
dataIndex: 'serialNumberStr',
|
dataIndex: 'serialNumberStr',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 150,
|
width: 150
|
||||||
scopedSlots: { customRender: 'name' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '证书类型',
|
title: '证书类型',
|
||||||
dataIndex: 'keyType',
|
dataIndex: 'keyType',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: '80px',
|
width: '80px',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文件状态',
|
title: '文件状态',
|
||||||
dataIndex: 'fileExists',
|
dataIndex: 'fileExists',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'fileExists' },
|
|
||||||
width: '80px'
|
width: '80px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '共享',
|
title: '共享',
|
||||||
dataIndex: 'workspaceId',
|
dataIndex: 'workspaceId',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'global' },
|
|
||||||
width: '90px'
|
width: '90px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -212,63 +227,63 @@ export default {
|
|||||||
dataIndex: 'issuerDnName',
|
dataIndex: 'issuerDnName',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 200,
|
width: 200,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '主题',
|
title: '主题',
|
||||||
dataIndex: 'subjectDnName',
|
dataIndex: 'subjectDnName',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '密钥算法',
|
title: '密钥算法',
|
||||||
dataIndex: 'sigAlgName',
|
dataIndex: 'sigAlgName',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '算法 OID',
|
title: '算法 OID',
|
||||||
dataIndex: 'sigAlgOid',
|
dataIndex: 'sigAlgOid',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '生效时间',
|
title: '生效时间',
|
||||||
dataIndex: 'effectiveTime',
|
dataIndex: 'effectiveTime',
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
sorter: true,
|
sorter: true,
|
||||||
width: '160px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '到期时间',
|
title: '到期时间',
|
||||||
dataIndex: 'expirationTime',
|
dataIndex: 'expirationTime',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '160px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '版本号',
|
title: '版本号',
|
||||||
dataIndex: 'certVersion',
|
dataIndex: 'certVersion',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: '80px',
|
width: '80px',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建人',
|
title: '创建人',
|
||||||
dataIndex: 'createUser',
|
dataIndex: 'createUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -276,8 +291,8 @@ export default {
|
|||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '160px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@ -295,12 +310,23 @@ export default {
|
|||||||
type: [{ required: true, message: '请选择证书类型', trigger: 'blur' }]
|
type: [{ required: true, message: '请选择证书类型', trigger: 'blur' }]
|
||||||
},
|
},
|
||||||
releaseFileVisible: false,
|
releaseFileVisible: false,
|
||||||
editVisible: false
|
editVisible: false,
|
||||||
|
confirmLoading: false,
|
||||||
|
tableSelections: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
|
},
|
||||||
|
rowSelection() {
|
||||||
|
return {
|
||||||
|
onChange: (selectedRowKeys) => {
|
||||||
|
this.tableSelections = selectedRowKeys
|
||||||
|
},
|
||||||
|
selectedRowKeys: this.tableSelections,
|
||||||
|
type: 'radio'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -339,12 +365,9 @@ export default {
|
|||||||
// 提交 Cert 数据
|
// 提交 Cert 数据
|
||||||
handleEditCertOk() {
|
handleEditCertOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['importCertForm'].validate((valid) => {
|
this.$refs['importCertForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.uploadFileList.length === 0) {
|
if (this.uploadFileList.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择证书文件'
|
message: '请选择证书文件'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@ -355,23 +378,29 @@ export default {
|
|||||||
formData.append('password', this.temp.password || '')
|
formData.append('password', this.temp.password || '')
|
||||||
|
|
||||||
// 提交数据
|
// 提交数据
|
||||||
certificateImportFile(formData).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
certificateImportFile(formData)
|
||||||
// 成功
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
this.editCertVisible = false
|
this.editCertVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除该证书么,删除会将证书文件一并删除奥?',
|
content: '真的要删除该证书么,删除会将证书文件一并删除奥?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -382,7 +411,7 @@ export default {
|
|||||||
}
|
}
|
||||||
deleteCert(params).then((res) => {
|
deleteCert(params).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -402,27 +431,33 @@ export default {
|
|||||||
},
|
},
|
||||||
// 编辑
|
// 编辑
|
||||||
handleEdit(item) {
|
handleEdit(item) {
|
||||||
this.temp = { ...item, global: item.workspaceId === 'GLOBAL', workspaceId: '' }
|
this.temp = {
|
||||||
|
...item,
|
||||||
|
global: item.workspaceId === 'GLOBAL',
|
||||||
|
workspaceId: ''
|
||||||
|
}
|
||||||
this.editVisible = true
|
this.editVisible = true
|
||||||
this.$refs['editForm']?.resetFields()
|
this.$refs['editForm']?.resetFields()
|
||||||
},
|
},
|
||||||
// 编辑确认
|
// 编辑确认
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
this.$refs['editForm'].validate((valid) => {
|
this.$refs['editForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.confirmLoading = true
|
||||||
return false
|
certificateEdit(this.temp)
|
||||||
}
|
.then((res) => {
|
||||||
certificateEdit(this.temp).then((res) => {
|
if (res.code === 200) {
|
||||||
if (res.code === 200) {
|
// 成功
|
||||||
// 成功
|
this.$notification.success({
|
||||||
$notification.success({
|
message: res.msg
|
||||||
message: res.msg
|
})
|
||||||
})
|
|
||||||
|
|
||||||
this.editVisible = false
|
this.editVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleDeployFile(record) {
|
handleDeployFile(record) {
|
||||||
@ -431,18 +466,40 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleCommitTask(data) {
|
handleCommitTask(data) {
|
||||||
certificateDeploy({ ...data, id: this.temp.id }).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
certificateDeploy({ ...data, id: this.temp.id })
|
||||||
// 成功
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
this.releaseFileVisible = false
|
this.releaseFileVisible = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseFileOk() {
|
||||||
|
this.$refs.releaseFile?.tryCommit()
|
||||||
|
},
|
||||||
|
// 确认
|
||||||
|
handerConfirm() {
|
||||||
|
if (!this.tableSelections.length) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '请选择要使用的证书'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selectData = this.list.filter((item) => {
|
||||||
|
return item.id === this.tableSelections[0]
|
||||||
|
})[0]
|
||||||
|
|
||||||
|
this.$emit('confirm', `${selectData.serialNumberStr}:${selectData.keyType}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- <div ref="filter" class="filter"> -->
|
|
||||||
<!-- <a-button type="primary" @click="handleFilter">刷新</a-button> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
size="middle"
|
size="middle"
|
||||||
@ -11,17 +8,19 @@
|
|||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
bordered
|
bordered
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-select v-model="listQuery.nodeId" allowClear placeholder="请选择节点" class="search-input-item">
|
<a-select v-model:value="listQuery.nodeId" allowClear placeholder="请选择节点" class="search-input-item">
|
||||||
<a-select-option v-for="node in nodeList" :key="node.id">{{ node.name }}</a-select-option>
|
<a-select-option v-for="node in nodeList" :key="node.id">{{ node.name }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.outGivingId" allowClear placeholder="分发项目" class="search-input-item">
|
<a-select v-model:value="listQuery.outGivingId" allowClear placeholder="分发项目" class="search-input-item">
|
||||||
<a-select-option v-for="dispatch in dispatchList" :key="dispatch.id">{{ dispatch.name }}</a-select-option>
|
<a-select-option v-for="dispatch in dispatchList" :key="dispatch.id">{{ dispatch.name }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.status" allowClear placeholder="请选择状态" class="search-input-item">
|
<a-select v-model:value="listQuery.status" allowClear placeholder="请选择状态" class="search-input-item">
|
||||||
<a-select-option v-for="(item, key) in dispatchStatusMap" :key="key" :value="key">{{
|
<a-select-option v-for="(item, key) in dispatchStatusMap" :key="key" :value="key">{{
|
||||||
item
|
item
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
@ -37,91 +36,110 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #outGivingId slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.dataIndex === 'outGivingId'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<a-tooltip #nodeName slot-scope="text, record" placement="topLeft" :title="text">
|
<template v-else-if="column.dataIndex === 'nodeName'">
|
||||||
<span>{{
|
<a-tooltip
|
||||||
nodeList.filter((item) => item.id === record.nodeId) &&
|
placement="topLeft"
|
||||||
nodeList.filter((item) => item.id === record.nodeId)[0] &&
|
:title="
|
||||||
nodeList.filter((item) => item.id === record.nodeId)[0].name
|
nodeList.filter((item) => item.id === record.nodeId) &&
|
||||||
}}</span>
|
nodeList.filter((item) => item.id === record.nodeId)[0] &&
|
||||||
</a-tooltip>
|
nodeList.filter((item) => item.id === record.nodeId)[0].name
|
||||||
<a-tooltip #projectId slot-scope="text" placement="topLeft" :title="text">
|
"
|
||||||
<span>{{ text }}</span>
|
>
|
||||||
</a-tooltip>
|
<span>{{
|
||||||
<a-tooltip
|
nodeList.filter((item) => item.id === record.nodeId) &&
|
||||||
#outGivingResultMsg
|
nodeList.filter((item) => item.id === record.nodeId)[0] &&
|
||||||
slot-scope="text, item"
|
nodeList.filter((item) => item.id === record.nodeId)[0].name
|
||||||
placement="topLeft"
|
}}</span>
|
||||||
:title="readJsonStrField(item.result, 'msg')"
|
</a-tooltip>
|
||||||
>
|
</template>
|
||||||
<span
|
<template v-else-if="column.dataIndex === 'projectId'">
|
||||||
>{{ readJsonStrField(item.result, 'code') }}-{{ readJsonStrField(item.result, 'msg') || item.result }}</span
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
>
|
<span>{{ text }}</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip
|
</template>
|
||||||
#outGivingResultTime
|
<template v-else-if="column.dataIndex === 'mode'">
|
||||||
slot-scope="text, item"
|
<a-tooltip placement="topLeft" :title="`${dispatchMode[text] || ''} 关联数据:${record.modeData || ''}`">
|
||||||
placement="topLeft"
|
<span>{{ dispatchMode[text] || '' }}</span>
|
||||||
:title="readJsonStrField(item.result, 'upload_duration')"
|
</a-tooltip>
|
||||||
>
|
</template>
|
||||||
<span>{{ readJsonStrField(item.result, 'upload_duration') }}</span>
|
|
||||||
</a-tooltip>
|
<template v-else-if="column.dataIndex === 'outGivingResultMsg'">
|
||||||
<a-tooltip
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.result, 'msg')">
|
||||||
#outGivingResultSize
|
<span
|
||||||
slot-scope="text, item"
|
>{{ readJsonStrField(record.result, 'code') }}-{{
|
||||||
placement="topLeft"
|
readJsonStrField(record.result, 'msg') || record.result
|
||||||
:title="readJsonStrField(item.result, 'upload_file_size')"
|
}}</span
|
||||||
>
|
>
|
||||||
{{ readJsonStrField(item.result, 'upload_file_size') }}
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</template>
|
||||||
<a-tooltip
|
<template v-else-if="column.dataIndex === 'outGivingResultTime'">
|
||||||
#outGivingResultMsgData
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.result, 'upload_duration')">
|
||||||
slot-scope="text, item"
|
<span>{{ readJsonStrField(record.result, 'upload_duration') }}</span>
|
||||||
placement="topLeft"
|
</a-tooltip>
|
||||||
:title="`${readJsonStrField(item.result, 'data')}`"
|
</template>
|
||||||
>
|
<template v-else-if="column.dataIndex === 'outGivingResultSize'">
|
||||||
<template v-if="item.fileSize"> {{ Math.floor((item.progressSize / item.fileSize) * 100) }}% </template>
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.result, 'upload_file_size')">
|
||||||
{{ readJsonStrField(item.result, 'data') }}
|
{{ readJsonStrField(record.result, 'upload_file_size') }}
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip #status slot-scope="text">
|
</template>
|
||||||
<!-- {{ dispatchStatusMap[text] || "未知" }} -->
|
<template v-else-if="column.dataIndex === 'outGivingResultMsgData'">
|
||||||
<a-tag v-if="text === 2" color="green">{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
<a-tooltip placement="topLeft" :title="`${readJsonStrField(record.result, 'data')}`">
|
||||||
<a-tag v-else-if="text === 1 || text === 0 || text === 5" color="orange">{{
|
<template v-if="record.fileSize">
|
||||||
dispatchStatusMap[text] || '未知'
|
{{ Math.floor((record.progressSize / record.fileSize) * 100) }}%
|
||||||
}}</a-tag>
|
</template>
|
||||||
<a-tag v-else-if="text === 3 || text === 4 || text === 6" color="red">{{
|
{{ readJsonStrField(record.result, 'data') }}
|
||||||
dispatchStatusMap[text] || '未知'
|
</a-tooltip>
|
||||||
}}</a-tag>
|
</template>
|
||||||
<a-tag v-else>{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
</a-tooltip>
|
<!-- {{ dispatchStatusMap[text] || "未知" }} -->
|
||||||
<template #operation slot-scope="text, record">
|
<a-tag v-if="text === 2" color="green">{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
||||||
<a-button type="primary" size="small" @click="handleDetail(record)">详情</a-button>
|
<a-tag v-else-if="text === 1 || text === 0 || text === 5" color="orange">{{
|
||||||
|
dispatchStatusMap[text] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else-if="text === 3 || text === 4 || text === 6" color="red">{{
|
||||||
|
dispatchStatusMap[text] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else>{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-button type="primary" size="small" @click="handleDetail(record)">详情</a-button>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 详情区 -->
|
<!-- 详情区 -->
|
||||||
<a-modal destroyOnClose v-model:visible="detailVisible" width="600px" title="详情信息" :footer="null">
|
<a-modal destroyOnClose v-model:open="detailVisible" width="600px" title="详情信息" :footer="null">
|
||||||
<a-list item-layout="horizontal" :data-source="detailData">
|
<a-list item-layout="horizontal" :data-source="detailData">
|
||||||
<a-list-item #renderItem slot-scope="item">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item-meta :description="item.description">
|
<a-list-item>
|
||||||
<h4 #title>{{ item.title }}</h4>
|
<a-list-item-meta :description="item.description">
|
||||||
</a-list-item-meta>
|
<template v-slot:title>
|
||||||
</a-list-item>
|
<h4>{{ item.title }}</h4>
|
||||||
|
</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
</a-list>
|
</a-list>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
import { dispatchStatusMap, getDishPatchListAll, getDishPatchLogList } from '@/api/dispatch'
|
import { dispatchStatusMap, getDishPatchListAll, getDishPatchLogList, dispatchMode } from '@/api/dispatch'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, readJsonStrField, parseTime } from '@/utils/const'
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, readJsonStrField, parseTime } from '@/utils/const'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
dispatchMode,
|
||||||
|
loading: true,
|
||||||
list: [],
|
list: [],
|
||||||
nodeList: [],
|
nodeList: [],
|
||||||
dispatchList: [],
|
dispatchList: [],
|
||||||
@ -135,40 +153,54 @@ export default {
|
|||||||
{
|
{
|
||||||
title: '分发项目 ID',
|
title: '分发项目 ID',
|
||||||
dataIndex: 'outGivingId',
|
dataIndex: 'outGivingId',
|
||||||
ellipsis: true,
|
width: 100,
|
||||||
scopedSlots: { customRender: 'outGivingId' }
|
ellipsis: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{ title: '节点名称', dataIndex: 'nodeName', ellipsis: true, scopedSlots: { customRender: 'nodeName' } },
|
{
|
||||||
{ title: '项目 ID', dataIndex: 'projectId', ellipsis: true, scopedSlots: { customRender: 'projectId' } },
|
title: '节点名称',
|
||||||
|
dataIndex: 'nodeName',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '项目 ID',
|
||||||
|
dataIndex: 'projectId',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '分发方式',
|
||||||
|
dataIndex: 'mode',
|
||||||
|
ellipsis: true,
|
||||||
|
width: '100px'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '分发结果',
|
title: '分发结果',
|
||||||
dataIndex: 'outGivingResultMsg',
|
dataIndex: 'outGivingResultMsg',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'outGivingResultMsg' }
|
width: 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发状态消息',
|
title: '分发状态消息',
|
||||||
dataIndex: 'outGivingResultMsgData',
|
dataIndex: 'outGivingResultMsgData',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'outGivingResultMsgData' }
|
width: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发耗时',
|
title: '分发耗时',
|
||||||
dataIndex: 'outGivingResultTime',
|
dataIndex: 'outGivingResultTime',
|
||||||
width: '120px',
|
width: '120px'
|
||||||
scopedSlots: { customRender: 'outGivingResultTime' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文件大小',
|
title: '文件大小',
|
||||||
dataIndex: 'outGivingResultSize',
|
dataIndex: 'outGivingResultSize',
|
||||||
width: '100px',
|
width: '100px'
|
||||||
scopedSlots: { customRender: 'outGivingResultSize' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '开始时间',
|
title: '开始时间',
|
||||||
dataIndex: 'startTime',
|
dataIndex: 'startTime',
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
sorter: true,
|
sorter: true,
|
||||||
@ -178,7 +210,7 @@ export default {
|
|||||||
title: '结束时间',
|
title: '结束时间',
|
||||||
dataIndex: 'endTime',
|
dataIndex: 'endTime',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
width: '170px'
|
width: '170px'
|
||||||
@ -187,11 +219,17 @@ export default {
|
|||||||
title: '操作人',
|
title: '操作人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{ title: '状态', dataIndex: 'status', width: 100, ellipsis: true, scopedSlots: { customRender: 'status' } }
|
{
|
||||||
// { title: "操作", dataIndex: "operation", align: "center", scopedSlots: { customRender: "operation" }, width: "100px" },
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 100,
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: 'right'
|
||||||
|
},
|
||||||
|
{ title: '操作', dataIndex: 'operation', align: 'center', width: '100px', fixed: 'right' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -258,4 +296,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="list"
|
:data-source="list"
|
||||||
@ -8,12 +8,14 @@
|
|||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
bordered
|
bordered
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="日志名称"
|
placeholder="日志名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -25,96 +27,107 @@
|
|||||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #name slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.tooltip">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button>
|
<a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button>
|
||||||
<a-button type="primary" size="small" @click="handleLogRead(record)">查看</a-button>
|
<a-button type="primary" size="small" @click="handleLogRead(record)">查看</a-button>
|
||||||
<a-button type="danger" size="small" @click="handleDelete(record)">删除</a-button>
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editVisible"
|
v-model:open="editVisible"
|
||||||
width="60%"
|
width="60%"
|
||||||
title="编辑日志搜索"
|
title="编辑日志搜索"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
@ok="handleEditOk"
|
@ok="handleEditOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="日志名称" name="name">
|
<a-form-item label="日志名称" name="name">
|
||||||
<a-input v-model="temp.name" :maxLength="50" placeholder="日志项目名称" />
|
<a-input v-model:value="temp.name" :maxLength="50" placeholder="日志项目名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="绑定节点" required>
|
<a-form-item label="绑定节点" required>
|
||||||
<a-row v-for="(item, index) in temp.projectList" :key="index">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-col :span="11">
|
<a-row v-for="(item, index) in temp.projectList" :key="index">
|
||||||
<span>节点: </span>
|
<a-col :span="11">
|
||||||
<a-select
|
<span>节点: </span>
|
||||||
style="width: 80%"
|
<a-select
|
||||||
v-model="item.nodeId"
|
style="width: 80%"
|
||||||
placeholder="请选择节点"
|
v-model:value="item.nodeId"
|
||||||
@change="
|
placeholder="请选择节点"
|
||||||
() => {
|
@change="
|
||||||
temp = {
|
() => {
|
||||||
...temp,
|
temp = {
|
||||||
projectList: temp.projectList.map((item, index1) => {
|
...temp,
|
||||||
if (index1 === index && item.projectId) {
|
projectList: temp.projectList.map((item, index1) => {
|
||||||
return Object.assign(item, { projectId: undefined })
|
if (index1 === index && item.projectId) {
|
||||||
}
|
return Object.assign(item, { projectId: undefined })
|
||||||
return item
|
}
|
||||||
})
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-select-option
|
|
||||||
v-for="nodeItem in nodeList"
|
|
||||||
:key="nodeItem.id"
|
|
||||||
:disabled="
|
|
||||||
!nodeProjectList[nodeItem.id] || !nodeProjectList[nodeItem.id].projects || nodeItem.openStatus !== 1
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ nodeItem.name }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="11">
|
|
||||||
<span>项目: </span>
|
|
||||||
<a-select
|
|
||||||
:disabled="!item.nodeId"
|
|
||||||
style="width: 80%"
|
|
||||||
v-model="item.projectId"
|
|
||||||
:placeholder="`请选择项目`"
|
|
||||||
>
|
|
||||||
<!-- <a-select-option value=""> 请先选择节点</a-select-option> -->
|
|
||||||
<template v-if="nodeProjectList[item.nodeId]">
|
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="project in nodeProjectList[item.nodeId].projects"
|
v-for="nodeItem in nodeList"
|
||||||
|
:key="nodeItem.id"
|
||||||
:disabled="
|
:disabled="
|
||||||
temp.projectList.filter((item, nowIndex) => {
|
!nodeProjectList[nodeItem.id] ||
|
||||||
return (
|
!nodeProjectList[nodeItem.id].projects ||
|
||||||
item.nodeId === project.nodeId && item.projectId === project.projectId && nowIndex !== index
|
nodeItem.openStatus !== 1
|
||||||
)
|
|
||||||
}).length > 0
|
|
||||||
"
|
"
|
||||||
:key="project.projectId"
|
|
||||||
>
|
>
|
||||||
{{ project.name }}
|
{{ nodeItem.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</template>
|
</a-select>
|
||||||
</a-select>
|
</a-col>
|
||||||
</a-col>
|
<a-col :span="11">
|
||||||
<a-col :span="2">
|
<span>项目: </span>
|
||||||
<a-button type="danger" @click="() => temp.projectList.splice(index, 1)" icon="delete"></a-button>
|
<a-select
|
||||||
</a-col>
|
:disabled="!item.nodeId"
|
||||||
</a-row>
|
style="width: 80%"
|
||||||
|
v-model:value="item.projectId"
|
||||||
|
:placeholder="`请选择项目`"
|
||||||
|
>
|
||||||
|
<!-- <a-select-option value=""> 请先选择节点</a-select-option> -->
|
||||||
|
<template v-if="nodeProjectList[item.nodeId]">
|
||||||
|
<a-select-option
|
||||||
|
v-for="project in nodeProjectList[item.nodeId].projects"
|
||||||
|
:disabled="
|
||||||
|
temp.projectList.filter((item, nowIndex) => {
|
||||||
|
return (
|
||||||
|
item.nodeId === project.nodeId && item.projectId === project.projectId && nowIndex !== index
|
||||||
|
)
|
||||||
|
}).length > 0
|
||||||
|
"
|
||||||
|
:key="project.projectId"
|
||||||
|
>
|
||||||
|
{{ project.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</template>
|
||||||
|
</a-select>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="2">
|
||||||
|
<a-button type="primary" danger @click="() => temp.projectList.splice(index, 1)"
|
||||||
|
><DeleteOutlined
|
||||||
|
/></a-button>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
<a-button type="primary" @click="() => temp.projectList.push({})">添加</a-button>
|
<a-button type="primary" @click="() => temp.projectList.push({})">添加</a-button>
|
||||||
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
@ -123,7 +136,7 @@
|
|||||||
destroyOnClose
|
destroyOnClose
|
||||||
placement="right"
|
placement="right"
|
||||||
:width="`${this.getCollapsed ? 'calc(100vw - 80px)' : 'calc(100vw - 200px)'}`"
|
:width="`${this.getCollapsed ? 'calc(100vw - 80px)' : 'calc(100vw - 200px)'}`"
|
||||||
:visible="logReadVisible"
|
:open="logReadVisible"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.logReadVisible = false
|
this.logReadVisible = false
|
||||||
@ -137,7 +150,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<logReadView
|
<logReadView
|
||||||
v-if="logReadVisible"
|
v-if="logReadVisible"
|
||||||
:data="temp"
|
:data="this.temp"
|
||||||
@changeTitle="
|
@changeTitle="
|
||||||
(logFile) => {
|
(logFile) => {
|
||||||
const cacheData = { ...this.temp.cacheData, logFile: logFile }
|
const cacheData = { ...this.temp.cacheData, logFile: logFile }
|
||||||
@ -148,11 +161,12 @@
|
|||||||
</a-drawer>
|
</a-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { deleteLogRead, editLogRead, getLogReadList } from '@/api/log-read'
|
import { deleteLogRead, editLogRead, getLogReadList } from '@/api/log-read'
|
||||||
import { getNodeListAll, getProjectListAll } from '@/api/node'
|
import { getNodeListAll, getProjectListAll } from '@/api/node'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, itemGroupBy, parseTime } from '@/utils/const'
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, itemGroupBy, parseTime } from '@/utils/const'
|
||||||
|
import { useGuideStore } from '@/stores/guide'
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
import logReadView from './logReadView'
|
import logReadView from './logReadView'
|
||||||
|
|
||||||
@ -172,21 +186,26 @@ export default {
|
|||||||
temp: {},
|
temp: {},
|
||||||
editVisible: false,
|
editVisible: false,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '名称', dataIndex: 'name', ellipsis: true, scopedSlots: { customRender: 'name' } },
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
tooltip: true,
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
if (!text || text === '0') {
|
if (!text || text === '0') {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
@ -198,18 +217,19 @@ export default {
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
width: 180,
|
width: 180,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
name: [{ required: true, message: '请填写日志项目名称', trigger: 'blur' }]
|
name: [{ required: true, message: '请填写日志项目名称', trigger: 'blur' }]
|
||||||
}
|
},
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getCollapsed']),
|
...mapState(useGuideStore, ['getCollapsed']),
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
}
|
}
|
||||||
@ -277,7 +297,9 @@ export default {
|
|||||||
},
|
},
|
||||||
// 修改
|
// 修改
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
this.temp = Object.assign({}, record, { projectList: JSON.parse(record.nodeProject) })
|
this.temp = Object.assign({}, record, {
|
||||||
|
projectList: JSON.parse(record.nodeProject)
|
||||||
|
})
|
||||||
|
|
||||||
this.loadNodeList().then(() => {
|
this.loadNodeList().then(() => {
|
||||||
this.editVisible = true
|
this.editVisible = true
|
||||||
@ -285,39 +307,41 @@ export default {
|
|||||||
},
|
},
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editForm'].validate((valid) => {
|
this.$refs['editForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const temp = Object.assign({}, this.temp)
|
const temp = Object.assign({}, this.temp)
|
||||||
temp.projectList = temp.projectList?.filter((item) => {
|
temp.projectList = temp.projectList?.filter((item) => {
|
||||||
return item.nodeId && item.projectId
|
return item.nodeId && item.projectId
|
||||||
})
|
})
|
||||||
if (!temp.projectList || !temp.projectList.length) {
|
if (!temp.projectList || !temp.projectList.length) {
|
||||||
$notification.warn({
|
this.$notification.warn({
|
||||||
message: '至少选择一个节点和项目'
|
message: '至少选择一个节点和项目'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// console.log(temp);
|
// console.log(temp);
|
||||||
|
this.confirmLoading = true
|
||||||
editLogRead(temp).then((res) => {
|
editLogRead(temp)
|
||||||
if (res.code === 200) {
|
.then((res) => {
|
||||||
// 成功
|
if (res.code === 200) {
|
||||||
$notification.success({
|
// 成功
|
||||||
message: res.msg
|
this.$notification.success({
|
||||||
})
|
message: res.msg
|
||||||
this.$refs['editForm'].resetFields()
|
})
|
||||||
this.editVisible = false
|
this.$refs['editForm'].resetFields()
|
||||||
this.loadData()
|
this.editVisible = false
|
||||||
}
|
this.loadData()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除日志搜索么?',
|
content: '真的要删除日志搜索么?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -325,7 +349,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteLogRead(record.id).then((res) => {
|
deleteLogRead(record.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -352,4 +376,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 布局 -->
|
<!-- 布局 -->
|
||||||
<a-layout class="file-layout node-full-content">
|
<a-layout class="file-layout">
|
||||||
<!-- 目录树 -->
|
<!-- 目录树 -->
|
||||||
<a-layout-sider theme="light" class="sider" width="25%">
|
<a-layout-sider theme="light" class="sider" width="25%">
|
||||||
<div class="dir-container">
|
<div class="dir-container">
|
||||||
@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-directory-tree
|
<a-directory-tree
|
||||||
:replace-fields="treeReplaceFields"
|
:fieldNames="treeReplaceFields"
|
||||||
@select="nodeClick"
|
@select="nodeClick"
|
||||||
:loadData="onTreeData"
|
:loadData="onTreeData"
|
||||||
:treeData="treeList"
|
:treeData="treeList"
|
||||||
@ -45,7 +45,7 @@
|
|||||||
<a-input
|
<a-input
|
||||||
placeholder="关键词,支持正则"
|
placeholder="关键词,支持正则"
|
||||||
:style="`width: 250px`"
|
:style="`width: 250px`"
|
||||||
v-model="temp.cacheData.keyword"
|
v-model:value="temp.cacheData.keyword"
|
||||||
@pressEnter="sendSearchLog"
|
@pressEnter="sendSearchLog"
|
||||||
>
|
>
|
||||||
</a-input>
|
</a-input>
|
||||||
@ -55,7 +55,7 @@
|
|||||||
显示前N行
|
显示前N行
|
||||||
<a-input-number
|
<a-input-number
|
||||||
id="inputNumber"
|
id="inputNumber"
|
||||||
v-model="temp.cacheData.beforeCount"
|
v-model:value="temp.cacheData.beforeCount"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="1000"
|
:max="1000"
|
||||||
@pressEnter="sendSearchLog"
|
@pressEnter="sendSearchLog"
|
||||||
@ -65,22 +65,22 @@
|
|||||||
显示后N行
|
显示后N行
|
||||||
<a-input-number
|
<a-input-number
|
||||||
id="inputNumber"
|
id="inputNumber"
|
||||||
v-model="temp.cacheData.afterCount"
|
v-model:value="temp.cacheData.afterCount"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="1000"
|
:max="1000"
|
||||||
@pressEnter="sendSearchLog"
|
@pressEnter="sendSearchLog"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<a-popover title="正则语法参考">
|
<a-popover title="正则语法参考">
|
||||||
<template #content>
|
<template v-slot:content>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>^.*\d+.*$</b> - 匹配包含数字的行</li>
|
<li><b>^.*\d+.*$</b> - 匹配包含数字的行</li>
|
||||||
<li><b>.*(a|b).*</b> - 匹配包含 a 或者 b 的行</li>
|
<li><b>.*(a|b).*</b> - 匹配包含 a 或者 b 的行</li>
|
||||||
<li><b>.*(异常).*</b> - 匹配包含 异常 的行</li>
|
<li><b>.*(异常).*</b> - 匹配包含 异常 的行</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<a-button type="link" style="padding: 0" icon="unordered-list"
|
<a-button type="link" style="padding: 0"
|
||||||
><span style="margin-left: 2px">语法参考</span></a-button
|
><UnorderedListOutlined /><span style="margin-left: 2px">语法参考</span></a-button
|
||||||
>
|
>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</a-space>
|
</a-space>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
文件前N行
|
文件前N行
|
||||||
<a-input-number
|
<a-input-number
|
||||||
id="inputNumber"
|
id="inputNumber"
|
||||||
v-model="temp.cacheData.head"
|
v-model:value="temp.cacheData.head"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="1000"
|
:max="1000"
|
||||||
@pressEnter="sendSearchLog"
|
@pressEnter="sendSearchLog"
|
||||||
@ -121,14 +121,14 @@
|
|||||||
文件后N行
|
文件后N行
|
||||||
<a-input-number
|
<a-input-number
|
||||||
id="inputNumber"
|
id="inputNumber"
|
||||||
v-model="temp.cacheData.tail"
|
v-model:value="temp.cacheData.tail"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="1000"
|
:max="1000"
|
||||||
@pressEnter="sendSearchLog"
|
@pressEnter="sendSearchLog"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<a-popover title="搜索配置参考">
|
<a-popover title="搜索配置参考">
|
||||||
<template #content>
|
<template v-slot:content>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>从尾搜索、文件前0行、文件后3行</b> - 在文件最后 3 行中搜索</li>
|
<li><b>从尾搜索、文件前0行、文件后3行</b> - 在文件最后 3 行中搜索</li>
|
||||||
<li><b>从头搜索、文件前0行、文件后3行</b> - 在文件第 3 - 2147483647 行中搜索</li>
|
<li><b>从头搜索、文件前0行、文件后3行</b> - 在文件第 3 - 2147483647 行中搜索</li>
|
||||||
@ -139,18 +139,18 @@
|
|||||||
<li><b>从头搜索、文件前20行、文件后3行</b> - 在文件第 3 - 20 行中搜索</li>
|
<li><b>从头搜索、文件前20行、文件后3行</b> - 在文件第 3 - 20 行中搜索</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<a-button type="link" style="padding: 0" icon="unordered-list"
|
<a-button type="link" style="padding: 0"
|
||||||
><span style="margin-left: 2px">搜索参考</span></a-button
|
><UnorderedListOutlined /><span style="margin-left: 2px">搜索参考</span></a-button
|
||||||
>
|
>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-tabs v-if="temp.cacheData" v-model="activeTagKey" :tabBarStyle="{ marginBottom: 0 }">
|
<a-tabs v-if="temp.cacheData" v-model:value="activeTagKey" :tabBarStyle="{ marginBottom: 0 }">
|
||||||
<template v-for="item in temp.projectList">
|
<template v-for="item in temp.projectList">
|
||||||
<a-tab-pane forceRender v-if="nodeName[item.nodeId]" :key="`${item.nodeId},${item.projectId}`">
|
<a-tab-pane forceRender v-if="nodeName[item.nodeId]">
|
||||||
<template #tab>
|
<template v-slot:tab>
|
||||||
【{{ nodeName[item.nodeId] && nodeName[item.nodeId].name }}】
|
【{{ nodeName[item.nodeId] && nodeName[item.nodeId].name }}】
|
||||||
{{
|
{{
|
||||||
nodeProjectList[item.nodeId] &&
|
nodeProjectList[item.nodeId] &&
|
||||||
@ -175,12 +175,15 @@
|
|||||||
</a-layout>
|
</a-layout>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getNodeListAll, getProjectListAll } from '@/api/node'
|
import { getNodeListAll, getProjectListAll } from '@/api/node'
|
||||||
import { getFileList } from '@/api/node-project'
|
import { getFileList } from '@/api/node-project'
|
||||||
import { itemGroupBy } from '@/utils/const'
|
import { itemGroupBy } from '@/utils/const'
|
||||||
import { getWebSocketUrl } from '@/api/config'
|
import { getWebSocketUrl } from '@/api/config'
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useAppStore } from '@/stores/app'
|
||||||
import viewPre from '@/components/logView/view-pre'
|
import viewPre from '@/components/logView/view-pre'
|
||||||
import { updateCache } from '@/api/log-read'
|
import { updateCache } from '@/api/log-read'
|
||||||
|
|
||||||
@ -210,7 +213,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getLongTermToken', 'getWorkspaceId']),
|
...mapState(useUserStore, ['getLongTermToken']),
|
||||||
|
...mapState(useAppStore, ['getWorkspaceId']),
|
||||||
selectPath() {
|
selectPath() {
|
||||||
if (!Object.keys(this.tempNode).length) {
|
if (!Object.keys(this.tempNode).length) {
|
||||||
return ''
|
return ''
|
||||||
@ -255,7 +259,7 @@ export default {
|
|||||||
'/socket/console',
|
'/socket/console',
|
||||||
`userId=${this.getLongTermToken}&id=${itemProjectData.id}&nodeId=${
|
`userId=${this.getLongTermToken}&id=${itemProjectData.id}&nodeId=${
|
||||||
item.nodeId
|
item.nodeId
|
||||||
}&type=console©Id=&workspaceId=${this.getWorkspaceId()}`
|
}&type=console&workspaceId=${this.getWorkspaceId()}`
|
||||||
)
|
)
|
||||||
const domId = `pre-dom-${item.nodeId},${item.projectId}`
|
const domId = `pre-dom-${item.nodeId},${item.projectId}`
|
||||||
this.socketCache = { ...this.socketCache, [domId]: {} }
|
this.socketCache = { ...this.socketCache, [domId]: {} }
|
||||||
@ -263,7 +267,11 @@ export default {
|
|||||||
|
|
||||||
this.socketCache = {
|
this.socketCache = {
|
||||||
...this.socketCache,
|
...this.socketCache,
|
||||||
[domId]: { socket: socket, projectId: item.projectId, nodeId: item.nodeId }
|
[domId]: {
|
||||||
|
socket: socket,
|
||||||
|
projectId: item.projectId,
|
||||||
|
nodeId: item.nodeId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接成功后
|
// 连接成功后
|
||||||
@ -278,27 +286,27 @@ export default {
|
|||||||
})
|
})
|
||||||
this.activeTagKey = this.temp.cacheData.useNodeId + ',' + this.temp.cacheData.useProjectId
|
this.activeTagKey = this.temp.cacheData.useNodeId + ',' + this.temp.cacheData.useProjectId
|
||||||
// console.log(cacheData);
|
// console.log(cacheData);
|
||||||
|
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
|
||||||
|
window.onbeforeunload = () => {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
Object.keys(this.socketCache).forEach((item) => {
|
this.close()
|
||||||
clearInterval(this.socketCache[item].heart)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
Object.keys(this.socketCache).forEach((item) => {
|
|
||||||
clearInterval(this.socketCache[item].heart)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
close() {
|
||||||
|
Object.keys(this.socketCache).forEach((item) => {
|
||||||
|
clearInterval(this.socketCache[item].heart)
|
||||||
|
this.socketCache[item].socket?.close()
|
||||||
|
})
|
||||||
|
},
|
||||||
initWebSocket(id, url) {
|
initWebSocket(id, url) {
|
||||||
let socket
|
const socket = new WebSocket(url)
|
||||||
if (!socket || socket.readyState !== socket.OPEN || socket.readyState !== socket.CONNECTING) {
|
|
||||||
socket = new WebSocket(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.onerror = (err) => {
|
socket.onerror = (err) => {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
key: 'log-read-error',
|
key: 'log-read-error',
|
||||||
message: 'web socket 错误,请检查是否开启 ws 代理'
|
message: 'web socket 错误,请检查是否开启 ws 代理'
|
||||||
})
|
})
|
||||||
@ -307,9 +315,9 @@ export default {
|
|||||||
socket.onclose = (err) => {
|
socket.onclose = (err) => {
|
||||||
//当客户端收到服务端发送的关闭连接请求时,触发onclose事件
|
//当客户端收到服务端发送的关闭连接请求时,触发onclose事件
|
||||||
console.error(err)
|
console.error(err)
|
||||||
$notification.info({
|
this.$notification.info({
|
||||||
key: 'log-read-close',
|
key: 'log-read-close',
|
||||||
message: '会话已经关闭'
|
message: '会话已经关闭[tail-log]'
|
||||||
})
|
})
|
||||||
clearInterval(this.socketCache[id].heart)
|
clearInterval(this.socketCache[id].heart)
|
||||||
}
|
}
|
||||||
@ -377,7 +385,11 @@ export default {
|
|||||||
nodeChange(value) {
|
nodeChange(value) {
|
||||||
const keyArray = value.split(',')
|
const keyArray = value.split(',')
|
||||||
|
|
||||||
const cacheData = { ...this.temp.cacheData, useNodeId: keyArray[0], useProjectId: keyArray[1] }
|
const cacheData = {
|
||||||
|
...this.temp.cacheData,
|
||||||
|
useNodeId: keyArray[0],
|
||||||
|
useProjectId: keyArray[1]
|
||||||
|
}
|
||||||
this.temp = { ...this.temp, cacheData: cacheData }
|
this.temp = { ...this.temp, cacheData: cacheData }
|
||||||
this.loadFileData()
|
this.loadFileData()
|
||||||
//
|
//
|
||||||
@ -392,14 +404,17 @@ export default {
|
|||||||
if (node.dataRef.textFileEdit) {
|
if (node.dataRef.textFileEdit) {
|
||||||
this.tempFileNode = node.dataRef
|
this.tempFileNode = node.dataRef
|
||||||
// let cacheData = ;
|
// let cacheData = ;
|
||||||
const cacheData = { ...this.temp.cacheData, logFile: this.selectFilePath }
|
const cacheData = {
|
||||||
|
...this.temp.cacheData,
|
||||||
|
logFile: this.selectFilePath
|
||||||
|
}
|
||||||
this.temp = { ...this.temp, cacheData: cacheData }
|
this.temp = { ...this.temp, cacheData: cacheData }
|
||||||
this.$emit('changeTitle', this.selectFilePath)
|
this.$emit('changeTitle', this.selectFilePath)
|
||||||
//
|
//
|
||||||
this.sendSearchLog()
|
this.sendSearchLog()
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
$message.error('当前文件不可读,需要配置可读文件白名单')
|
this.$message.error('当前文件不可读,需要配置可读文件授权')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -485,7 +500,8 @@ export default {
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
emits: ['changeTitle']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -502,13 +518,10 @@ export default {
|
|||||||
.file-content {
|
.file-content {
|
||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 80px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
/* margin: 10px 10px 0; */
|
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.log-filter {
|
.log-filter {
|
||||||
/* margin-top: -22px; */
|
|
||||||
/* margin-bottom: 10px; */
|
|
||||||
padding: 0 10px 10px;
|
padding: 0 10px 10px;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
|
743
web-vue3/src/pages/dispatch/start.vue
Normal file
743
web-vue3/src/pages/dispatch/start.vue
Normal file
@ -0,0 +1,743 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
:open="true"
|
||||||
|
:closable="!uploading"
|
||||||
|
:footer="uploading ? null : undefined"
|
||||||
|
width="50%"
|
||||||
|
:keyboard="false"
|
||||||
|
:title="'分发项目-' + data.name"
|
||||||
|
@ok="handleDispatchOk"
|
||||||
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
@cancel="
|
||||||
|
() => {
|
||||||
|
$emit('cancel')
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a-form ref="dispatchForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
|
<a-form-item label="方式" name="type">
|
||||||
|
<a-radio-group v-model:value="temp.type" name="type" :disabled="!!percentage" @change="restForm">
|
||||||
|
<a-radio :value="'use-build'">构建产物</a-radio>
|
||||||
|
<a-radio :value="'file-storage'">文件中心</a-radio>
|
||||||
|
<a-radio :value="'static-file-storage'">静态文件</a-radio>
|
||||||
|
<a-radio :value="'upload'">上传文件</a-radio>
|
||||||
|
<a-radio :value="'download'">远程下载</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 手动上传 -->
|
||||||
|
<a-form-item label="选择分发文件" name="clearOld" v-if="temp.type === 'upload'">
|
||||||
|
<a-progress v-if="percentage" :percent="percentage">
|
||||||
|
<template #format="percent">
|
||||||
|
{{ percent }}%
|
||||||
|
<template v-if="percentageInfo.total"> ({{ renderSize(percentageInfo.total) }}) </template>
|
||||||
|
<template v-if="percentageInfo.duration"> 用时:{{ formatDuration(percentageInfo.duration) }} </template>
|
||||||
|
</template>
|
||||||
|
</a-progress>
|
||||||
|
|
||||||
|
<a-upload :file-list="fileList" :disabled="!!percentage" @remove="handleRemove" :before-upload="beforeUpload">
|
||||||
|
<LoadingOutlined v-if="percentage" />
|
||||||
|
<a-button v-else type="primary"><UploadOutlined />选择文件</a-button>
|
||||||
|
</a-upload>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 远程下载 -->
|
||||||
|
<a-form-item label="远程下载URL" name="url" v-else-if="temp.type === 'download'">
|
||||||
|
<a-input v-model:value="temp.url" placeholder="远程下载地址" />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 在线构建 -->
|
||||||
|
<template v-else-if="temp.type == 'use-build'">
|
||||||
|
<a-form-item label="选择构建">
|
||||||
|
<a-space>
|
||||||
|
{{ chooseBuildInfo.name }}
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
chooseVisible = 1
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
选择构建
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="选择产物">
|
||||||
|
<a-space>
|
||||||
|
<a-tag v-if="chooseBuildInfo.buildNumberId">#{{ chooseBuildInfo.buildNumberId }}</a-tag>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!chooseBuildInfo.id"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
chooseVisible = 2
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
选择产物
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
<!-- 文件中心 -->
|
||||||
|
<template v-else-if="temp.type === 'file-storage'">
|
||||||
|
<a-form-item label="选择文件">
|
||||||
|
<a-space>
|
||||||
|
{{ chooseFileInfo.name }}
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
chooseVisible = 3
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
选择文件
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item></template
|
||||||
|
>
|
||||||
|
<!-- 静态文件 -->
|
||||||
|
<template v-else-if="temp.type === 'static-file-storage'">
|
||||||
|
<a-form-item label="选择文件">
|
||||||
|
<a-space>
|
||||||
|
{{ chooseFileInfo.name }}
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
chooseVisible = 4
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
选择文件
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item></template
|
||||||
|
>
|
||||||
|
<a-form-item name="clearOld">
|
||||||
|
<template v-slot:label>
|
||||||
|
清空发布
|
||||||
|
<a-tooltip>
|
||||||
|
<template v-slot:title>
|
||||||
|
清空发布是指在上传新文件前,会将项目文件夹目录里面的所有文件先删除后再保存新文件
|
||||||
|
</template>
|
||||||
|
<QuestionCircleOutlined />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-switch v-model:checked="temp.clearOld" checked-children="是" un-checked-children="否" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item name="unzip" v-if="temp.type !== 'use-build'">
|
||||||
|
<template v-slot:label>
|
||||||
|
是否解压
|
||||||
|
<a-tooltip>
|
||||||
|
<template v-slot:title>
|
||||||
|
如果上传的压缩文件是否自动解压 支持的压缩包类型有 tar.bz2, tar.gz, tar, bz2, zip, gz</template
|
||||||
|
>
|
||||||
|
<QuestionCircleOutlined />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-switch v-model:checked="temp.autoUnzip" checked-children="是" un-checked-children="否" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="剔除文件夹" v-if="temp.autoUnzip">
|
||||||
|
<a-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
v-model:value="temp.stripComponents"
|
||||||
|
:min="0"
|
||||||
|
placeholder="解压时候自动剔除压缩包里面多余的文件夹名"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="分发后操作" name="afterOpt">
|
||||||
|
<a-select v-model:value="temp.afterOpt" placeholder="请选择发布后操作">
|
||||||
|
<a-select-option v-for="item in afterOptList" :key="item.value">{{ item.title }}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item name="secondaryDirectory" label="二级目录">
|
||||||
|
<a-input v-model:value="temp.secondaryDirectory" placeholder="不填写则发布至项目的根目录" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item name="selectProject" label="筛选项目" help="筛选之后本次发布操作只发布筛选项,并且只对本次操作生效">
|
||||||
|
<a-select mode="multiple" v-model:value="temp.selectProjectArray" placeholder="请选择指定发布的项目">
|
||||||
|
<a-select-option v-for="item in itemProjectList" :key="item.id" :value="`${item.projectId}@${item.nodeId}`">
|
||||||
|
{{ item.nodeName }}-{{ item.cacheProjectName || item.projectId }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
<!-- 选择构建 -->
|
||||||
|
<a-drawer
|
||||||
|
destroyOnClose
|
||||||
|
:title="`选择构建`"
|
||||||
|
placement="right"
|
||||||
|
:open="chooseVisible === 1"
|
||||||
|
width="80vw"
|
||||||
|
:zIndex="1009"
|
||||||
|
@close="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
|
>
|
||||||
|
<build-list
|
||||||
|
v-if="chooseVisible === 1"
|
||||||
|
:choose="'radio'"
|
||||||
|
layout="table"
|
||||||
|
mode="choose"
|
||||||
|
ref="buildList"
|
||||||
|
@confirm="
|
||||||
|
(data) => {
|
||||||
|
this.chooseBuildInfo = {
|
||||||
|
id: data[0].id,
|
||||||
|
name: data[0].name
|
||||||
|
}
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@cancel="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></build-list>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['buildList'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-drawer>
|
||||||
|
<!-- 选择构建产物 -->
|
||||||
|
<a-drawer
|
||||||
|
destroyOnClose
|
||||||
|
:title="`选择构建产物`"
|
||||||
|
placement="right"
|
||||||
|
:open="chooseVisible === 2"
|
||||||
|
width="80vw"
|
||||||
|
:zIndex="1009"
|
||||||
|
@close="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
|
>
|
||||||
|
<!-- 选择构建产物 -->
|
||||||
|
<build-history
|
||||||
|
v-if="chooseVisible === 2"
|
||||||
|
:choose="'radio'"
|
||||||
|
mode="choose"
|
||||||
|
ref="buildHistory"
|
||||||
|
@confirm="
|
||||||
|
(data) => {
|
||||||
|
this.chooseBuildInfo = {
|
||||||
|
...this.chooseBuildInfo,
|
||||||
|
buildNumberId: data[0]
|
||||||
|
}
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@cancel="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></build-history>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['buildHistory'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-drawer>
|
||||||
|
<!-- 选择文件 -->
|
||||||
|
<a-drawer
|
||||||
|
destroyOnClose
|
||||||
|
:title="`选择文件`"
|
||||||
|
placement="right"
|
||||||
|
:open="chooseVisible === 3"
|
||||||
|
width="80vw"
|
||||||
|
:zIndex="1009"
|
||||||
|
@close="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
|
>
|
||||||
|
<!-- 选择文件 -->
|
||||||
|
<file-storage
|
||||||
|
v-if="chooseVisible === 3"
|
||||||
|
:choose="'radio'"
|
||||||
|
mode="choose"
|
||||||
|
ref="fileStorage"
|
||||||
|
@confirm="
|
||||||
|
(data) => {
|
||||||
|
this.chooseFileInfo = { id: data[0].id, name: data[0].name }
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@cancel="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></file-storage>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['fileStorage'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-drawer>
|
||||||
|
<!-- 选择静态文件 -->
|
||||||
|
<a-drawer
|
||||||
|
destroyOnClose
|
||||||
|
:title="`选择静态文件`"
|
||||||
|
placement="right"
|
||||||
|
:open="chooseVisible === 4"
|
||||||
|
width="80vw"
|
||||||
|
:zIndex="1009"
|
||||||
|
@close="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
|
>
|
||||||
|
<!-- 选择静态文件 -->
|
||||||
|
<static-file-storage
|
||||||
|
v-if="chooseVisible === 4"
|
||||||
|
:choose="'radio'"
|
||||||
|
mode="choose"
|
||||||
|
ref="staticFileStorage"
|
||||||
|
@confirm="
|
||||||
|
(data) => {
|
||||||
|
this.chooseFileInfo = { id: data[0].id, name: data[0].name }
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@cancel="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></static-file-storage>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['staticFileStorage'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { uploadPieces } from '@/utils/upload-pieces'
|
||||||
|
import {
|
||||||
|
remoteDownload,
|
||||||
|
uploadDispatchFile,
|
||||||
|
uploadDispatchFileMerge,
|
||||||
|
afterOptList,
|
||||||
|
getDispatchProject,
|
||||||
|
useBuild,
|
||||||
|
useuseFileStorage,
|
||||||
|
useuseStaticFileStorage
|
||||||
|
} from '@/api/dispatch'
|
||||||
|
import { renderSize, formatDuration } from '@/utils/const'
|
||||||
|
import BuildList from '@/pages/build/list-info'
|
||||||
|
import BuildHistory from '@/pages/build/history'
|
||||||
|
import FileStorage from '@/pages/file-manager/fileStorage/list'
|
||||||
|
import StaticFileStorage from '@/pages/file-manager/staticFileStorage/list'
|
||||||
|
import { getBuildGet } from '@/api/build-info'
|
||||||
|
import { hasFile } from '@/api/file-manager/file-storage'
|
||||||
|
import { hasStaticFile } from '@/api/file-manager/static-storage'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BuildList,
|
||||||
|
BuildHistory,
|
||||||
|
FileStorage,
|
||||||
|
StaticFileStorage
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
data: Object
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
afterOptList,
|
||||||
|
percentage: 0,
|
||||||
|
percentageInfo: {},
|
||||||
|
uploading: false,
|
||||||
|
itemProjectList: [],
|
||||||
|
fileList: [],
|
||||||
|
rules: {
|
||||||
|
afterOpt: [{ required: true, message: '请选择发布后操作', trigger: 'blur' }],
|
||||||
|
url: [{ required: true, message: '请输入远程地址', trigger: 'blur' }]
|
||||||
|
},
|
||||||
|
temp: { type: 'upload' },
|
||||||
|
chooseVisible: 0,
|
||||||
|
chooseBuildInfo: {},
|
||||||
|
chooseFileInfo: {},
|
||||||
|
confirmLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.temp = {
|
||||||
|
...this.temp,
|
||||||
|
afterOpt: this.data.afterOpt,
|
||||||
|
id: this.data.id,
|
||||||
|
clearOld: this.data.clearOld,
|
||||||
|
secondaryDirectory: this.data.secondaryDirectory,
|
||||||
|
type: this.data.mode || 'upload'
|
||||||
|
}
|
||||||
|
getDispatchProject(this.data.id, true).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.itemProjectList = res.data?.projectList
|
||||||
|
|
||||||
|
this.percentage = 0
|
||||||
|
this.percentageInfo = {}
|
||||||
|
this.fileList = []
|
||||||
|
this.restForm()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (this.data.mode === 'use-build') {
|
||||||
|
// 构建
|
||||||
|
const buildData = (this.data.modeData || '').split(':')
|
||||||
|
if (buildData.length === 2) {
|
||||||
|
getBuildGet({
|
||||||
|
id: buildData[0]
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
this.chooseBuildInfo = {
|
||||||
|
id: res.data.id,
|
||||||
|
name: res.data.name,
|
||||||
|
buildNumberId: buildData[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (this.data.mode === 'download') {
|
||||||
|
// 下载
|
||||||
|
this.temp = { ...this.temp, url: this.data.modeData }
|
||||||
|
} else if (this.data.mode === 'file-storage') {
|
||||||
|
// 文件中心
|
||||||
|
if (this.data.modeData) {
|
||||||
|
hasFile({ fileSumMd5: this.data.modeData }).then((res) => {
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
this.chooseFileInfo = { id: res.data.id, name: res.data.name }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (this.data.mode === 'static-file-storage') {
|
||||||
|
// 静态文件
|
||||||
|
if (this.data.modeData) {
|
||||||
|
hasStaticFile({ fileId: this.data.modeData }).then((res) => {
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
this.chooseFileInfo = { id: res.data.id, name: res.data.name }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(this.temp);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
renderSize,
|
||||||
|
formatDuration,
|
||||||
|
// 处理文件移除
|
||||||
|
handleRemove(file) {
|
||||||
|
const index = this.fileList.indexOf(file)
|
||||||
|
const newFileList = this.fileList.slice()
|
||||||
|
newFileList.splice(index, 1)
|
||||||
|
this.fileList = newFileList
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
// 准备上传文件
|
||||||
|
beforeUpload(file) {
|
||||||
|
// 只允许上传单个文件
|
||||||
|
this.fileList = [file]
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
// 提交分发文件
|
||||||
|
handleDispatchOk() {
|
||||||
|
// console.log(this.temp);
|
||||||
|
this.temp = {
|
||||||
|
...this.temp,
|
||||||
|
selectProject: (this.temp.selectProjectArray && this.temp.selectProjectArray.join(',')) || ''
|
||||||
|
}
|
||||||
|
// 检验表单
|
||||||
|
this.$refs['dispatchForm'].validate().then((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// const key = this.temp.type;
|
||||||
|
if (this.temp.type == 'upload') {
|
||||||
|
// 判断文件
|
||||||
|
if (this.fileList.length === 0) {
|
||||||
|
this.$notification.error({
|
||||||
|
message: '请选择文件'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.percentage = 0
|
||||||
|
this.percentageInfo = {}
|
||||||
|
let file = this.fileList[0]
|
||||||
|
this.uploading = true
|
||||||
|
this.confirmLoading = true
|
||||||
|
uploadPieces({
|
||||||
|
file,
|
||||||
|
process: (process, end, total, duration) => {
|
||||||
|
this.percentage = Math.max(this.percentage, process)
|
||||||
|
this.percentageInfo = { end, total, duration }
|
||||||
|
},
|
||||||
|
success: (uploadData) => {
|
||||||
|
// 准备合并
|
||||||
|
uploadDispatchFileMerge({
|
||||||
|
...uploadData[0],
|
||||||
|
id: this.temp.id,
|
||||||
|
afterOpt: this.temp.afterOpt,
|
||||||
|
clearOld: this.temp.clearOld,
|
||||||
|
autoUnzip: this.temp.autoUnzip,
|
||||||
|
secondaryDirectory: this.temp.secondaryDirectory || '',
|
||||||
|
stripComponents: this.temp.stripComponents || 0,
|
||||||
|
selectProject: this.temp.selectProject
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.fileList = []
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.percentage = 0
|
||||||
|
this.percentageInfo = {}
|
||||||
|
this.$emit('cancel')
|
||||||
|
}, 2000)
|
||||||
|
this.uploading = false
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.uploading = false
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
error: (msg) => {
|
||||||
|
this.$notification.error({
|
||||||
|
message: msg
|
||||||
|
})
|
||||||
|
this.uploading = false
|
||||||
|
this.confirmLoading = false
|
||||||
|
},
|
||||||
|
uploadCallback: (formData) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
formData.append('id', this.temp.id)
|
||||||
|
// 上传文件
|
||||||
|
uploadDispatchFile(formData)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
resolve()
|
||||||
|
} else {
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
reject()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else if (this.temp.type == 'download') {
|
||||||
|
if (!this.temp.url) {
|
||||||
|
this.$notification.error({
|
||||||
|
message: '请填写远程URL'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.confirmLoading = true
|
||||||
|
remoteDownload(this.temp)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} else if (this.temp.type == 'use-build') {
|
||||||
|
// 构建
|
||||||
|
if (!this.chooseBuildInfo || !this.chooseBuildInfo.id || !this.chooseBuildInfo.buildNumberId) {
|
||||||
|
this.$notification.error({
|
||||||
|
message: '请填写构建和产物'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.confirmLoading = true
|
||||||
|
useBuild({
|
||||||
|
...this.temp,
|
||||||
|
buildId: this.chooseBuildInfo.id,
|
||||||
|
buildNumberId: this.chooseBuildInfo.buildNumberId
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} else if (this.temp.type == 'file-storage') {
|
||||||
|
// 文件中心
|
||||||
|
if (!this.chooseFileInfo || !this.chooseFileInfo.id) {
|
||||||
|
this.$notification.error({
|
||||||
|
message: '请选择文件中心的文件'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.confirmLoading = true
|
||||||
|
useuseFileStorage({
|
||||||
|
...this.temp,
|
||||||
|
fileId: this.chooseFileInfo.id
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
} else if (this.temp.type == 'static-file-storage') {
|
||||||
|
// 文件中心
|
||||||
|
if (!this.chooseFileInfo || !this.chooseFileInfo.id) {
|
||||||
|
this.$notification.error({
|
||||||
|
message: '请选择静态文件中的文件'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.confirmLoading = true
|
||||||
|
useuseStaticFileStorage({
|
||||||
|
...this.temp,
|
||||||
|
fileId: this.chooseFileInfo.id
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//
|
||||||
|
restForm(e) {
|
||||||
|
// console.log(e);
|
||||||
|
if (e) {
|
||||||
|
this.temp = { ...this.temp, type: e.target.value }
|
||||||
|
}
|
||||||
|
this.$refs['dispatchForm'] && this.$refs['dispatchForm'].clearValidate()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['cancel']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/deep/ .ant-progress-text {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,132 +1,203 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 嵌套表格 -->
|
<a-drawer
|
||||||
<a-table
|
destroyOnClose
|
||||||
:loading="childLoading"
|
:title="`查看 ${name} 状态`"
|
||||||
:columns="childColumns"
|
placement="right"
|
||||||
size="middle"
|
width="85vw"
|
||||||
:bordered="true"
|
:open="true"
|
||||||
:data-source="list"
|
@close="
|
||||||
:pagination="false"
|
() => {
|
||||||
rowKey="id_no"
|
$emit('close')
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<template #title>
|
<a-tabs v-model:value="tabKey" tab-position="left">
|
||||||
<a-space>
|
<a-tab-pane key="1" tab="状态">
|
||||||
<div>
|
<!-- 嵌套表格 -->
|
||||||
当前状态:
|
<a-table
|
||||||
<a-tag v-if="data.status === 2" color="green">{{ statusMap[data.status] || '未知' }}</a-tag>
|
:loading="childLoading"
|
||||||
<a-tag v-else-if="data.status === 1 || data.status === 0" color="orange">{{
|
:columns="childColumns"
|
||||||
statusMap[data.status] || '未知'
|
size="middle"
|
||||||
}}</a-tag>
|
:bordered="true"
|
||||||
<a-tag v-else-if="data.status === 3 || data.status === 4" color="red">{{
|
:data-source="list"
|
||||||
statusMap[data.status] || '未知'
|
:pagination="false"
|
||||||
}}</a-tag>
|
rowKey="id_no"
|
||||||
<a-tag v-else>{{ statusMap[data.status] || '未知' }}</a-tag>
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<a-space>
|
||||||
|
<div>
|
||||||
|
当前状态:
|
||||||
|
<a-tag v-if="data.status === 2" color="green">{{ statusMap[data.status] || '未知' }}</a-tag>
|
||||||
|
<a-tag v-else-if="data.status === 1 || data.status === 0" color="orange">{{
|
||||||
|
statusMap[data.status] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else-if="data.status === 3 || data.status === 4" color="red">{{
|
||||||
|
statusMap[data.status] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else>{{ statusMap[data.status] || '未知' }}</a-tag>
|
||||||
|
</div>
|
||||||
|
<div>状态描述:{{ data.statusMsg || '-' }}</div>
|
||||||
|
<a-button type="primary" size="small" :loading="childLoading" @click="loadData">刷新</a-button>
|
||||||
|
|
||||||
|
<a-statistic-countdown
|
||||||
|
format=" s 秒"
|
||||||
|
title="刷新倒计时"
|
||||||
|
:value="countdownTime"
|
||||||
|
@finish="silenceLoadData"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
|
<template v-if="column.dataIndex === 'nodeId'">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<a-button type="link" style="padding: 0" size="small" @click="toNode(text)">
|
||||||
|
<span>{{ nodeNameMap[text] || text }}</span>
|
||||||
|
<FullscreenOutlined />
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'projectName'">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<template v-if="record.disabled">
|
||||||
|
<a-tooltip title="当前项目被禁用">
|
||||||
|
<EyeInvisibleOutlined />
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<span>{{ text || record.cacheProjectName }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'outGivingStatus'">
|
||||||
|
<a-tag v-if="text === 2" color="green">{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
||||||
|
<a-tag v-else-if="text === 1 || text === 0 || text === 5" color="orange">{{
|
||||||
|
dispatchStatusMap[text] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else-if="text === 3 || text === 4 || text === 6" color="red">{{
|
||||||
|
dispatchStatusMap[text] || '未知'
|
||||||
|
}}</a-tag>
|
||||||
|
<a-tag v-else>{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'outGivingResultMsg'">
|
||||||
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.outGivingResult, 'msg')">
|
||||||
|
<span
|
||||||
|
>{{ readJsonStrField(record.outGivingResult, 'code') }}-{{
|
||||||
|
readJsonStrField(record.outGivingResult, 'msg') || record.outGivingResult
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'outGivingResultTime'">
|
||||||
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.outGivingResult, 'upload_duration')">
|
||||||
|
<span>{{ readJsonStrField(record.outGivingResult, 'upload_duration') }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'outGivingResultSize'">
|
||||||
|
<a-tooltip placement="topLeft" :title="readJsonStrField(record.outGivingResult, 'upload_file_size')">
|
||||||
|
{{ readJsonStrField(record.outGivingResult, 'upload_file_size') }}
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'outGivingResultMsgData'">
|
||||||
|
<a-tooltip placement="topLeft" :title="`${readJsonStrField(record.outGivingResult, 'data')}`">
|
||||||
|
<template v-if="record.fileSize">
|
||||||
|
{{ Math.floor((record.progressSize / record.fileSize) * 100) }}%
|
||||||
|
</template>
|
||||||
|
{{ readJsonStrField(record.outGivingResult, 'data') }}
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'projectStatus'">
|
||||||
|
<a-tooltip v-if="record.errorMsg" :title="record.errorMsg">
|
||||||
|
<WarningOutlined />
|
||||||
|
</a-tooltip>
|
||||||
|
<a-switch
|
||||||
|
v-else
|
||||||
|
:checked="text"
|
||||||
|
:disabled="true"
|
||||||
|
size="small"
|
||||||
|
checked-children="运行中"
|
||||||
|
un-checked-children="未运行"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'projectPid'">
|
||||||
|
<a-tooltip
|
||||||
|
placement="topLeft"
|
||||||
|
:title="`进程号:${record.projectPid || '-'} / 端口号:${record.projectPort || '-'}`"
|
||||||
|
>
|
||||||
|
<span>{{ record.projectPid || '-' }}/{{ record.projectPort || '-' }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'child-operation'">
|
||||||
|
<a-space>
|
||||||
|
<a-button size="small" :disabled="!record.projectName" type="primary" @click="handleFile(record)"
|
||||||
|
>文件</a-button
|
||||||
|
>
|
||||||
|
<a-button size="small" :disabled="!record.projectName" type="primary" @click="handleConsole(record)"
|
||||||
|
>控制台</a-button
|
||||||
|
>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" tab="配置">
|
||||||
|
<!-- 配置分发 -->
|
||||||
|
<div style="width: 50vw">
|
||||||
|
<draggable v-model="list" :group="`sortValue`" item-key="id" handle=".move" chosenClass="box-shadow">
|
||||||
|
<template #item="{ element }">
|
||||||
|
<a-row class="item-row">
|
||||||
|
<a-col :span="18">
|
||||||
|
<span> 节点名: {{ element.nodeName }} </span>
|
||||||
|
<span> 项目名: {{ element.cacheProjectName }} </span>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-space>
|
||||||
|
<a-switch
|
||||||
|
checked-children="启用"
|
||||||
|
un-checked-children="禁用"
|
||||||
|
:checked="element.disabled ? false : true"
|
||||||
|
@change="
|
||||||
|
(checked) => {
|
||||||
|
list = list.map((item2) => {
|
||||||
|
if (element.id === item2.id) {
|
||||||
|
item2.disabled = !checked
|
||||||
|
}
|
||||||
|
return { ...item2 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
size="small"
|
||||||
|
@click="handleRemoveProject(element)"
|
||||||
|
:disabled="!list || list.length <= 1"
|
||||||
|
>
|
||||||
|
解绑
|
||||||
|
</a-button>
|
||||||
|
<a-tooltip placement="left" :title="`长按可以拖动排序`" class="move">
|
||||||
|
<MenuOutlined />
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
<a-col style="margin-top: 10px">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" size="small" @click="viewDispatchManagerOk">保存</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
</div>
|
</div>
|
||||||
<div>状态描述:{{ data.statusMsg || '-' }}</div>
|
</a-tab-pane>
|
||||||
<a-button type="primary" :loading="childLoading" @click="loadData">刷新</a-button>
|
</a-tabs>
|
||||||
|
</a-drawer>
|
||||||
<a-statistic-countdown format=" s 秒" title="刷新倒计时" :value="countdownTime" @finish="silenceLoadData" />
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<a-tooltip #nodeId slot-scope="text" placement="topLeft" :title="text">
|
|
||||||
<a-button type="link" style="padding: 0" size="small" @click="toNode(text)">
|
|
||||||
<span>{{ nodeNameMap[text] || text }}</span>
|
|
||||||
<a-icon type="fullscreen" />
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<template #projectName slot-scope="text, item">
|
|
||||||
<template v-if="item.disabled">
|
|
||||||
<a-tooltip title="当前项目被禁用">
|
|
||||||
<a-icon type="eye-invisible" />
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<a-tooltip #projectName placement="topLeft" :title="text">
|
|
||||||
<span>{{ text || item.cacheProjectName }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<template #outGivingStatus slot-scope="text">
|
|
||||||
<a-tag v-if="text === 2" color="green">{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
|
||||||
<a-tag v-else-if="text === 1 || text === 0 || text === 5" color="orange">{{
|
|
||||||
dispatchStatusMap[text] || '未知'
|
|
||||||
}}</a-tag>
|
|
||||||
<a-tag v-else-if="text === 3 || text === 4 || text === 6" color="red">{{
|
|
||||||
dispatchStatusMap[text] || '未知'
|
|
||||||
}}</a-tag>
|
|
||||||
<a-tag v-else>{{ dispatchStatusMap[text] || '未知' }}</a-tag>
|
|
||||||
</template>
|
|
||||||
<a-tooltip
|
|
||||||
#outGivingResultMsg
|
|
||||||
slot-scope="text, item"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="readJsonStrField(item.outGivingResult, 'msg')"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
>{{ readJsonStrField(item.outGivingResult, 'code') }}-{{
|
|
||||||
readJsonStrField(item.outGivingResult, 'msg') || item.outGivingResult
|
|
||||||
}}</span
|
|
||||||
>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip
|
|
||||||
#outGivingResultTime
|
|
||||||
slot-scope="text, item"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="readJsonStrField(item.outGivingResult, 'upload_duration')"
|
|
||||||
>
|
|
||||||
<span>{{ readJsonStrField(item.outGivingResult, 'upload_duration') }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip
|
|
||||||
#outGivingResultSize
|
|
||||||
slot-scope="text, item"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="readJsonStrField(item.outGivingResult, 'upload_file_size')"
|
|
||||||
>
|
|
||||||
{{ readJsonStrField(item.outGivingResult, 'upload_file_size') }}
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip
|
|
||||||
#outGivingResultMsgData
|
|
||||||
slot-scope="text, item"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="`${readJsonStrField(item.outGivingResult, 'data')}`"
|
|
||||||
>
|
|
||||||
<template v-if="item.fileSize"> {{ Math.floor((item.progressSize / item.fileSize) * 100) }}% </template>
|
|
||||||
{{ readJsonStrField(item.outGivingResult, 'data') }}
|
|
||||||
</a-tooltip>
|
|
||||||
|
|
||||||
<template #projectStatus slot-scope="text, item">
|
|
||||||
<a-tooltip v-if="item.errorMsg" :title="item.errorMsg">
|
|
||||||
<a-icon type="warning" />
|
|
||||||
</a-tooltip>
|
|
||||||
<a-switch
|
|
||||||
v-else
|
|
||||||
:checked="text"
|
|
||||||
:disabled="true"
|
|
||||||
size="small"
|
|
||||||
checked-children="运行中"
|
|
||||||
un-checked-children="未运行"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a-tooltip
|
|
||||||
#projectPid
|
|
||||||
slot-scope="text, record"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="`进程号:${record.projectPid || '-'} / 端口号:${record.projectPort || '-'}`"
|
|
||||||
>
|
|
||||||
<span>{{ record.projectPid || '-' }}/{{ record.projectPort || '-' }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
|
|
||||||
<template #child-operation slot-scope="text, record">
|
|
||||||
<a-space>
|
|
||||||
<a-button size="small" :disabled="!record.projectName" type="primary" @click="handleFile(record)"
|
|
||||||
>文件</a-button
|
|
||||||
>
|
|
||||||
<a-button size="small" :disabled="!record.projectName" type="primary" @click="handleConsole(record)"
|
|
||||||
>控制台</a-button
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
|
|
||||||
<!-- 项目文件组件 -->
|
<!-- 项目文件组件 -->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
@ -134,7 +205,7 @@
|
|||||||
:title="drawerTitle"
|
:title="drawerTitle"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="85vw"
|
width="85vw"
|
||||||
:visible="drawerFileVisible"
|
:open="drawerFileVisible"
|
||||||
@close="onFileClose"
|
@close="onFileClose"
|
||||||
>
|
>
|
||||||
<file
|
<file
|
||||||
@ -152,7 +223,7 @@
|
|||||||
:title="drawerTitle"
|
:title="drawerTitle"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="85vw"
|
width="85vw"
|
||||||
:visible="drawerConsoleVisible"
|
:open="drawerConsoleVisible"
|
||||||
@close="onConsoleClose"
|
@close="onConsoleClose"
|
||||||
>
|
>
|
||||||
<console
|
<console
|
||||||
@ -169,7 +240,7 @@
|
|||||||
:title="drawerTitle"
|
:title="drawerTitle"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="85vw"
|
width="85vw"
|
||||||
:visible="drawerReadFileVisible"
|
:open="drawerReadFileVisible"
|
||||||
@close="onReadFileClose"
|
@close="onReadFileClose"
|
||||||
>
|
>
|
||||||
<file-read
|
<file-read
|
||||||
@ -183,8 +254,15 @@
|
|||||||
</a-drawer>
|
</a-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getDispatchProject, dispatchStatusMap, statusMap } from '@/api/dispatch'
|
import {
|
||||||
|
getDispatchProject,
|
||||||
|
dispatchStatusMap,
|
||||||
|
statusMap,
|
||||||
|
removeProject,
|
||||||
|
saveDispatchProjectConfig
|
||||||
|
} from '@/api/dispatch'
|
||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
import { getRuningProjectInfo } from '@/api/node-project'
|
import { getRuningProjectInfo } from '@/api/node-project'
|
||||||
import {
|
import {
|
||||||
@ -199,25 +277,30 @@ import {
|
|||||||
import File from '@/pages/node/node-layout/project/project-file'
|
import File from '@/pages/node/node-layout/project/project-file'
|
||||||
import Console from '@/pages/node/node-layout/project/project-console'
|
import Console from '@/pages/node/node-layout/project/project-console'
|
||||||
import FileRead from '@/pages/node/node-layout/project/project-file-read'
|
import FileRead from '@/pages/node/node-layout/project/project-file-read'
|
||||||
|
import draggable from 'vuedraggable-es'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
File,
|
File,
|
||||||
Console,
|
Console,
|
||||||
FileRead
|
FileRead,
|
||||||
|
draggable
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
id: {
|
id: {
|
||||||
type: String
|
type: String
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
childLoading: true,
|
||||||
childLoading: false,
|
|
||||||
statusMap,
|
statusMap,
|
||||||
dispatchStatusMap,
|
dispatchStatusMap,
|
||||||
|
|
||||||
list: [],
|
list: [],
|
||||||
|
tabKey: '1',
|
||||||
data: {},
|
data: {},
|
||||||
drawerTitle: '',
|
drawerTitle: '',
|
||||||
drawerFileVisible: false,
|
drawerFileVisible: false,
|
||||||
@ -226,82 +309,79 @@ export default {
|
|||||||
nodeNameMap: {},
|
nodeNameMap: {},
|
||||||
|
|
||||||
childColumns: [
|
childColumns: [
|
||||||
{ title: '节点名称', dataIndex: 'nodeId', width: 120, ellipsis: true, scopedSlots: { customRender: 'nodeId' } },
|
{
|
||||||
|
title: '节点名称',
|
||||||
|
dataIndex: 'nodeId',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '项目名称',
|
title: '项目名称',
|
||||||
dataIndex: 'projectName',
|
dataIndex: 'projectName',
|
||||||
width: 120,
|
width: 120,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'projectName' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '项目状态',
|
title: '项目状态',
|
||||||
dataIndex: 'projectStatus',
|
dataIndex: 'projectStatus',
|
||||||
width: 120,
|
width: 120,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'projectStatus' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '进程/端口',
|
title: '进程/端口',
|
||||||
dataIndex: 'projectPid',
|
dataIndex: 'projectPid',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'projectPid' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发状态',
|
title: '分发状态',
|
||||||
dataIndex: 'outGivingStatus',
|
dataIndex: 'outGivingStatus',
|
||||||
width: '120px',
|
width: '120px'
|
||||||
scopedSlots: { customRender: 'outGivingStatus' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发结果',
|
title: '分发结果',
|
||||||
dataIndex: 'outGivingResultMsg',
|
dataIndex: 'outGivingResultMsg',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 120,
|
width: 120
|
||||||
scopedSlots: { customRender: 'outGivingResultMsg' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发状态消息',
|
title: '分发状态消息',
|
||||||
dataIndex: 'outGivingResultMsgData',
|
dataIndex: 'outGivingResultMsgData',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 120,
|
width: 120
|
||||||
scopedSlots: { customRender: 'outGivingResultMsgData' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分发耗时',
|
title: '分发耗时',
|
||||||
dataIndex: 'outGivingResultTime',
|
dataIndex: 'outGivingResultTime',
|
||||||
width: '120px',
|
width: '120px'
|
||||||
scopedSlots: { customRender: 'outGivingResultTime' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文件大小',
|
title: '文件大小',
|
||||||
dataIndex: 'outGivingResultSize',
|
dataIndex: 'outGivingResultSize',
|
||||||
width: '100px',
|
width: '100px'
|
||||||
scopedSlots: { customRender: 'outGivingResultSize' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最后分发时间',
|
title: '最后分发时间',
|
||||||
dataIndex: 'lastTime',
|
dataIndex: 'lastTime',
|
||||||
width: '170px',
|
width: '170px',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text)
|
customRender: ({ text }) => parseTime(text)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'child-operation',
|
dataIndex: 'child-operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
scopedSlots: { customRender: 'child-operation' },
|
|
||||||
width: '140px',
|
width: '140px',
|
||||||
align: 'center'
|
align: 'center'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
countdownTime: Date.now(),
|
countdownTime: Date.now(),
|
||||||
refreshInterval: 5
|
refreshInterval: 5,
|
||||||
|
temp: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {},
|
computed: {},
|
||||||
watch: {},
|
watch: {},
|
||||||
created() {
|
created() {
|
||||||
@ -337,6 +417,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 静默
|
// 静默
|
||||||
silenceLoadData() {
|
silenceLoadData() {
|
||||||
|
if (this.tabKey !== '1') {
|
||||||
|
// 避免配置页面数据被刷新
|
||||||
|
// 重新计算倒计时
|
||||||
|
this.countdownTime = Date.now() + this.refreshInterval * 1000
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.childLoading = true
|
||||||
this.handleReloadById().then(() => {
|
this.handleReloadById().then(() => {
|
||||||
// 重新计算倒计时
|
// 重新计算倒计时
|
||||||
this.countdownTime = Date.now() + this.refreshInterval * 1000
|
this.countdownTime = Date.now() + this.refreshInterval * 1000
|
||||||
@ -350,7 +437,10 @@ export default {
|
|||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
let projectList =
|
let projectList =
|
||||||
res.data?.projectList?.map((item) => {
|
res.data?.projectList?.map((item) => {
|
||||||
return { ...item, id_no: `${item.id}-${item.nodeId}-${item.projectId}-${new Date().getTime()}` }
|
return {
|
||||||
|
...item,
|
||||||
|
id_no: `${item.id}-${item.nodeId}-${item.projectId}-${new Date().getTime()}`
|
||||||
|
}
|
||||||
}) || []
|
}) || []
|
||||||
this.data = res.data?.data || {}
|
this.data = res.data?.data || {}
|
||||||
let oldProjectList = this.list
|
let oldProjectList = this.list
|
||||||
@ -363,13 +453,14 @@ export default {
|
|||||||
const nodeProjects = itemGroupBy(projectList, 'nodeId')
|
const nodeProjects = itemGroupBy(projectList, 'nodeId')
|
||||||
this.getRuningProjectInfo(nodeProjects)
|
this.getRuningProjectInfo(nodeProjects)
|
||||||
}
|
}
|
||||||
this.childLoading = false
|
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
// 取消加载中
|
// 取消加载中
|
||||||
this.childLoading = false
|
this.childLoading = false
|
||||||
resolve()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -419,7 +510,12 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.list = this.list.map((element) => {
|
this.list = this.list.map((element) => {
|
||||||
if (element.nodeId === data.type) {
|
if (element.nodeId === data.type) {
|
||||||
return { ...element, projectStatus: false, projectPid: '-', errorMsg: res2.msg }
|
return {
|
||||||
|
...element,
|
||||||
|
projectStatus: false,
|
||||||
|
projectPid: '-',
|
||||||
|
errorMsg: res2.msg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return element
|
return element
|
||||||
})
|
})
|
||||||
@ -430,7 +526,12 @@ export default {
|
|||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.list = this.list.map((element) => {
|
this.list = this.list.map((element) => {
|
||||||
if (element.nodeId === data.type) {
|
if (element.nodeId === data.type) {
|
||||||
return { ...element, projectStatus: false, projectPid: '-', errorMsg: '网络异常' }
|
return {
|
||||||
|
...element,
|
||||||
|
projectStatus: false,
|
||||||
|
projectPid: '-',
|
||||||
|
errorMsg: '网络异常'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return element
|
return element
|
||||||
})
|
})
|
||||||
@ -496,25 +597,86 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
window.open(newpage.href, '_blank')
|
window.open(newpage.href, '_blank')
|
||||||
|
},
|
||||||
|
// 删除项目
|
||||||
|
handleRemoveProject(item) {
|
||||||
|
const html =
|
||||||
|
"<b style='font-size: 20px;'>真的要释放(删除)当前项目么?</b>" +
|
||||||
|
"<ul style='font-size: 20px;color:red;font-weight: bold;'>" +
|
||||||
|
'<li>不会真实请求节点删除项目信息</b></li>' +
|
||||||
|
'<li>一般用于服务器无法连接且已经确定不再使用</li>' +
|
||||||
|
'<li>如果误操作会产生冗余数据!!!</li>' +
|
||||||
|
' </ul>'
|
||||||
|
|
||||||
|
this.$confirm({
|
||||||
|
title: '危险操作!!!',
|
||||||
|
zIndex: 1009,
|
||||||
|
content: h('div', null, [h('p', { innerHTML: html }, null)]),
|
||||||
|
okButtonProps: { type: 'primary', size: 'small', danger: true },
|
||||||
|
cancelButtonProps: { type: 'primary' },
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
removeProject({
|
||||||
|
nodeId: item.nodeId,
|
||||||
|
projectId: item.projectId,
|
||||||
|
id: this.id
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//分发管理
|
||||||
|
viewDispatchManagerOk() {
|
||||||
|
const temp = {
|
||||||
|
data: this.list.map((item, index) => {
|
||||||
|
return {
|
||||||
|
nodeId: item.nodeId,
|
||||||
|
projectId: item.projectId,
|
||||||
|
sortValue: index,
|
||||||
|
disabled: item.disabled
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
id: this.id
|
||||||
|
}
|
||||||
|
saveDispatchProjectConfig(temp).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
emits: ['close']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/deep/ .ant-progress-text {
|
/deep/ .ant-progress-text {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
/* .replica-btn-del {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 74px;
|
|
||||||
} */
|
|
||||||
/deep/ .ant-statistic div {
|
/deep/ .ant-statistic div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .ant-statistic-content-value,
|
/deep/ .ant-statistic-content-value,
|
||||||
/deep/ .ant-statistic-content {
|
/deep/ .ant-statistic-content {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
.box-shadow {
|
||||||
|
box-shadow: 0 0 10px 5px rgba(223, 222, 222, 0.5);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.item-row {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -52,7 +52,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
temp: {},
|
temp: {},
|
||||||
submitAble: false
|
submitAble: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -61,9 +61,11 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
// load data
|
// load data
|
||||||
loadData() {
|
loadData() {
|
||||||
|
this.loading = true
|
||||||
getDispatchWhiteList({ workspaceId: this.workspaceId }).then((res) => {
|
getDispatchWhiteList({ workspaceId: this.workspaceId }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.temp = res.data
|
this.temp = res.data
|
||||||
|
this.submitAble = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<template v-if="this.useSuggestions">
|
<template v-if="this.useSuggestions">
|
||||||
<a-result
|
<a-result
|
||||||
title="当前工作空间还没有 Docker"
|
title="当前工作空间还没有 Docker"
|
||||||
@ -23,6 +23,9 @@
|
|||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -41,59 +44,68 @@
|
|||||||
>
|
>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:tooltip="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
<template v-if="column.tooltip">
|
||||||
<span>{{ text }}</span>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
</a-tooltip>
|
<span>{{ text }}</span>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-slot:status="text, record">
|
|
||||||
<template v-if="record.machineDocker">
|
|
||||||
<a-tag color="green" v-if="record.machineDocker.status === 1">正常</a-tag>
|
|
||||||
<a-tooltip v-else :title="record.machineDocker.failureMsg">
|
|
||||||
<a-tag color="red">无法连接</a-tag>
|
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-tooltip v-else title="集群关联的 docker 信息丢失,不能继续使用管理功能">
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('status')">
|
||||||
<a-tag color="red">信息丢失</a-tag>
|
<template v-if="record.machineDocker">
|
||||||
</a-tooltip>
|
<a-tag color="green" v-if="record.machineDocker.status === 1">正常</a-tag>
|
||||||
</template>
|
<a-tooltip v-else :title="record.machineDocker.failureMsg">
|
||||||
<template v-slot:tags="tags">
|
<a-tag color="red">无法连接</a-tag>
|
||||||
<a-tooltip
|
</a-tooltip>
|
||||||
:title="
|
</template>
|
||||||
(tags || '')
|
|
||||||
.split(':')
|
<a-tooltip v-else title="集群关联的 docker 信息丢失,不能继续使用管理功能">
|
||||||
.filter((item) => item)
|
<a-tag color="red">信息丢失</a-tag>
|
||||||
.join(',')
|
</a-tooltip>
|
||||||
"
|
</template>
|
||||||
>
|
<template v-else-if="column.dataIndex === 'tags'">
|
||||||
<a-tag v-for="item in (tags || '').split(':').filter((item) => item)" :key="item"> {{ item }}</a-tag>
|
<a-tooltip
|
||||||
</a-tooltip>
|
:title="
|
||||||
</template>
|
(text || '')
|
||||||
<template v-slot:operation="text, record">
|
.split(':')
|
||||||
<a-space>
|
.filter((item) => item)
|
||||||
<a-button
|
.join(',')
|
||||||
size="small"
|
"
|
||||||
type="primary"
|
|
||||||
:disabled="!record.machineDocker || record.machineDocker.status !== 1"
|
|
||||||
@click="handleConsole(record)"
|
|
||||||
>控制台</a-button
|
|
||||||
>
|
>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
<a-tag v-for="item in (text || '').split(':').filter((item) => item)" :key="item"> {{ item }}</a-tag>
|
||||||
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
</a-tooltip>
|
||||||
</a-space>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="!record.machineDocker || record.machineDocker.status !== 1"
|
||||||
|
@click="handleConsole(record)"
|
||||||
|
>控制台</a-button
|
||||||
|
>
|
||||||
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal destroyOnClose v-model:value="editVisible" title="编辑 Docker" @ok="handleEditOk" :maskClosable="false">
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editVisible"
|
||||||
|
title="编辑 Docker"
|
||||||
|
@ok="handleEditOk"
|
||||||
|
:maskClosable="false"
|
||||||
|
>
|
||||||
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="容器名称" name="name">
|
<a-form-item label="容器名称" name="name">
|
||||||
<a-input v-model:value="temp.name" placeholder="容器名称" />
|
<a-input v-model:value="temp.name" placeholder="容器名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="标签" name="tagInput" help="标签用于容器构建选择容器功能(fromTag)">
|
<a-form-item label="标签" name="tagInput" help="标签用于容器构建选择容器功能(fromTag)">
|
||||||
<template>
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<div>
|
<div>
|
||||||
<a-tooltip :key="index" :title="tag" v-for="(tag, index) in temp.tagsArray">
|
<a-tooltip :key="index" :title="tag" v-for="(tag, index) in temp.tagsArray">
|
||||||
<a-tag
|
<a-tag
|
||||||
@ -109,32 +121,31 @@
|
|||||||
</a-tag>
|
</a-tag>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-if="temp.inputVisible"
|
v-if="temp.inputVisible"
|
||||||
ref="tagInput"
|
ref="tagInput"
|
||||||
type="text"
|
type="text"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="请输入标签名 字母数字 长度 1-10"
|
placeholder="请输入标签名 字母数字 长度 1-10"
|
||||||
v-model:value="temp.tagInput"
|
v-model:value="temp.tagInput"
|
||||||
@blur="handleInputConfirm"
|
@blur="handleInputConfirm"
|
||||||
@keyup.enter="handleInputConfirm"
|
@keyup.enter="handleInputConfirm"
|
||||||
/>
|
/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-tag
|
<a-tag
|
||||||
v-if="!temp.tagsArray || temp.tagsArray.length < 10"
|
v-if="!temp.tagsArray || temp.tagsArray.length < 10"
|
||||||
style="background: #fff; borderstyle: dashed"
|
style="background: #fff; borderstyle: dashed"
|
||||||
@click="showInput"
|
@click="showInput"
|
||||||
>
|
>
|
||||||
<a-icon type="plus" /> 添加
|
<PlusOutlined /> 添加
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<!-- 控制台 -->
|
|
||||||
<!-- <a-drawer destroyOnClose :title="`${temp.name} 控制台`" placement="right" :width="`${this.getCollapsed ? 'calc(100vw - 80px)' : 'calc(100vw - 200px)'}`" :visible="consoleVisible" @close="onClose"> -->
|
|
||||||
<console
|
<console
|
||||||
v-if="consoleVisible"
|
v-if="consoleVisible"
|
||||||
:visible="consoleVisible"
|
:visible="consoleVisible"
|
||||||
@ -146,7 +157,8 @@
|
|||||||
<!-- 同步到其他工作空间 -->
|
<!-- 同步到其他工作空间 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:value="syncToWorkspaceVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="syncToWorkspaceVisible"
|
||||||
title="同步到其他工作空间"
|
title="同步到其他工作空间"
|
||||||
@ok="handleSyncToWorkspace"
|
@ok="handleSyncToWorkspace"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -182,7 +194,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { deleteDcoker, dockerList, editDocker, syncToWorkspace } from '@/api/docker-api'
|
import { deleteDcoker, dockerList, editDocker, syncToWorkspace } from '@/api/docker-api'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
||||||
import { useGuideStore } from '@/stores/guide'
|
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { useAppStore } from '@/stores/app'
|
import { useAppStore } from '@/stores/app'
|
||||||
import Console from './console'
|
import Console from './console'
|
||||||
@ -216,46 +228,43 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'host',
|
title: 'host',
|
||||||
dataIndex: 'machineDocker.host',
|
dataIndex: ['machineDocker', 'host'],
|
||||||
width: 150,
|
width: 150,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'machineDocker.status',
|
dataIndex: ['machineDocker', 'status'],
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '100px',
|
width: '100px'
|
||||||
scopedSlots: { customRender: 'status' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'docker版本',
|
title: 'docker版本',
|
||||||
dataIndex: 'machineDocker.dockerVersion',
|
dataIndex: ['machineDocker', 'dockerVersion'],
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: '120px',
|
width: '120px',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '标签',
|
title: '标签',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'tags' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最后修改人',
|
title: '最后修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'modifyUser' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -263,13 +272,13 @@ export default {
|
|||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '190px'
|
width: '190px'
|
||||||
@ -291,11 +300,11 @@ export default {
|
|||||||
},
|
},
|
||||||
workspaceList: [],
|
workspaceList: [],
|
||||||
tableSelections: [],
|
tableSelections: [],
|
||||||
syncToWorkspaceVisible: false
|
syncToWorkspaceVisible: false,
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useGuideStore, ['getCollapsed']),
|
|
||||||
...mapState(useUserStore, ['getUserInfo']),
|
...mapState(useUserStore, ['getUserInfo']),
|
||||||
...mapState(useAppStore, ['getWorkspaceId']),
|
...mapState(useAppStore, ['getWorkspaceId']),
|
||||||
pagination() {
|
pagination() {
|
||||||
@ -398,27 +407,28 @@ export default {
|
|||||||
// 提交 数据
|
// 提交 数据
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editForm'].validate((valid) => {
|
this.$refs['editForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const temp = Object.assign({}, this.temp)
|
const temp = Object.assign({}, this.temp)
|
||||||
|
|
||||||
temp.tags = (temp.tagsArray || []).join(',')
|
temp.tags = (temp.tagsArray || []).join(',')
|
||||||
delete temp.tagsArray
|
delete temp.tagsArray
|
||||||
delete temp.inputVisible
|
delete temp.inputVisible
|
||||||
delete temp.tagInput
|
delete temp.tagInput
|
||||||
|
this.confirmLoading = true
|
||||||
editDocker(temp).then((res) => {
|
editDocker(temp)
|
||||||
if (res.code === 200) {
|
.then((res) => {
|
||||||
// 成功
|
if (res.code === 200) {
|
||||||
this.$notification.success({
|
// 成功
|
||||||
message: res.msg
|
this.$notification.success({
|
||||||
})
|
message: res.msg
|
||||||
this.editVisible = false
|
})
|
||||||
this.loadData()
|
this.editVisible = false
|
||||||
}
|
this.loadData()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
@ -459,14 +469,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleInputConfirm() {
|
handleInputConfirm() {
|
||||||
this.$refs['editForm'].validateField('tagInput', (errmsg) => {
|
this.$refs['editForm'].validateFields('tagInput').then(() => {
|
||||||
if (errmsg) {
|
|
||||||
// console.log(err);
|
|
||||||
this.$notification.warn({
|
|
||||||
message: errmsg
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const inputValue = this.temp.tagInput
|
const inputValue = this.temp.tagInput
|
||||||
let tags = this.temp.tagsArray || []
|
let tags = this.temp.tagsArray || []
|
||||||
if (inputValue && tags.indexOf(inputValue) === -1) {
|
if (inputValue && tags.indexOf(inputValue) === -1) {
|
||||||
@ -480,6 +483,15 @@ export default {
|
|||||||
inputVisible: false
|
inputVisible: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// .catch((error) => {
|
||||||
|
// console.log(error)
|
||||||
|
// if (errmsgs) {
|
||||||
|
// this.$notification.warn({
|
||||||
|
// message: errmsgs
|
||||||
|
// })
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载工作空间数据
|
// 加载工作空间数据
|
||||||
@ -507,19 +519,24 @@ export default {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 同步
|
// 同步
|
||||||
|
this.confirmLoading = true
|
||||||
syncToWorkspace({
|
syncToWorkspace({
|
||||||
ids: this.tableSelections.join(','),
|
ids: this.tableSelections.join(','),
|
||||||
toWorkspaceId: this.temp.workspaceId
|
toWorkspaceId: this.temp.workspaceId
|
||||||
}).then((res) => {
|
|
||||||
if (res.code == 200) {
|
|
||||||
this.$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
this.tableSelections = []
|
|
||||||
this.syncToWorkspaceVisible = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.tableSelections = []
|
||||||
|
this.syncToWorkspaceVisible = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
@change="changePage"
|
@change="changePage"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
bordered
|
bordered
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -40,56 +43,60 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:tooltip="text">
|
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.tooltip">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
</template>
|
<span>{{ text }}</span>
|
||||||
<template v-slot:status="text, record">
|
</a-tooltip>
|
||||||
<template v-if="record.machineDocker">
|
</template>
|
||||||
<a-tag color="green" v-if="record.machineDocker.status === 1">正常</a-tag>
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('status')">
|
||||||
<a-tooltip v-else :title="record.machineDocker.failureMsg">
|
<template v-if="record.machineDocker">
|
||||||
<a-tag color="red">无法连接</a-tag>
|
<a-tag color="green" v-if="record.machineDocker.status === 1">正常</a-tag>
|
||||||
|
<a-tooltip v-else :title="record.machineDocker.failureMsg">
|
||||||
|
<a-tag color="red">无法连接</a-tag>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-tooltip v-else title="集群关联的 docker 信息丢失,不能继续使用管理功能">
|
||||||
|
<a-tag color="red">信息丢失</a-tag>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-tooltip v-else title="集群关联的 docker 信息丢失,不能继续使用管理功能">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-tag color="red">信息丢失</a-tag>
|
<a-space>
|
||||||
</a-tooltip>
|
<template v-if="record.machineDocker">
|
||||||
</template>
|
<a-button
|
||||||
|
size="small"
|
||||||
|
:disabled="record.machineDocker.status !== 1"
|
||||||
|
type="primary"
|
||||||
|
@click="handleConsole(record, 'server')"
|
||||||
|
>服务</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
size="small"
|
||||||
|
:disabled="record.machineDocker.status !== 1"
|
||||||
|
type="primary"
|
||||||
|
@click="handleConsole(record, 'node')"
|
||||||
|
>节点</a-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<a-button size="small" :disabled="true" type="primary">服务</a-button>
|
||||||
|
<a-button size="small" :disabled="true" type="primary">节点</a-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-slot:operation="text, record">
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
<a-space>
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
<template v-if="record.machineDocker">
|
</a-space>
|
||||||
<a-button
|
</template>
|
||||||
size="small"
|
|
||||||
:disabled="record.machineDocker.status !== 1"
|
|
||||||
type="primary"
|
|
||||||
@click="handleConsole(record, 'server')"
|
|
||||||
>服务</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
size="small"
|
|
||||||
:disabled="record.machineDocker.status !== 1"
|
|
||||||
type="primary"
|
|
||||||
@click="handleConsole(record, 'node')"
|
|
||||||
>节点</a-button
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-button size="small" :disabled="true" type="primary">服务</a-button>
|
|
||||||
<a-button size="small" :disabled="true" type="primary">节点</a-button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
|
||||||
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 创建集群区 -->
|
<!-- 编辑集群区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:value="editVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editVisible"
|
||||||
title="编辑 Docker 集群"
|
title="编辑 Docker 集群"
|
||||||
@ok="handleEditOk"
|
@ok="handleEditOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -106,26 +113,31 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
<!-- 控制台 -->
|
<!-- 控制台 -->
|
||||||
<a-drawer
|
<!-- <a-drawer
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:title="`${temp.name} 控制台`"
|
:title="`${temp.name} 控制台`"
|
||||||
placement="right"
|
placement="right"
|
||||||
:width="`${this.getCollapsed ? 'calc(100vw - 80px)' : 'calc(100vw - 200px)'}`"
|
:width="`${this.getCollapsed ? 'calc(100vw - 80px)' : 'calc(100vw - 200px)'}`"
|
||||||
:visible="consoleVisible"
|
:open="consoleVisible"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.consoleVisible = false
|
this.consoleVisible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
> -->
|
||||||
<console
|
<console
|
||||||
v-if="consoleVisible"
|
v-if="consoleVisible"
|
||||||
:id="temp.id"
|
:id="temp.id"
|
||||||
:visible="consoleVisible"
|
:visible="consoleVisible"
|
||||||
:initMenu="temp.menuKey"
|
:initMenu="temp.menuKey"
|
||||||
urlPrefix=""
|
urlPrefix=""
|
||||||
></console>
|
@close="
|
||||||
</a-drawer>
|
() => {
|
||||||
|
this.consoleVisible = false
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></console>
|
||||||
|
<!-- </a-drawer> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -154,7 +166,7 @@ export default {
|
|||||||
title: '名称',
|
title: '名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -162,57 +174,55 @@ export default {
|
|||||||
dataIndex: 'swarmId',
|
dataIndex: 'swarmId',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '容器标签',
|
title: '容器标签',
|
||||||
dataIndex: 'tag',
|
dataIndex: 'tag',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'status',
|
dataIndex: ['machineDocker', 'status'],
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '100px',
|
width: '100px'
|
||||||
scopedSlots: { customRender: 'status' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最后修改人',
|
title: '最后修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
width: 120,
|
width: 120,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'modifyUser' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '集群创建时间',
|
title: '集群创建时间',
|
||||||
dataIndex: 'machineDocker.swarmCreatedAt',
|
dataIndex: ['machineDocker', 'swarmCreatedAt'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '集群修改时间',
|
title: '集群修改时间',
|
||||||
dataIndex: 'machineDocker.swarmUpdatedAt',
|
dataIndex: ['machineDocker', 'swarmUpdatedAt'],
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
scopedSlots: { customRender: 'operation' },
|
fixed: 'right',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '220px'
|
width: '220px'
|
||||||
}
|
}
|
||||||
@ -225,7 +235,8 @@ export default {
|
|||||||
{ required: true, message: '请填写关联容器标签', trigger: 'blur' },
|
{ required: true, message: '请填写关联容器标签', trigger: 'blur' },
|
||||||
{ pattern: /^\w{1,10}$/, message: '标签限制为字母数字且长度 1-10' }
|
{ pattern: /^\w{1,10}$/, message: '标签限制为字母数字且长度 1-10' }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -287,55 +298,26 @@ export default {
|
|||||||
// 提交 数据
|
// 提交 数据
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editForm'].validate((valid) => {
|
this.$refs['editForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.confirmLoading = true
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
editDockerSwarm(this.temp).then((res) => {
|
editDockerSwarm(this.temp)
|
||||||
if (res.code === 200) {
|
.then((res) => {
|
||||||
// 成功
|
if (res.code === 200) {
|
||||||
this.$notification.success({
|
// 成功
|
||||||
message: res.msg
|
this.$notification.success({
|
||||||
})
|
message: res.msg
|
||||||
this.editVisible = false
|
})
|
||||||
this.loadData()
|
this.editVisible = false
|
||||||
}
|
this.loadData()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// // 解绑
|
|
||||||
// handleUnbind(record) {
|
|
||||||
// const html =
|
|
||||||
// "<b style='font-size: 20px;'>真的要解绑该集群么?</b>" +
|
|
||||||
// "<ul style='font-size: 20px;color:red;font-weight: bold;'>" +
|
|
||||||
// "<li>解绑只删除在本系统的关联数据,不会删除容器里面数据</b></li>" +
|
|
||||||
// " </ul>";
|
|
||||||
|
|
||||||
// //
|
|
||||||
// this.$confirm({
|
|
||||||
// title: "危险操作!!!",
|
|
||||||
// content: h("div", null, [h("p", { domProps: { innerHTML: html } }, null)]),
|
|
||||||
// okButtonProps: { props: { type: "danger", size: "small" } },
|
|
||||||
// cancelButtonProps: { props: { type: "primary" } },
|
|
||||||
// okText: "确认",
|
|
||||||
// cancelText: "取消",
|
|
||||||
// onOk: () => {
|
|
||||||
// // 组装参数
|
|
||||||
// const params = {
|
|
||||||
// id: record.id,
|
|
||||||
// };
|
|
||||||
// unbindSwarm(params).then((res) => {
|
|
||||||
// if (res.code === 200) {
|
|
||||||
// this.$notification.success({
|
|
||||||
// message: res.msg,
|
|
||||||
// });
|
|
||||||
// this.loadData();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
@ -16,29 +16,32 @@
|
|||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="文件名称"
|
placeholder="文件名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%aliasCode%']"
|
v-model:value="listQuery['%aliasCode%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="别名码"
|
placeholder="别名码"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['extName']"
|
v-model:value="listQuery['extName']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="后缀,精准搜索"
|
placeholder="后缀,精准搜索"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['id']"
|
v-model:value="listQuery['id']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="文件id,精准搜索"
|
placeholder="文件id,精准搜索"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -49,7 +52,8 @@
|
|||||||
<a-button type="primary" @click="handleUpload">上传文件</a-button>
|
<a-button type="primary" @click="handleUpload">上传文件</a-button>
|
||||||
<a-button type="primary" @click="handleRemoteDownload">远程下载</a-button>
|
<a-button type="primary" @click="handleRemoteDownload">远程下载</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
type="danger"
|
type="primary"
|
||||||
|
danger
|
||||||
:disabled="!tableSelections || tableSelections.length <= 0"
|
:disabled="!tableSelections || tableSelections.length <= 0"
|
||||||
@click="handleBatchDelete"
|
@click="handleBatchDelete"
|
||||||
>
|
>
|
||||||
@ -57,62 +61,75 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #tooltip slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.tooltip">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-tooltip #id slot-scope="text, item" placement="topLeft" :title="text">
|
<span>{{ (text || '').slice(0, 8) }}</span>
|
||||||
<span v-if="item.status === 0 || item.status === 2">-</span>
|
</a-tooltip>
|
||||||
<span v-else>{{ text }}</span>
|
</template>
|
||||||
</a-tooltip>
|
<template v-else-if="column.dataIndex === 'id'">
|
||||||
<a-popover #name slot-scope="text, item" title="文件信息">
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<template #content>
|
<span v-if="record.status === 0 || record.status === 2">-</span>
|
||||||
<p>文件名:{{ text }}</p>
|
<span v-else>{{ (text || '').slice(0, 8) }}</span>
|
||||||
<p>文件描述:{{ item.description }}</p>
|
</a-tooltip>
|
||||||
<p v-if="item.status !== undefined">下载状态:{{ statusMap[item.status] || '未知' }}</p>
|
</template>
|
||||||
<p v-if="item.progressDesc">状态描述:{{ item.progressDesc }}</p>
|
<template v-else-if="column.dataIndex === 'name'">
|
||||||
|
<a-popover title="文件信息">
|
||||||
|
<template v-slot:content>
|
||||||
|
<p>文件名:{{ text }}</p>
|
||||||
|
<p>文件描述:{{ record.description }}</p>
|
||||||
|
<p v-if="record.status !== undefined">下载状态:{{ statusMap[record.status] || '未知' }}</p>
|
||||||
|
<p v-if="record.progressDesc">状态描述:{{ record.progressDesc }}</p>
|
||||||
|
</template>
|
||||||
|
<!-- {{ text }} -->
|
||||||
|
<a-button type="link" style="padding: 0" @click="handleEdit(record)" size="small">{{ text }}</a-button>
|
||||||
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
<!-- {{ text }} -->
|
|
||||||
<a-button type="link" style="padding: 0" @click="handleEdit(item)" size="small">{{ text }}</a-button>
|
|
||||||
</a-popover>
|
|
||||||
|
|
||||||
<a-tooltip #renderSize slot-scope="text" placement="topLeft" :title="renderSize(text)">
|
<template v-else-if="column.dataIndex === 'size'">
|
||||||
<span>{{ renderSize(text) }}</span>
|
<a-tooltip placement="topLeft" :title="renderSize(text)">
|
||||||
</a-tooltip>
|
<span>{{ renderSize(text) }}</span>
|
||||||
<a-tooltip #source slot-scope="text" placement="topLeft" :title="`${sourceMap[text] || '未知'}`">
|
</a-tooltip>
|
||||||
<span>{{ sourceMap[text] || '未知' }}</span>
|
</template>
|
||||||
</a-tooltip>
|
<template v-else-if="column.dataIndex === 'source'">
|
||||||
|
<a-tooltip placement="topLeft" :title="`${sourceMap[text] || '未知'}`">
|
||||||
|
<span>{{ sourceMap[text] || '未知' }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #exists slot-scope="text">
|
<template v-else-if="column.dataIndex === 'exists'">
|
||||||
<a-tag v-if="text" color="green">存在</a-tag>
|
<a-tag v-if="text" color="green">存在</a-tag>
|
||||||
<a-tag v-else color="red">丢失</a-tag>
|
<a-tag v-else color="red">丢失</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #global slot-scope="text">
|
<template v-else-if="column.dataIndex === 'workspaceId'">
|
||||||
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
||||||
<a-tag v-else>工作空间</a-tag>
|
<a-tag v-else>工作空间</a-tag>
|
||||||
</template>
|
</template>
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<!-- <a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button> -->
|
<!-- <a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button> -->
|
||||||
<a-button size="small" :disabled="!record.exists" type="primary" @click="handleDownloadUrl(record)"
|
<a-button size="small" :disabled="!record.exists" type="primary" @click="handleDownloadUrl(record)"
|
||||||
>下载</a-button
|
>下载</a-button
|
||||||
>
|
>
|
||||||
<a-button size="small" :disabled="!record.exists" type="primary" @click="handleReleaseFile(record)"
|
<a-button size="small" :disabled="!record.exists" type="primary" @click="handleReleaseFile(record)"
|
||||||
>发布</a-button
|
>发布</a-button
|
||||||
>
|
>
|
||||||
<a-button type="danger" size="small" @click="handleDelete(record)">删除</a-button>
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 上传文件 -->
|
<!-- 上传文件 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="uploadVisible"
|
v-model:open="uploadVisible"
|
||||||
:closable="!uploading"
|
:closable="!uploading"
|
||||||
:footer="uploading ? null : undefined"
|
:footer="uploading ? null : undefined"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:title="`上传文件`"
|
:title="`上传文件`"
|
||||||
@ok="handleUploadOk"
|
@ok="handleUploadOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form ref="form" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form ref="form" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-form-item label="选择文件" name="file">
|
<a-form-item label="选择文件" name="file">
|
||||||
@ -127,9 +144,10 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
:file-list="fileList"
|
:file-list="fileList"
|
||||||
:disabled="!!percentage"
|
:disabled="!!percentage"
|
||||||
:remove="
|
@remove="
|
||||||
(file) => {
|
(file) => {
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:before-upload="
|
:before-upload="
|
||||||
@ -140,20 +158,20 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<a-icon type="loading" v-if="percentage" />
|
<LoadingOutlined v-if="percentage" />
|
||||||
<a-button v-else type="primary" icon="upload">选择文件</a-button>
|
<a-button v-else type="primary"><UploadOutlined />选择文件</a-button>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="保留天数" name="keepDay">
|
<a-form-item label="保留天数" name="keepDay">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="temp.keepDay"
|
v-model:value="temp.keepDay"
|
||||||
:min="1"
|
:min="1"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="文件保存天数,默认 3650 天"
|
placeholder="文件保存天数,默认 3650 天"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件共享" name="global">
|
<a-form-item label="文件共享" name="global">
|
||||||
<a-radio-group v-model="temp.global">
|
<a-radio-group v-model:value="temp.global">
|
||||||
<a-radio :value="true"> 全局 </a-radio>
|
<a-radio :value="true"> 全局 </a-radio>
|
||||||
<a-radio :value="false"> 当前工作空间 </a-radio>
|
<a-radio :value="false"> 当前工作空间 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
@ -161,7 +179,7 @@
|
|||||||
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
:maxLength="50"
|
:maxLength="50"
|
||||||
v-model="temp.aliasCode"
|
v-model:value="temp.aliasCode"
|
||||||
placeholder="请输入别名码"
|
placeholder="请输入别名码"
|
||||||
@search="
|
@search="
|
||||||
() => {
|
() => {
|
||||||
@ -169,38 +187,39 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #enterButton>
|
<template v-slot:enterButton>
|
||||||
<a-button type="primary"> 随机生成 </a-button>
|
<a-button type="primary"> 随机生成 </a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-input-search>
|
</a-input-search>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件描述" name="description">
|
<a-form-item label="文件描述" name="description">
|
||||||
<a-textarea v-model="temp.description" placeholder="请输入文件描述" />
|
<a-textarea v-model:value="temp.description" placeholder="请输入文件描述" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 编辑文件 -->
|
<!-- 编辑文件 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:visible="editVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editVisible"
|
||||||
:title="`修改文件`"
|
:title="`修改文件`"
|
||||||
@ok="handleEditOk"
|
@ok="handleEditOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-form-item label="文件名" name="name">
|
<a-form-item label="文件名" name="name">
|
||||||
<a-input placeholder="文件名" v-model="temp.name" />
|
<a-input placeholder="文件名" v-model:value="temp.name" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="保留天数" name="keepDay">
|
<a-form-item label="保留天数" name="keepDay">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="temp.keepDay"
|
v-model:value="temp.keepDay"
|
||||||
:min="1"
|
:min="1"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="文件保存天数,默认 3650 天"
|
placeholder="文件保存天数,默认 3650 天"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件共享" name="global">
|
<a-form-item label="文件共享" name="global">
|
||||||
<a-radio-group v-model="temp.global">
|
<a-radio-group v-model:value="temp.global">
|
||||||
<a-radio :value="true"> 全局 </a-radio>
|
<a-radio :value="true"> 全局 </a-radio>
|
||||||
<a-radio :value="false"> 当前工作空间 </a-radio>
|
<a-radio :value="false"> 当前工作空间 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
@ -208,7 +227,7 @@
|
|||||||
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
:maxLength="50"
|
:maxLength="50"
|
||||||
v-model="temp.aliasCode"
|
v-model:value="temp.aliasCode"
|
||||||
placeholder="请输入别名码"
|
placeholder="请输入别名码"
|
||||||
@search="
|
@search="
|
||||||
() => {
|
() => {
|
||||||
@ -216,38 +235,39 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #enterButton>
|
<template v-slot:enterButton>
|
||||||
<a-button type="primary"> 随机生成 </a-button>
|
<a-button type="primary"> 随机生成 </a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-input-search>
|
</a-input-search>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件描述" name="description">
|
<a-form-item label="文件描述" name="description">
|
||||||
<a-textarea v-model="temp.description" placeholder="请输入文件描述" />
|
<a-textarea v-model:value="temp.description" placeholder="请输入文件描述" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!--远程下载 -->
|
<!--远程下载 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="uploadRemoteFileVisible"
|
v-model:open="uploadRemoteFileVisible"
|
||||||
title="远程下载文件"
|
title="远程下载文件"
|
||||||
@ok="handleRemoteUpload"
|
@ok="handleRemoteUpload"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" :rules="rules" ref="remoteForm">
|
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" :rules="rules" ref="remoteForm">
|
||||||
<a-form-item label="远程下载URL" name="url">
|
<a-form-item label="远程下载URL" name="url">
|
||||||
<a-input v-model="temp.url" placeholder="远程下载地址" />
|
<a-input v-model:value="temp.url" placeholder="远程下载地址" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="保留天数" name="keepDay">
|
<a-form-item label="保留天数" name="keepDay">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
v-model="temp.keepDay"
|
v-model:value="temp.keepDay"
|
||||||
:min="1"
|
:min="1"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="文件保存天数,默认 3650 天"
|
placeholder="文件保存天数,默认 3650 天"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件共享" name="global">
|
<a-form-item label="文件共享" name="global">
|
||||||
<a-radio-group v-model="temp.global">
|
<a-radio-group v-model:value="temp.global">
|
||||||
<a-radio :value="true"> 全局 </a-radio>
|
<a-radio :value="true"> 全局 </a-radio>
|
||||||
<a-radio :value="false"> 当前工作空间 </a-radio>
|
<a-radio :value="false"> 当前工作空间 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
@ -255,7 +275,7 @@
|
|||||||
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
<a-form-item label="别名码" name="aliasCode" help="用于区别文件是否为同一类型,可以针对同类型进行下载管理">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
:maxLength="50"
|
:maxLength="50"
|
||||||
v-model="temp.aliasCode"
|
v-model:value="temp.aliasCode"
|
||||||
placeholder="请输入别名码"
|
placeholder="请输入别名码"
|
||||||
@search="
|
@search="
|
||||||
() => {
|
() => {
|
||||||
@ -263,20 +283,20 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #enterButton>
|
<template v-slot:enterButton>
|
||||||
<a-button type="primary"> 随机生成 </a-button>
|
<a-button type="primary"> 随机生成 </a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-input-search>
|
</a-input-search>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件描述" name="description">
|
<a-form-item label="文件描述" name="description">
|
||||||
<a-textarea v-model="temp.description" placeholder="请输入文件描述" />
|
<a-textarea v-model:value="temp.description" placeholder="请输入文件描述" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 断点下载 -->
|
<!-- 断点下载 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="triggerVisible"
|
v-model:open="triggerVisible"
|
||||||
title="断点/分片下载"
|
title="断点/分片下载"
|
||||||
width="50%"
|
width="50%"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -284,42 +304,30 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="editTriggerForm" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form ref="editTriggerForm" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<template #tabBarExtraContent>
|
<template v-slot:rightExtra>
|
||||||
<a-tooltip title="重置下载 token 信息,重置后之前的下载 token 将失效">
|
<a-tooltip title="重置下载 token 信息,重置后之前的下载 token 将失效">
|
||||||
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-tab-pane key="1" tab="断点/分片单文件下载">
|
<a-tab-pane key="1" tab="断点/分片单文件下载">
|
||||||
<a-space style="display: block" direction="vertical" align="baseline">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-alert
|
<a-alert type="info" :message="`下载地址(点击可以复制)`">
|
||||||
v-clipboard:copy="`${temp.triggerDownloadUrl}`"
|
<template v-slot:description>
|
||||||
v-clipboard:success="
|
<a-typography-paragraph :copyable="{ tooltip: false, text: temp.triggerDownloadUrl }">
|
||||||
() => {
|
<a-tag>GET</a-tag>
|
||||||
tempVue.prototype.$notification.success({ message: '复制成功' })
|
<span>{{ `${temp.triggerDownloadUrl}` }} </span>
|
||||||
}
|
</a-typography-paragraph>
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({ message: '复制失败' })
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`下载地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template #description>
|
|
||||||
<a-tag>GET</a-tag> <span>{{ `${temp.triggerDownloadUrl}` }} </span>
|
|
||||||
<a-icon type="copy" />
|
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a :href="temp.triggerDownloadUrl" target="_blank">
|
<a :href="temp.triggerDownloadUrl" target="_blank">
|
||||||
<a-button size="small" icon="download" type="primary">立即下载</a-button>
|
<a-button size="small" type="primary"><DownloadOutlined />立即下载</a-button>
|
||||||
</a>
|
</a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" tab="断点/分片别名下载" v-if="temp.triggerAliasDownloadUrl">
|
<a-tab-pane tab="断点/分片别名下载" v-if="temp.triggerAliasDownloadUrl">
|
||||||
<a-space style="display: block" direction="vertical" align="baseline">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning">
|
||||||
<template #description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
支持自定义排序字段:sort=createTimeMillis:desc
|
支持自定义排序字段:sort=createTimeMillis:desc
|
||||||
@ -331,28 +339,16 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a-alert
|
<a-alert type="info" :message="`下载地址(点击可以复制)`">
|
||||||
v-clipboard:copy="`${temp.triggerAliasDownloadUrl}`"
|
<template v-slot:description>
|
||||||
v-clipboard:success="
|
<a-typography-paragraph :copyable="{ tooltip: false, text: temp.triggerAliasDownloadUrl }">
|
||||||
() => {
|
<a-tag>GET</a-tag>
|
||||||
tempVue.prototype.$notification.success({ message: '复制成功' })
|
<span>{{ `${temp.triggerAliasDownloadUrl}` }} </span>
|
||||||
}
|
</a-typography-paragraph>
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({ message: '复制失败' })
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`下载地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template #description>
|
|
||||||
<a-tag>GET</a-tag> <span>{{ `${temp.triggerAliasDownloadUrl}` }} </span>
|
|
||||||
<a-icon type="copy" />
|
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a :href="temp.triggerAliasDownloadUrl" target="_blank">
|
<a :href="temp.triggerAliasDownloadUrl" target="_blank">
|
||||||
<a-button size="small" icon="download" type="primary">立即下载</a-button>
|
<a-button size="small" type="primary"><DownloadOutlined />立即下载</a-button>
|
||||||
</a>
|
</a>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
@ -362,19 +358,45 @@
|
|||||||
<!-- 发布文件 -->
|
<!-- 发布文件 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="releaseFileVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="releaseFileVisible"
|
||||||
title="发布文件"
|
title="发布文件"
|
||||||
width="50%"
|
width="50%"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ok="
|
@ok="releaseFileOk()"
|
||||||
() => {
|
|
||||||
this.$refs.releaseFile?.tryCommit()
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<releaseFile ref="releaseFile" v-if="releaseFileVisible" @commit="handleCommitTask"></releaseFile>
|
<releaseFile ref="releaseFile" v-if="releaseFileVisible" @commit="handleCommitTask"></releaseFile>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 选择确认区域 -->
|
||||||
|
<div style="padding-top: 50px" v-if="this.choose">
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: '100%',
|
||||||
|
borderTop: '1px solid #e9e9e9',
|
||||||
|
padding: '10px 16px',
|
||||||
|
background: '#fff',
|
||||||
|
textAlign: 'right',
|
||||||
|
zIndex: 1
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -401,7 +423,7 @@ import {
|
|||||||
triggerUrl
|
triggerUrl
|
||||||
} from '@/api/file-manager/file-storage'
|
} from '@/api/file-manager/file-storage'
|
||||||
import { uploadPieces } from '@/utils/upload-pieces'
|
import { uploadPieces } from '@/utils/upload-pieces'
|
||||||
// import Vue from 'vue'
|
import * as Vue from 'vue'
|
||||||
import releaseFile from './releaseFile.vue'
|
import releaseFile from './releaseFile.vue'
|
||||||
import { addReleaseTask } from '@/api/file-manager/release-task-log'
|
import { addReleaseTask } from '@/api/file-manager/release-task-log'
|
||||||
|
|
||||||
@ -409,49 +431,72 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
releaseFile
|
releaseFile
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
choose: {
|
||||||
|
// "radio"
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
list: [],
|
list: [],
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '文件MD5', dataIndex: 'id', ellipsis: true, width: 100, scopedSlots: { customRender: 'id' } },
|
{
|
||||||
{ title: '名称', dataIndex: 'name', ellipsis: true, width: 150, scopedSlots: { customRender: 'name' } },
|
title: '文件MD5',
|
||||||
|
dataIndex: 'id',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '别名码',
|
title: '别名码',
|
||||||
dataIndex: 'aliasCode',
|
dataIndex: 'aliasCode',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '大小',
|
title: '大小',
|
||||||
dataIndex: 'size',
|
dataIndex: 'size',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'renderSize' },
|
|
||||||
width: '100px'
|
width: '100px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '后缀',
|
title: '后缀',
|
||||||
dataIndex: 'extName',
|
dataIndex: 'extName',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' },
|
tooltip: true,
|
||||||
width: '80px'
|
width: '80px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '共享',
|
title: '共享',
|
||||||
dataIndex: 'workspaceId',
|
dataIndex: 'workspaceId',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'global' },
|
|
||||||
width: '90px'
|
width: '90px'
|
||||||
},
|
},
|
||||||
{ title: '来源', dataIndex: 'source', ellipsis: true, scopedSlots: { customRender: 'source' }, width: '80px' },
|
{
|
||||||
|
title: '来源',
|
||||||
|
dataIndex: 'source',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '过期天数',
|
title: '过期天数',
|
||||||
dataIndex: 'validUntil',
|
dataIndex: 'validUntil',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return '-'
|
return '-'
|
||||||
}
|
}
|
||||||
@ -463,35 +508,35 @@ export default {
|
|||||||
title: '文件状态',
|
title: '文件状态',
|
||||||
dataIndex: 'exists',
|
dataIndex: 'exists',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'exists' },
|
|
||||||
width: '80px'
|
width: '80px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建人',
|
title: '创建人',
|
||||||
dataIndex: 'createUser',
|
dataIndex: 'createUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' },
|
tooltip: true,
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' },
|
tooltip: true,
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -499,7 +544,7 @@ export default {
|
|||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: '170px'
|
width: '170px'
|
||||||
}
|
}
|
||||||
@ -522,7 +567,8 @@ export default {
|
|||||||
tempVue: null,
|
tempVue: null,
|
||||||
triggerVisible: false,
|
triggerVisible: false,
|
||||||
releaseFileVisible: false,
|
releaseFileVisible: false,
|
||||||
tableSelections: []
|
tableSelections: [],
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -534,7 +580,8 @@ export default {
|
|||||||
onChange: (selectedRowKeys) => {
|
onChange: (selectedRowKeys) => {
|
||||||
this.tableSelections = selectedRowKeys
|
this.tableSelections = selectedRowKeys
|
||||||
},
|
},
|
||||||
selectedRowKeys: this.tableSelections
|
selectedRowKeys: this.tableSelections,
|
||||||
|
type: this.choose || 'checkbox'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -569,14 +616,10 @@ export default {
|
|||||||
// 上传文件
|
// 上传文件
|
||||||
handleUploadOk() {
|
handleUploadOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['form'].validate((valid) => {
|
this.$refs['form'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断文件
|
// 判断文件
|
||||||
if (this.fileList.length === 0) {
|
if (this.fileList.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择文件'
|
message: '请选择文件'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@ -584,6 +627,7 @@ export default {
|
|||||||
this.percentage = 0
|
this.percentage = 0
|
||||||
this.percentageInfo = {}
|
this.percentageInfo = {}
|
||||||
this.uploading = true
|
this.uploading = true
|
||||||
|
this.confirmLoading = true
|
||||||
uploadPieces({
|
uploadPieces({
|
||||||
file: this.fileList[0],
|
file: this.fileList[0],
|
||||||
uploadBeforeAbrot: (md5) => {
|
uploadBeforeAbrot: (md5) => {
|
||||||
@ -594,13 +638,14 @@ export default {
|
|||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
//
|
//
|
||||||
$notification.warning({
|
this.$notification.warning({
|
||||||
message: `当前文件已经存在啦,文件名:${res.data.name} ,是否共享:${
|
message: `当前文件已经存在啦,文件名:${res.data.name} ,是否共享:${
|
||||||
res.data.workspaceId === 'GLOBAL' ? '是' : '否'
|
res.data.workspaceId === 'GLOBAL' ? '是' : '否'
|
||||||
}`
|
}`
|
||||||
})
|
})
|
||||||
//
|
//
|
||||||
this.uploading = false
|
this.uploading = false
|
||||||
|
this.confirmLoading = false
|
||||||
} else {
|
} else {
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
@ -619,23 +664,31 @@ export default {
|
|||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
this.loadData()
|
this.loadData()
|
||||||
this.uploadVisible = false
|
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.percentage = 0
|
this.percentage = 0
|
||||||
this.percentageInfo = {}
|
this.percentageInfo = {}
|
||||||
|
this.uploadVisible = false
|
||||||
}, 2000)
|
}, 2000)
|
||||||
this.uploading = false
|
this.uploading = false
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.uploading = false
|
this.uploading = false
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
error: (msg) => {
|
error: (msg) => {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: msg
|
message: msg
|
||||||
})
|
})
|
||||||
this.uploading = false
|
this.uploading = false
|
||||||
|
this.confirmLoading = false
|
||||||
},
|
},
|
||||||
uploadCallback: (formData) => {
|
uploadCallback: (formData) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -660,33 +713,40 @@ export default {
|
|||||||
},
|
},
|
||||||
// 编辑
|
// 编辑
|
||||||
handleEdit(item) {
|
handleEdit(item) {
|
||||||
this.temp = { ...item, global: item.workspaceId === 'GLOBAL', workspaceId: '' }
|
this.temp = {
|
||||||
|
...item,
|
||||||
|
global: item.workspaceId === 'GLOBAL',
|
||||||
|
workspaceId: ''
|
||||||
|
}
|
||||||
this.editVisible = true
|
this.editVisible = true
|
||||||
this.$refs['editForm']?.resetFields()
|
this.$refs['editForm']?.resetFields()
|
||||||
},
|
},
|
||||||
// 编辑确认
|
// 编辑确认
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
this.$refs['editForm'].validate((valid) => {
|
this.$refs['editForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.confirmLoading = true
|
||||||
return false
|
fileEdit(this.temp)
|
||||||
}
|
.then((res) => {
|
||||||
fileEdit(this.temp).then((res) => {
|
if (res.code === 200) {
|
||||||
if (res.code === 200) {
|
// 成功
|
||||||
// 成功
|
this.$notification.success({
|
||||||
$notification.success({
|
message: res.msg
|
||||||
message: res.msg
|
})
|
||||||
})
|
|
||||||
|
|
||||||
this.editVisible = false
|
this.editVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除文件
|
// 删除文件
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除当前文件么?' + record.name,
|
content: '真的要删除当前文件么?' + record.name,
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -696,7 +756,7 @@ export default {
|
|||||||
id: record.id
|
id: record.id
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -709,13 +769,14 @@ export default {
|
|||||||
// 批量删除
|
// 批量删除
|
||||||
handleBatchDelete() {
|
handleBatchDelete() {
|
||||||
if (!this.tableSelections || this.tableSelections.length <= 0) {
|
if (!this.tableSelections || this.tableSelections.length <= 0) {
|
||||||
$notification.warning({
|
this.$notification.warning({
|
||||||
message: '没有选择任何数据'
|
message: '没有选择任何数据'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除这些文件么?',
|
content: '真的要删除这些文件么?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -723,7 +784,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
delFile({ ids: this.tableSelections.join(',') }).then((res) => {
|
delFile({ ids: this.tableSelections.join(',') }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.tableSelections = []
|
this.tableSelections = []
|
||||||
@ -744,21 +805,23 @@ export default {
|
|||||||
// 开始远程下载
|
// 开始远程下载
|
||||||
handleRemoteUpload() {
|
handleRemoteUpload() {
|
||||||
//
|
//
|
||||||
this.$refs['remoteForm'].validate((valid) => {
|
this.$refs['remoteForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.confirmLoading = true
|
||||||
return false
|
remoteDownload(this.temp)
|
||||||
}
|
.then((res) => {
|
||||||
remoteDownload(this.temp).then((res) => {
|
if (res.code === 200) {
|
||||||
if (res.code === 200) {
|
// 成功
|
||||||
// 成功
|
this.$notification.success({
|
||||||
$notification.success({
|
message: res.msg
|
||||||
message: res.msg
|
})
|
||||||
})
|
|
||||||
|
|
||||||
this.uploadRemoteFileVisible = false
|
this.uploadRemoteFileVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 下载地址
|
// 下载地址
|
||||||
@ -770,7 +833,9 @@ export default {
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.fillDownloadUrlResult(res)
|
this.fillDownloadUrlResult(res)
|
||||||
this.triggerVisible = true
|
this.$nextTick(() => {
|
||||||
|
this.triggerVisible = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -781,7 +846,7 @@ export default {
|
|||||||
rest: 'rest'
|
rest: 'rest'
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.fillDownloadUrlResult(res)
|
this.fillDownloadUrlResult(res)
|
||||||
@ -804,21 +869,51 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleCommitTask(data) {
|
handleCommitTask(data) {
|
||||||
addReleaseTask({ ...data, fileId: this.temp.fileId }).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
addReleaseTask({ ...data, fileId: this.temp.fileId, fileType: 1 })
|
||||||
// 成功
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
this.releaseFileVisible = false
|
this.releaseFileVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseFileOk() {
|
||||||
|
this.$refs.releaseFile?.tryCommit()
|
||||||
|
},
|
||||||
|
// 选择确认
|
||||||
|
handerConfirm() {
|
||||||
|
if (!this.tableSelections.length) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '请选择要使用的文件'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selectData = this.list.filter((item) => {
|
||||||
|
return this.tableSelections.indexOf(item.id) > -1
|
||||||
})
|
})
|
||||||
|
if (!selectData.length) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '请选择要使用的文件'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$emit('confirm', selectData)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
emits: ['cancel', 'confirm']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/deep/ .ant-progress-text {
|
/deep/ .ant-progress-text {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
>
|
||||||
<a-form-item label="任务名" name="name">
|
<a-form-item label="任务名" name="name">
|
||||||
<a-input placeholder="请输入任务名" :maxLength="50" v-model="temp.name" />
|
<a-input placeholder="请输入任务名" :maxLength="50" v-model:value="temp.name" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="发布方式" name="taskType">
|
<a-form-item label="发布方式" name="taskType">
|
||||||
<a-radio-group v-model="temp.taskType" @change="taskTypeChange">
|
<a-radio-group v-model:value="temp.taskType" @change="taskTypeChange">
|
||||||
<a-radio :value="0"> SSH </a-radio>
|
<a-radio :value="0"> SSH </a-radio>
|
||||||
<a-radio :value="1"> 节点 </a-radio>
|
<a-radio :value="1"> 节点 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
@ -25,7 +25,7 @@
|
|||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="temp.taskDataIds"
|
v-model:value="temp.taskDataIds"
|
||||||
placeholder="请选择SSH"
|
placeholder="请选择SSH"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="ssh in sshList" :key="ssh.id">
|
<a-select-option v-for="ssh in sshList" :key="ssh.id">
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="1" style="margin-left: 10px">
|
<a-col :span="1" style="margin-left: 10px">
|
||||||
<a-icon type="reload" @click="loadSshList" />
|
<ReloadOutlined @click="loadSshList" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -45,7 +45,7 @@
|
|||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="temp.taskDataIds"
|
v-model:value="temp.taskDataIds"
|
||||||
placeholder="请选择节点"
|
placeholder="请选择节点"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="ssh in nodeList" :key="ssh.id">
|
<a-select-option v-for="ssh in nodeList" :key="ssh.id">
|
||||||
@ -54,16 +54,15 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="1" style="margin-left: 10px">
|
<a-col :span="1" style="margin-left: 10px">
|
||||||
<a-icon type="reload" @click="loadNodeList" />
|
<ReloadOutlined @click="loadNodeList" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item name="releasePathParent" label="发布目录">
|
<a-form-item name="releasePathParent" label="发布目录">
|
||||||
<template #help>
|
<template v-slot:help>
|
||||||
<a-tooltip title="需要配置授权目录(白名单才能正常使用发布),授权目录主要是用于确定可以发布到哪些目录中"
|
<a-tooltip title="需要配置授权目录(授权才能正常使用发布),授权目录主要是用于确定可以发布到哪些目录中"
|
||||||
><a-button
|
><a-button
|
||||||
icon="info-circle"
|
|
||||||
size="small"
|
size="small"
|
||||||
type="link"
|
type="link"
|
||||||
@click="
|
@click="
|
||||||
@ -72,55 +71,68 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
配置目录
|
<InfoCircleOutlined />配置目录
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-tooltip></template
|
</a-tooltip>
|
||||||
>
|
</template>
|
||||||
<a-input-group compact>
|
<a-input-group compact>
|
||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
allowClear
|
allowClear
|
||||||
style="width: 30%"
|
style="width: 30%"
|
||||||
v-model="temp.releasePathParent"
|
v-model:value="temp.releasePathParent"
|
||||||
placeholder="请选择发布的一级目录"
|
placeholder="请选择发布的一级目录"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="item in accessList" :key="item">
|
<a-select-option v-for="item in accessList" :key="item">
|
||||||
<a-tooltip :title="item">{{ item }}</a-tooltip>
|
<a-tooltip :title="item">{{ item }}</a-tooltip>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
<a-icon #suffixIcon type="reload" @click="loadAccesList" />
|
<template v-slot:suffixIcon>
|
||||||
|
<ReloadOutlined @click="loadAccesList" />
|
||||||
|
</template>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
<a-form-item-rest>
|
||||||
<a-input style="width: 70%" v-model="temp.releasePathSecondary" placeholder="请填写发布的二级目录" />
|
<a-input style="width: 70%" v-model:value="temp.releasePathSecondary" placeholder="请填写发布的二级目录" />
|
||||||
|
</a-form-item-rest>
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="执行脚本" name="releaseBeforeCommand">
|
<a-form-item label="执行脚本" name="releaseBeforeCommand">
|
||||||
<a-tabs tabPosition="right">
|
<a-form-item-rest>
|
||||||
<a-tab-pane key="before" tab="上传前">
|
<a-tabs tabPosition="right">
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<a-tab-pane key="before" tab="上传前">
|
||||||
<code-editor
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
v-model="temp.beforeScript"
|
<code-editor
|
||||||
:options="{ mode: temp.taskType === 0 ? 'shell' : '', tabSize: 2, theme: 'abcdef' }"
|
v-model:content="temp.beforeScript"
|
||||||
></code-editor>
|
:options="{
|
||||||
</div>
|
mode: temp.taskType === 0 ? 'shell' : '',
|
||||||
<div style="margin-top: 10px">文件上传前需要执行的脚本(非阻塞命令)</div>
|
tabSize: 2,
|
||||||
</a-tab-pane>
|
theme: 'abcdef'
|
||||||
<a-tab-pane key="after" tab="上传后">
|
}"
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
></code-editor>
|
||||||
<code-editor
|
</div>
|
||||||
v-model="temp.afterScript"
|
<div style="margin-top: 10px">文件上传前需要执行的脚本(非阻塞命令)</div>
|
||||||
:options="{ mode: temp.taskType === 0 ? 'shell' : '', tabSize: 2, theme: 'abcdef' }"
|
</a-tab-pane>
|
||||||
></code-editor>
|
<a-tab-pane key="after" tab="上传后">
|
||||||
</div>
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
<div style="margin-top: 10px">文件上传成功后需要执行的脚本(非阻塞命令)</div>
|
<code-editor
|
||||||
</a-tab-pane>
|
v-model:content="temp.afterScript"
|
||||||
</a-tabs>
|
:options="{
|
||||||
|
mode: temp.taskType === 0 ? 'shell' : '',
|
||||||
|
tabSize: 2,
|
||||||
|
theme: 'abcdef'
|
||||||
|
}"
|
||||||
|
></code-editor>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 10px">文件上传成功后需要执行的脚本(非阻塞命令)</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-form-item-rest>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="configDir"
|
v-model:value="configDir"
|
||||||
:title="`配置授权目录`"
|
:title="`配置授权目录`"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -142,6 +154,7 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getSshListAll } from '@/api/ssh'
|
import { getSshListAll } from '@/api/ssh'
|
||||||
import { getDispatchWhiteList } from '@/api/dispatch'
|
import { getDispatchWhiteList } from '@/api/dispatch'
|
||||||
@ -159,7 +172,13 @@ export default {
|
|||||||
releaseFileRules: {
|
releaseFileRules: {
|
||||||
name: [{ required: true, message: '请输入文件任务名', trigger: 'blur' }],
|
name: [{ required: true, message: '请输入文件任务名', trigger: 'blur' }],
|
||||||
taskType: [{ required: true, message: '请选择发布方式', trigger: 'blur' }],
|
taskType: [{ required: true, message: '请选择发布方式', trigger: 'blur' }],
|
||||||
releasePath: [{ required: true, message: '请选择发布的一级目录和填写二级目录', trigger: 'blur' }],
|
releasePath: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择发布的一级目录和填写二级目录',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
taskDataIds: [{ required: true, message: '请选择发布的SSH', trigger: 'blur' }]
|
taskDataIds: [{ required: true, message: '请选择发布的SSH', trigger: 'blur' }]
|
||||||
},
|
},
|
||||||
sshList: [],
|
sshList: [],
|
||||||
@ -185,14 +204,14 @@ export default {
|
|||||||
},
|
},
|
||||||
// 创建任务
|
// 创建任务
|
||||||
tryCommit() {
|
tryCommit() {
|
||||||
this.$refs['releaseFileForm'].validate((valid) => {
|
this.$refs['releaseFileForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.$emit('commit', {
|
||||||
return false
|
...this.temp,
|
||||||
}
|
taskDataIds: this.temp.taskDataIds?.join(',')
|
||||||
this.$emit('commit', { ...this.temp, taskDataIds: this.temp.taskDataIds?.join(',') })
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 加载项目白名单列表
|
// 加载项目授权列表
|
||||||
loadAccesList() {
|
loadAccesList() {
|
||||||
getDispatchWhiteList().then((res) => {
|
getDispatchWhiteList().then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@ -220,6 +239,7 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
emits: ['commit']
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<a-form-item label="执行日志">
|
<a-form-item label="执行日志">
|
||||||
<a-tabs :activeKey="activeKey" @change="tabCallback">
|
<a-tabs :activeKey="activeKey" @change="tabCallback">
|
||||||
<a-tab-pane v-for="item in temp.taskList" :key="item.id">
|
<a-tab-pane v-for="item in temp.taskList" :key="item.id">
|
||||||
<template #tab>
|
<template v-slot:tab>
|
||||||
<a-icon v-if="!logMap[item.id] || logMap[item.id].run" type="loading" />
|
<LoadingOutlined v-if="!logMap[item.id] || logMap[item.id].run" type="loading" />
|
||||||
<template v-if="temp.taskData && temp.taskData.taskType === 0">
|
<template v-if="temp.taskData && temp.taskData.taskType === 0">
|
||||||
{{
|
{{
|
||||||
sshList.filter((item2) => {
|
sshList.filter((item2) => {
|
||||||
@ -45,7 +45,7 @@
|
|||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
<template>
|
<template>
|
||||||
<a-tooltip v-if="item.statusMsg" :title="item.statusMsg"><a-icon type="info-circle" /></a-tooltip>
|
<a-tooltip v-if="item.statusMsg" :title="item.statusMsg"><InfoCircleOutlined /></a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<log-view :ref="`logView-${item.id}`" height="60vh" />
|
<log-view :ref="`logView-${item.id}`" height="60vh" />
|
||||||
@ -57,7 +57,7 @@
|
|||||||
<a-tab-pane key="before" tab="上传前">
|
<a-tab-pane key="before" tab="上传前">
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
<code-editor
|
<code-editor
|
||||||
:code="temp.taskData && temp.taskData.beforeScript"
|
:content="temp.taskData && temp.taskData.beforeScript"
|
||||||
:options="{
|
:options="{
|
||||||
mode: temp.taskData && temp.taskData.taskType === 0 ? 'shell' : '',
|
mode: temp.taskData && temp.taskData.taskType === 0 ? 'shell' : '',
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
@ -70,7 +70,7 @@
|
|||||||
<a-tab-pane key="after" tab="上传后">
|
<a-tab-pane key="after" tab="上传后">
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
<code-editor
|
<code-editor
|
||||||
:code="temp.taskData && temp.taskData.afterScript"
|
:content="temp.taskData && temp.taskData.afterScript"
|
||||||
:options="{
|
:options="{
|
||||||
mode: temp.taskData && temp.taskData.taskType === 0 ? 'shell' : '',
|
mode: temp.taskData && temp.taskData.taskType === 0 ? 'shell' : '',
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
@ -85,9 +85,10 @@
|
|||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { taskDetails, statusMap, taskLogInfoList } from '@/api/file-manager/release-task-log'
|
import { taskDetails, statusMap, taskLogInfoList } from '@/api/file-manager/release-task-log'
|
||||||
import LogView from '@/components/logView'
|
import LogView from '@/components/logView/index2'
|
||||||
import codeEditor from '@/components/codeEditor'
|
import codeEditor from '@/components/codeEditor'
|
||||||
import { getSshListAll } from '@/api/ssh'
|
import { getSshListAll } from '@/api/ssh'
|
||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
@ -114,7 +115,7 @@ export default {
|
|||||||
nodeList: []
|
nodeList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
if (this.logTimerMap) {
|
if (this.logTimerMap) {
|
||||||
this.temp.taskList?.forEach((item) => {
|
this.temp.taskList?.forEach((item) => {
|
||||||
clearInterval(this.logTimerMap[item.id])
|
clearInterval(this.logTimerMap[item.id])
|
||||||
@ -190,7 +191,7 @@ export default {
|
|||||||
taskLogInfoList(params).then((res) => {
|
taskLogInfoList(params).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (!res.data) {
|
if (!res.data) {
|
||||||
$notification.warning({
|
this.$notification.warning({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
if (res.data.status !== 0) {
|
if (res.data.status !== 0) {
|
||||||
@ -226,7 +227,7 @@ export default {
|
|||||||
if (this.logTimerMap[key]) {
|
if (this.logTimerMap[key]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const data = this.temp.taskList?.filter((item1) => {
|
const data = this.temp.taskList?.filter((item1) => {
|
||||||
return item1.id === key
|
return item1.id === key
|
||||||
})[0]
|
})[0]
|
||||||
@ -236,4 +237,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<a-table
|
<a-table
|
||||||
size="middle"
|
size="middle"
|
||||||
:data-source="commandList"
|
:data-source="commandList"
|
||||||
@ -13,11 +13,14 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="任务名"
|
placeholder="任务名"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -25,7 +28,7 @@
|
|||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
v-model="listQuery.status"
|
v-model:value="listQuery.status"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="状态"
|
placeholder="状态"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -35,7 +38,7 @@
|
|||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
v-model="listQuery.taskType"
|
v-model:value="listQuery.taskType"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="发布类型"
|
placeholder="发布类型"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -47,45 +50,61 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #tooltip slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.tooltip">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #fileId slot-scope="text, item">
|
<template v-else-if="column.dataIndex === 'fileId'">
|
||||||
<a-button type="link" style="padding: 0" @click="handleViewFile(item)" size="small">{{ text }}</a-button>
|
<a-tooltip :title="text">
|
||||||
</template>
|
<a-button type="link" style="padding: 0" @click="handleViewFile(record)" size="small">{{
|
||||||
|
(text || '').slice(0, 10)
|
||||||
|
}}</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #status slot-scope="text">
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
<a-tag v-if="text === 2" color="green">{{ statusMap[text] || '未知' }}</a-tag>
|
<a-tag v-if="text === 2" color="green">{{ statusMap[text] || '未知' }}</a-tag>
|
||||||
<a-tag v-else-if="text === 0 || text === 1" color="orange">{{ statusMap[text] || '未知' }}</a-tag>
|
<a-tag v-else-if="text === 0 || text === 1" color="orange">{{ statusMap[text] || '未知' }}</a-tag>
|
||||||
<a-tag v-else-if="text === 4" color="blue"> {{ statusMap[text] || '未知' }} </a-tag>
|
<a-tag v-else-if="text === 4" color="blue">
|
||||||
<a-tag v-else-if="text === 3" color="red">{{ statusMap[text] || '未知' }}</a-tag>
|
{{ statusMap[text] || '未知' }}
|
||||||
<a-tag v-else>{{ statusMap[text] || '未知' }}</a-tag>
|
</a-tag>
|
||||||
</template>
|
<a-tag v-else-if="text === 3" color="red">{{ statusMap[text] || '未知' }}</a-tag>
|
||||||
<template #taskType slot-scope="text">
|
<a-tag v-else>{{ statusMap[text] || '未知' }}</a-tag>
|
||||||
<span>{{ taskTypeMap[text] || '未知' }}</span>
|
</template>
|
||||||
</template>
|
<template v-else-if="column.dataIndex === 'taskType'">
|
||||||
|
<span>{{ taskTypeMap[text] || '未知' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'fileType'">
|
||||||
|
<span v-if="text == 2">静态文件</span>
|
||||||
|
<span v-else>文件中心</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="primary" size="small" @click="handleView(record)">查看</a-button>
|
<a-button type="primary" size="small" @click="handleView(record)">查看</a-button>
|
||||||
|
|
||||||
<a-button type="primary" size="small" @click="handleRetask(record)">重建</a-button>
|
<a-button type="primary" size="small" @click="handleRetask(record)">重建</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
type="danger"
|
type="primary"
|
||||||
size="small"
|
danger
|
||||||
:disabled="!(record.status === 0 || record.status === 1)"
|
size="small"
|
||||||
@click="handleCancelTask(record)"
|
:disabled="!(record.status === 0 || record.status === 1)"
|
||||||
>取消</a-button
|
@click="handleCancelTask(record)"
|
||||||
>
|
>取消</a-button
|
||||||
<a-button
|
>
|
||||||
type="danger"
|
<a-button
|
||||||
size="small"
|
type="primary"
|
||||||
:disabled="record.status === 0 || record.status === 1"
|
danger
|
||||||
@click="handleDelete(record)"
|
size="small"
|
||||||
>删除</a-button
|
:disabled="record.status === 0 || record.status === 1"
|
||||||
>
|
@click="handleDelete(record)"
|
||||||
</a-space>
|
>删除</a-button
|
||||||
|
>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 任务详情 -->
|
<!-- 任务详情 -->
|
||||||
@ -93,19 +112,20 @@
|
|||||||
title="任务详情"
|
title="任务详情"
|
||||||
placement="right"
|
placement="right"
|
||||||
:width="'80vw'"
|
:width="'80vw'"
|
||||||
:visible="detailsVisible"
|
:open="detailsVisible"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.detailsVisible = false
|
this.detailsVisible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<task-details-page v-if="detailsVisible" :taskId="temp.id" />
|
<task-details-page v-if="detailsVisible" :taskId="this.temp.id" />
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
<!-- 重建任务 -->
|
<!-- 重建任务 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="releaseFileVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="releaseFileVisible"
|
||||||
title="发布文件"
|
title="发布文件"
|
||||||
width="50%"
|
width="50%"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -119,11 +139,11 @@
|
|||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
>
|
||||||
<a-form-item label="任务名" name="name">
|
<a-form-item label="任务名" name="name">
|
||||||
<a-input placeholder="请输入任务名" :maxLength="50" v-model="temp.name" />
|
<a-input placeholder="请输入任务名" :maxLength="50" v-model:value="temp.name" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="发布方式" name="taskType">
|
<a-form-item label="发布方式" name="taskType">
|
||||||
<a-radio-group v-model="temp.taskType" :disabled="true">
|
<a-radio-group v-model:value="temp.taskType" :disabled="true">
|
||||||
<a-radio :value="0"> SSH </a-radio>
|
<a-radio :value="0"> SSH </a-radio>
|
||||||
<a-radio :value="1"> 节点 </a-radio>
|
<a-radio :value="1"> 节点 </a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
@ -136,7 +156,7 @@
|
|||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="temp.taskDataIds"
|
v-model:value="temp.taskDataIds"
|
||||||
placeholder="请选择SSH"
|
placeholder="请选择SSH"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="ssh in sshList" :key="ssh.id">
|
<a-select-option v-for="ssh in sshList" :key="ssh.id">
|
||||||
@ -145,7 +165,7 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="1" style="margin-left: 10px">
|
<a-col :span="1" style="margin-left: 10px">
|
||||||
<a-icon type="reload" @click="loadSshList" />
|
<ReloadOutlined @click="loadSshList" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -156,7 +176,7 @@
|
|||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="temp.taskDataIds"
|
v-model:value="temp.taskDataIds"
|
||||||
placeholder="请选择节点"
|
placeholder="请选择节点"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="ssh in nodeList" :key="ssh.id">
|
<a-select-option v-for="ssh in nodeList" :key="ssh.id">
|
||||||
@ -165,45 +185,55 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="1" style="margin-left: 10px">
|
<a-col :span="1" style="margin-left: 10px">
|
||||||
<a-icon type="reload" @click="loadNodeList" />
|
<ReloadOutlined @click="loadNodeList" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item name="releasePathParent" label="发布目录">
|
<a-form-item name="releasePathParent" label="发布目录">
|
||||||
<a-input placeholder="请输入发布目录" :disabled="true" v-model="temp.releasePath" />
|
<a-input placeholder="请输入发布目录" :disabled="true" v-model:value="temp.releasePath" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item name="releasePathParent" label="文件id">
|
<a-form-item name="releasePathParent" label="文件id">
|
||||||
<a-input placeholder="请输入发布的文件id" v-model="temp.fileId" />
|
<a-input placeholder="请输入发布的文件id" v-model:value="temp.fileId" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="执行脚本" name="releaseBeforeCommand">
|
<a-form-item label="执行脚本" name="releaseBeforeCommand">
|
||||||
<a-tabs tabPosition="right">
|
<a-form-item-rest>
|
||||||
<a-tab-pane key="before" tab="上传前">
|
<a-tabs tabPosition="right">
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<a-tab-pane key="before" tab="上传前">
|
||||||
<code-editor
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
v-model="temp.beforeScript"
|
<code-editor
|
||||||
:options="{ mode: temp.taskType === 0 ? 'shell' : '', tabSize: 2, theme: 'abcdef' }"
|
v-model:content="temp.beforeScript"
|
||||||
></code-editor>
|
:options="{
|
||||||
</div>
|
mode: temp.taskType === 0 ? 'shell' : '',
|
||||||
<div style="margin-top: 10px">文件上传前需要执行的脚本(非阻塞命令)</div>
|
tabSize: 2,
|
||||||
</a-tab-pane>
|
theme: 'abcdef'
|
||||||
<a-tab-pane key="after" tab="上传后">
|
}"
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
></code-editor>
|
||||||
<code-editor
|
</div>
|
||||||
v-model="temp.afterScript"
|
<div style="margin-top: 10px">文件上传前需要执行的脚本(非阻塞命令)</div>
|
||||||
:options="{ mode: temp.taskType === 0 ? 'shell' : '', tabSize: 2, theme: 'abcdef' }"
|
</a-tab-pane>
|
||||||
></code-editor>
|
<a-tab-pane key="after" tab="上传后">
|
||||||
</div>
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
<div style="margin-top: 10px">文件上传成功后需要执行的脚本(非阻塞命令)</div>
|
<code-editor
|
||||||
</a-tab-pane>
|
v-model:content="temp.afterScript"
|
||||||
</a-tabs>
|
:options="{
|
||||||
|
mode: temp.taskType === 0 ? 'shell' : '',
|
||||||
|
tabSize: 2,
|
||||||
|
theme: 'abcdef'
|
||||||
|
}"
|
||||||
|
></code-editor>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 10px">文件上传成功后需要执行的脚本(非阻塞命令)</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-form-item-rest>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 查看文件 -->
|
<!-- 查看文件 -->
|
||||||
<a-modal destroyOnClose v-model:visible="viewFileVisible" :title="`查看文件`" :footer="null" :maskClosable="false">
|
<a-modal destroyOnClose v-model:open="viewFileVisible" :title="`查看文件`" :footer="null" :maskClosable="false">
|
||||||
<a-form :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-form-item label="文件名" name="name">
|
<a-form-item label="文件名" name="name">
|
||||||
{{ temp.name }}
|
{{ temp.name }}
|
||||||
@ -214,10 +244,10 @@
|
|||||||
<a-form-item label="文件大小" name="size">
|
<a-form-item label="文件大小" name="size">
|
||||||
{{ renderSize(temp.size) }}
|
{{ renderSize(temp.size) }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="过期时间" name="keepDay">
|
<a-form-item label="过期时间" name="validUntil" v-if="temp.validUntil">
|
||||||
{{ parseTime(temp.validUntil) }}
|
{{ parseTime(temp.validUntil) }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件共享" name="global">
|
<a-form-item label="文件共享" name="global" v-if="temp.workspaceId">
|
||||||
{{ temp.workspaceId === 'GLOBAL' ? '全局' : '工作空间' }}
|
{{ temp.workspaceId === 'GLOBAL' ? '全局' : '工作空间' }}
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文件描述" name="description">
|
<a-form-item label="文件描述" name="description">
|
||||||
@ -244,7 +274,7 @@ import { getSshListAll } from '@/api/ssh'
|
|||||||
import codeEditor from '@/components/codeEditor'
|
import codeEditor from '@/components/codeEditor'
|
||||||
import { hasFile } from '@/api/file-manager/file-storage'
|
import { hasFile } from '@/api/file-manager/file-storage'
|
||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
|
import { hasStaticFile } from '@/api/file-manager/static-storage'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
taskDetailsPage,
|
taskDetailsPage,
|
||||||
@ -259,45 +289,66 @@ export default {
|
|||||||
statusMap,
|
statusMap,
|
||||||
taskTypeMap,
|
taskTypeMap,
|
||||||
detailsVisible: false,
|
detailsVisible: false,
|
||||||
|
confirmLoading: false,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '任务名称', dataIndex: 'name', ellipsis: true, width: 150, scopedSlots: { customRender: 'tooltip' } },
|
{
|
||||||
|
title: '任务名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '分发类型',
|
title: '分发类型',
|
||||||
dataIndex: 'taskType',
|
dataIndex: 'taskType',
|
||||||
width: '100px',
|
width: '100px',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'taskType' }
|
},
|
||||||
|
{
|
||||||
|
title: '文件来源',
|
||||||
|
dataIndex: 'fileType',
|
||||||
|
width: '100px',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: '100px',
|
||||||
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{ title: '状态', dataIndex: 'status', width: '100px', ellipsis: true, scopedSlots: { customRender: 'status' } },
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '状态描述',
|
title: '状态描述',
|
||||||
dataIndex: 'statusMsg',
|
dataIndex: 'statusMsg',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 200,
|
width: 200,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '文件ID',
|
||||||
|
dataIndex: 'fileId',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150
|
||||||
},
|
},
|
||||||
{ title: '文件ID', dataIndex: 'fileId', ellipsis: true, width: 150, scopedSlots: { customRender: 'fileId' } },
|
|
||||||
{
|
{
|
||||||
title: '发布目录',
|
title: '发布目录',
|
||||||
dataIndex: 'releasePath',
|
dataIndex: 'releasePath',
|
||||||
width: '100px',
|
width: '100px',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '执行人',
|
title: '执行人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'modifyUser' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '任务时间',
|
title: '任务时间',
|
||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -305,7 +356,7 @@ export default {
|
|||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -313,7 +364,7 @@ export default {
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: '230px'
|
width: '230px'
|
||||||
}
|
}
|
||||||
@ -361,8 +412,9 @@ export default {
|
|||||||
|
|
||||||
// 删除命令
|
// 删除命令
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除该执行记录吗?',
|
content: '真的要删除该执行记录吗?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -372,7 +424,7 @@ export default {
|
|||||||
id: row.id
|
id: row.id
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -430,27 +482,33 @@ export default {
|
|||||||
},
|
},
|
||||||
// 创建任务
|
// 创建任务
|
||||||
handleReCrateTask() {
|
handleReCrateTask() {
|
||||||
this.$refs['releaseFileForm'].validate((valid) => {
|
this.$refs['releaseFileForm'].validate().then(() => {
|
||||||
if (!valid) {
|
this.confirmLoading = true
|
||||||
return false
|
reReleaseTask({
|
||||||
}
|
...this.temp,
|
||||||
reReleaseTask({ ...this.temp, taskDataIds: this.temp.taskDataIds?.join(',') }).then((res) => {
|
taskDataIds: this.temp.taskDataIds?.join(',')
|
||||||
if (res.code === 200) {
|
|
||||||
// 成功
|
|
||||||
$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
|
|
||||||
this.releaseFileVisible = false
|
|
||||||
this.loadData()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 成功
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.releaseFileVisible = false
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 取消
|
// 取消
|
||||||
handleCancelTask(record) {
|
handleCancelTask(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的取消当前发布任务吗?',
|
content: '真的取消当前发布任务吗?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -458,7 +516,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
cancelReleaseTask({ id: record.id }).then((res) => {
|
cancelReleaseTask({ id: record.id }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -469,22 +527,39 @@ export default {
|
|||||||
},
|
},
|
||||||
// 查看文件
|
// 查看文件
|
||||||
handleViewFile(record) {
|
handleViewFile(record) {
|
||||||
hasFile({
|
if (record.fileType === 2) {
|
||||||
fileSumMd5: record.fileId
|
//
|
||||||
}).then((res) => {
|
hasStaticFile({
|
||||||
if (res.code === 200) {
|
fileId: record.fileId
|
||||||
if (res.data) {
|
}).then((res) => {
|
||||||
this.temp = res.data
|
if (res.code === 200) {
|
||||||
this.viewFileVisible = true
|
if (res.data) {
|
||||||
} else {
|
this.temp = res.data
|
||||||
$notification.warning({
|
this.viewFileVisible = true
|
||||||
message: '文件不存在啦'
|
} else {
|
||||||
})
|
this.$notification.warning({
|
||||||
|
message: '文件不存在啦'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
} else {
|
||||||
|
hasFile({
|
||||||
|
fileSumMd5: record.fileId
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
if (res.data) {
|
||||||
|
this.temp = res.data
|
||||||
|
this.viewFileVisible = true
|
||||||
|
} else {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '文件不存在啦'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
609
web-vue3/src/pages/file-manager/staticFileStorage/list.vue
Normal file
609
web-vue3/src/pages/file-manager/staticFileStorage/list.vue
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<a-table
|
||||||
|
:data-source="list"
|
||||||
|
size="middle"
|
||||||
|
:columns="columns"
|
||||||
|
:pagination="pagination"
|
||||||
|
@change="
|
||||||
|
(pagination, filters, sorter) => {
|
||||||
|
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter })
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
bordered
|
||||||
|
rowKey="id"
|
||||||
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template v-slot:title>
|
||||||
|
<a-space>
|
||||||
|
<a-input
|
||||||
|
v-model:value="listQuery['%name%']"
|
||||||
|
@pressEnter="loadData"
|
||||||
|
placeholder="文件名称"
|
||||||
|
class="search-input-item"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<a-input
|
||||||
|
v-model:value="listQuery['extName']"
|
||||||
|
@pressEnter="loadData"
|
||||||
|
placeholder="后缀,精准搜索"
|
||||||
|
class="search-input-item"
|
||||||
|
/>
|
||||||
|
<a-input
|
||||||
|
v-model:value="listQuery['id']"
|
||||||
|
@pressEnter="loadData"
|
||||||
|
placeholder="文件id,精准搜索"
|
||||||
|
class="search-input-item"
|
||||||
|
/>
|
||||||
|
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
||||||
|
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<!-- <a-button type="primary" @click="handleUpload">上传文件</a-button> -->
|
||||||
|
<a-button type="primary" @click="reScanner">扫描</a-button>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
:disabled="!tableSelections || tableSelections.length <= 0"
|
||||||
|
@click="handleBatchDelete"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
|
<template v-if="column.tooltip">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'id'">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span v-if="record.status === 0 || record.status === 2">-</span>
|
||||||
|
<span v-else>{{ (text || '').slice(0, 8) }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'name'">
|
||||||
|
<a-popover title="文件信息">
|
||||||
|
<template v-slot:content>
|
||||||
|
<p>文件ID:{{ record.id }}</p>
|
||||||
|
<p>文件名:{{ text }}</p>
|
||||||
|
<p>文件描述:{{ record.description }}</p>
|
||||||
|
</template>
|
||||||
|
<!-- {{ text }} -->
|
||||||
|
<a-button type="link" style="padding: 0" @click="handleEdit(record)" size="small">{{ text }}</a-button>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'size'">
|
||||||
|
<a-tooltip placement="topLeft" :title="renderSize(text)">
|
||||||
|
<span>{{ renderSize(text) }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'source'">
|
||||||
|
<a-tooltip placement="topLeft" :title="`${sourceMap[text] || '未知'}`">
|
||||||
|
<span>{{ sourceMap[text] || '未知' }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
|
<a-tag v-if="text === 1" color="green">存在</a-tag>
|
||||||
|
<a-tag v-else color="red">丢失</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'type'">
|
||||||
|
<a-tag v-if="text === 1">文件</a-tag>
|
||||||
|
<a-tag v-else>文件夹</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-space>
|
||||||
|
<!-- <a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button> -->
|
||||||
|
<a-button
|
||||||
|
size="small"
|
||||||
|
:disabled="!(record.status === 1 && record.type === 1)"
|
||||||
|
type="primary"
|
||||||
|
@click="handleDownloadUrl(record)"
|
||||||
|
>
|
||||||
|
下载</a-button
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
size="small"
|
||||||
|
:disabled="!(record.status === 1 && record.type === 1)"
|
||||||
|
type="primary"
|
||||||
|
@click="handleReleaseFile(record)"
|
||||||
|
>发布</a-button
|
||||||
|
>
|
||||||
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
|
||||||
|
<!-- 编辑文件 -->
|
||||||
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
v-model:open="editVisible"
|
||||||
|
:title="`修改文件`"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
@ok="handleEditOk"
|
||||||
|
:maskClosable="false"
|
||||||
|
>
|
||||||
|
<a-form ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
|
<a-form-item label="文件名" name="name">
|
||||||
|
<a-input placeholder="文件名" :disabled="true" v-model:value="temp.name" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="文件描述" name="description">
|
||||||
|
<a-textarea v-model:value="temp.description" placeholder="请输入文件描述" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<!-- 断点下载 -->
|
||||||
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
v-model:open="triggerVisible"
|
||||||
|
title="断点/分片下载"
|
||||||
|
width="50%"
|
||||||
|
:footer="null"
|
||||||
|
:maskClosable="false"
|
||||||
|
>
|
||||||
|
<a-form ref="editTriggerForm" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
|
<a-tabs default-active-key="1">
|
||||||
|
<template v-slot:rightExtra>
|
||||||
|
<a-tooltip title="重置下载 token 信息,重置后之前的下载 token 将失效">
|
||||||
|
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<a-tab-pane key="1" tab="断点/分片单文件下载">
|
||||||
|
<a-space direction="vertical" style="width: 100%">
|
||||||
|
<a-alert type="info" :message="`下载地址(点击可以复制)`">
|
||||||
|
<template v-slot:description>
|
||||||
|
<a-typography-paragraph :copyable="{ text: temp.triggerDownloadUrl }">
|
||||||
|
<a-tag>GET</a-tag>
|
||||||
|
<span>{{ `${temp.triggerDownloadUrl}` }} </span>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a :href="temp.triggerDownloadUrl" target="_blank">
|
||||||
|
<a-button size="small" type="primary"><DownloadOutlined />立即下载</a-button>
|
||||||
|
</a>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane tab="断点/分片别名下载" v-if="temp.triggerAliasDownloadUrl">
|
||||||
|
<a-space direction="vertical" style="width: 100%">
|
||||||
|
<a-alert message="温馨提示" type="warning">
|
||||||
|
<template v-slot:description>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
支持自定义排序字段:sort=createTimeMillis:desc
|
||||||
|
|
||||||
|
<p>描述根据创建时间升序第一个</p>
|
||||||
|
</li>
|
||||||
|
<li>支持的字段可以通过接口返回的查看</li>
|
||||||
|
<li>通用的字段有:createTimeMillis、modifyTimeMillis</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert type="info" :message="`下载地址(点击可以复制)`">
|
||||||
|
<template v-slot:description>
|
||||||
|
<a-typography-paragraph :copyable="{ text: temp.triggerAliasDownloadUrl }">
|
||||||
|
<a-tag>GET</a-tag>
|
||||||
|
<span>{{ `${temp.triggerAliasDownloadUrl}` }} </span>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a :href="temp.triggerAliasDownloadUrl" target="_blank">
|
||||||
|
<a-button size="small" type="primary"><DownloadOutlined />立即下载</a-button>
|
||||||
|
</a>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
<!-- 发布文件 -->
|
||||||
|
<a-modal
|
||||||
|
destroyOnClose
|
||||||
|
v-model:open="releaseFileVisible"
|
||||||
|
title="发布文件"
|
||||||
|
width="50%"
|
||||||
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
@ok="releaseFileOk()"
|
||||||
|
>
|
||||||
|
<releaseFile ref="releaseFile" v-if="releaseFileVisible" @commit="handleCommitTask"></releaseFile>
|
||||||
|
</a-modal>
|
||||||
|
</div>
|
||||||
|
<!-- 选择确认区域
|
||||||
|
<div style="padding-top: 50px" v-if="this.choose">
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: '100%',
|
||||||
|
borderTop: '1px solid #e9e9e9',
|
||||||
|
padding: '10px 16px',
|
||||||
|
background: '#fff',
|
||||||
|
textAlign: 'right',
|
||||||
|
zIndex: 1
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$emit('cancel')
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
CHANGE_PAGE,
|
||||||
|
COMPUTED_PAGINATION,
|
||||||
|
PAGE_DEFAULT_LIST_QUERY,
|
||||||
|
parseTime,
|
||||||
|
renderSize,
|
||||||
|
formatDuration,
|
||||||
|
randomStr
|
||||||
|
} from '@/utils/const'
|
||||||
|
// import { uploadFile, uploadFileMerge, hasFile } from "@/api/file-manager/file-storage";
|
||||||
|
import { staticFileStorageList, delFile, triggerUrl, fileEdit, staticScanner } from '@/api/file-manager/static-storage'
|
||||||
|
|
||||||
|
import releaseFile from '@/pages/file-manager/fileStorage/releaseFile'
|
||||||
|
import { addReleaseTask } from '@/api/file-manager/release-task-log'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
releaseFile
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
choose: {
|
||||||
|
// "radio"
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
|
list: [],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'description',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '路径',
|
||||||
|
dataIndex: 'absolutePath',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 150,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '大小',
|
||||||
|
dataIndex: 'size',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
width: '100px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '后缀',
|
||||||
|
dataIndex: 'extName',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
tooltip: true,
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '文件状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
width: '80px'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '文件修改时间',
|
||||||
|
dataIndex: 'lastModified',
|
||||||
|
sorter: true,
|
||||||
|
customRender: ({ text }) => parseTime(text),
|
||||||
|
width: '170px'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
align: 'center',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
fixed: 'right',
|
||||||
|
width: '170px'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
name: [{ required: true, message: '请输入文件名称', trigger: 'blur' }],
|
||||||
|
url: [{ required: true, message: '请输入远程地址', trigger: 'blur' }]
|
||||||
|
},
|
||||||
|
|
||||||
|
temp: {},
|
||||||
|
|
||||||
|
fileList: [],
|
||||||
|
percentage: 0,
|
||||||
|
percentageInfo: {},
|
||||||
|
uploading: false,
|
||||||
|
uploadVisible: false,
|
||||||
|
editVisible: false,
|
||||||
|
|
||||||
|
tempVue: null,
|
||||||
|
triggerVisible: false,
|
||||||
|
releaseFileVisible: false,
|
||||||
|
tableSelections: [],
|
||||||
|
confirmLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
pagination() {
|
||||||
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
|
},
|
||||||
|
rowSelection() {
|
||||||
|
return {
|
||||||
|
onChange: (selectedRowKeys) => {
|
||||||
|
this.tableSelections = selectedRowKeys
|
||||||
|
},
|
||||||
|
selectedRowKeys: this.tableSelections,
|
||||||
|
type: this.choose || 'checkbox'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
randomStr,
|
||||||
|
CHANGE_PAGE,
|
||||||
|
renderSize,
|
||||||
|
formatDuration,
|
||||||
|
parseTime,
|
||||||
|
// 加载数据
|
||||||
|
loadData(pointerEvent) {
|
||||||
|
this.loading = true
|
||||||
|
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page
|
||||||
|
staticFileStorageList(this.listQuery).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.list = res.data.result
|
||||||
|
this.listQuery.total = res.data.total
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
handleEdit(item) {
|
||||||
|
this.temp = {
|
||||||
|
...item,
|
||||||
|
global: item.workspaceId === 'GLOBAL',
|
||||||
|
workspaceId: ''
|
||||||
|
}
|
||||||
|
this.editVisible = true
|
||||||
|
this.$refs['editForm']?.resetFields()
|
||||||
|
},
|
||||||
|
// 编辑确认
|
||||||
|
handleEditOk() {
|
||||||
|
this.$refs['editForm'].validate().then(() => {
|
||||||
|
this.confirmLoading = true
|
||||||
|
fileEdit(this.temp)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 成功
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.editVisible = false
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 删除文件
|
||||||
|
handleDelete(record) {
|
||||||
|
this.$confirm({
|
||||||
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
|
content: '真的要删除当前文件么?' + record.name,
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
// 删除
|
||||||
|
delFile({
|
||||||
|
id: record.id,
|
||||||
|
thorough: false
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 批量删除
|
||||||
|
handleBatchDelete() {
|
||||||
|
if (!this.tableSelections || this.tableSelections.length <= 0) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '没有选择任何数据'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm({
|
||||||
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
|
content: '真的要删除这些文件么?',
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
// 删除
|
||||||
|
delFile({
|
||||||
|
ids: this.tableSelections.join(','),
|
||||||
|
thorough: false
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.tableSelections = []
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下载地址
|
||||||
|
handleDownloadUrl(record) {
|
||||||
|
this.temp = Object.assign({}, record)
|
||||||
|
this.tempVue = Vue
|
||||||
|
triggerUrl({
|
||||||
|
id: record.id
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.fillDownloadUrlResult(res)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.triggerVisible = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 重置触发器
|
||||||
|
resetTrigger() {
|
||||||
|
triggerUrl({
|
||||||
|
id: this.temp.id,
|
||||||
|
rest: 'rest'
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.fillDownloadUrlResult(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fillDownloadUrlResult(res) {
|
||||||
|
this.temp = {
|
||||||
|
...this.temp,
|
||||||
|
triggerDownloadUrl: `${location.protocol}//${location.host}${res.data.triggerDownloadUrl}`,
|
||||||
|
triggerAliasDownloadUrl: res.data?.triggerAliasDownloadUrl
|
||||||
|
? `${location.protocol}//${location.host}${res.data.triggerAliasDownloadUrl}?sort=createTimeMillis:desc`
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 发布文件
|
||||||
|
handleReleaseFile(record) {
|
||||||
|
this.releaseFileVisible = true
|
||||||
|
this.temp = { fileId: record.id }
|
||||||
|
},
|
||||||
|
|
||||||
|
handleCommitTask(data) {
|
||||||
|
this.confirmLoading = true
|
||||||
|
addReleaseTask({ ...data, fileId: this.temp.fileId, fileType: 2 })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
// 成功
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
|
this.releaseFileVisible = false
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
releaseFileOk() {
|
||||||
|
this.$refs.releaseFile?.tryCommit()
|
||||||
|
},
|
||||||
|
// 选择确认
|
||||||
|
handerConfirm() {
|
||||||
|
if (!this.tableSelections.length) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '请选择要使用的文件'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selectData = this.list.filter((item) => {
|
||||||
|
return this.tableSelections.indexOf(item.id) > -1
|
||||||
|
})
|
||||||
|
if (!selectData.length) {
|
||||||
|
this.$notification.warning({
|
||||||
|
message: '请选择要使用的文件'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$emit('confirm', selectData)
|
||||||
|
},
|
||||||
|
// 扫描
|
||||||
|
reScanner() {
|
||||||
|
staticScanner({}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['cancel', 'confirm']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/deep/ .ant-progress-text {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
</style>
|
@ -18,7 +18,7 @@
|
|||||||
<a-input-search
|
<a-input-search
|
||||||
placeholder="请输入工作空间备注,留空使用默认的名称"
|
placeholder="请输入工作空间备注,留空使用默认的名称"
|
||||||
enter-button="确定"
|
enter-button="确定"
|
||||||
v-model="element.name"
|
v-model:value="element.name"
|
||||||
@search="editOk(element)"
|
@search="editOk(element)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="list"
|
:data-source="list"
|
||||||
@ -8,25 +8,27 @@
|
|||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
bordered
|
bordered
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="监控名称"
|
placeholder="监控名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-select v-model="listQuery.status" allowClear placeholder="开启状态" class="search-input-item">
|
<a-select v-model:value="listQuery.status" allowClear placeholder="开启状态" class="search-input-item">
|
||||||
<a-select-option :value="1">开启</a-select-option>
|
<a-select-option :value="1">开启</a-select-option>
|
||||||
<a-select-option :value="0">关闭</a-select-option>
|
<a-select-option :value="0">关闭</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.autoRestart" allowClear placeholder="自动重启" class="search-input-item">
|
<a-select v-model:value="listQuery.autoRestart" allowClear placeholder="自动重启" class="search-input-item">
|
||||||
<a-select-option :value="1">是</a-select-option>
|
<a-select-option :value="1">是</a-select-option>
|
||||||
<a-select-option :value="0">否</a-select-option>
|
<a-select-option :value="0">否</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.alarm" allowClear placeholder="报警状态" class="search-input-item">
|
<a-select v-model:value="listQuery.alarm" allowClear placeholder="报警状态" class="search-input-item">
|
||||||
<a-select-option :value="1">报警中</a-select-option>
|
<a-select-option :value="1">报警中</a-select-option>
|
||||||
<a-select-option :value="0">未报警</a-select-option>
|
<a-select-option :value="0">未报警</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@ -36,50 +38,35 @@
|
|||||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #name slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.dataIndex === 'name'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-switch
|
<span>{{ text }}</span>
|
||||||
#status
|
</a-tooltip>
|
||||||
size="small"
|
</template>
|
||||||
slot-scope="text"
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
:checked="text"
|
<a-switch size="small" :checked="text" disabled checked-children="开启" un-checked-children="关闭" />
|
||||||
disabled
|
</template>
|
||||||
checked-children="开启"
|
<template v-else-if="column.dataIndex === 'autoRestart'">
|
||||||
un-checked-children="关闭"
|
<a-switch size="small" :checked="text" disabled checked-children="是" un-checked-children="否" />
|
||||||
/>
|
</template>
|
||||||
<a-switch
|
<template v-else-if="column.dataIndex === 'alarm'">
|
||||||
#autoRestart
|
<a-switch size="small" :checked="text" disabled checked-children="报警中" un-checked-children="未报警" />
|
||||||
size="small"
|
</template>
|
||||||
slot-scope="text"
|
|
||||||
:checked="text"
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
disabled
|
<a-space>
|
||||||
checked-children="是"
|
<a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button>
|
||||||
un-checked-children="否"
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
/>
|
</a-space>
|
||||||
<a-switch
|
</template>
|
||||||
#alarm
|
|
||||||
size="small"
|
|
||||||
slot-scope="text"
|
|
||||||
:checked="text"
|
|
||||||
disabled
|
|
||||||
checked-children="报警中"
|
|
||||||
un-checked-children="未报警"
|
|
||||||
/>
|
|
||||||
<a-tooltip #parent slot-scope="text" placement="topLeft" :title="text">
|
|
||||||
<span>{{ text }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
<template #operation slot-scope="text, record">
|
|
||||||
<a-space>
|
|
||||||
<a-button type="primary" size="small" @click="handleEdit(record)">编辑</a-button>
|
|
||||||
<a-button type="danger" size="small" @click="handleDelete(record)">删除</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editMonitorVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editMonitorVisible"
|
||||||
width="60%"
|
width="60%"
|
||||||
title="编辑监控"
|
title="编辑监控"
|
||||||
@ok="handleEditMonitorOk"
|
@ok="handleEditMonitorOk"
|
||||||
@ -87,54 +74,47 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="editMonitorForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form ref="editMonitorForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="监控名称" name="name">
|
<a-form-item label="监控名称" name="name">
|
||||||
<a-input v-model="temp.name" :maxLength="50" placeholder="监控名称" />
|
<a-input v-model:value="temp.name" :maxLength="50" placeholder="监控名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="开启状态" name="status">
|
<a-form-item label="开启状态" name="status">
|
||||||
<a-space size="large">
|
<a-space size="large">
|
||||||
<a-switch v-model="temp.status" checked-children="开" un-checked-children="关" />
|
<a-switch v-model:checked="temp.status" checked-children="开" un-checked-children="关" />
|
||||||
<div>
|
<div>
|
||||||
自动重启:
|
自动重启:
|
||||||
<a-switch v-model="temp.autoRestart" checked-children="开" un-checked-children="关" />
|
<a-form-item-rest>
|
||||||
|
<a-switch v-model:checked="temp.autoRestart" checked-children="开" un-checked-children="关" />
|
||||||
|
</a-form-item-rest>
|
||||||
</div>
|
</div>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<!-- <a-form-item label="自动重启" name="autoRestart">
|
<!-- <a-form-item label="自动重启" name="autoRestart">
|
||||||
|
|
||||||
</a-form-item> -->
|
</a-form-item> -->
|
||||||
|
|
||||||
<!-- <a-form-item label="监控周期" name="cycle">
|
<!-- <a-form-item label="监控周期" name="cycle">
|
||||||
<a-radio-group v-model="temp.cycle" name="cycle">
|
<a-radio-group v-model="temp.cycle" name="cycle">
|
||||||
<a-radio :value="1">1 分钟</a-radio>
|
<a-radio :value="1">1 分钟</a-radio>
|
||||||
<a-radio :value="5">5 分钟</a-radio>
|
<a-radio :value="5">5 分钟</a-radio>
|
||||||
<a-radio :value="10">10 分钟</a-radio>
|
<a-radio :value="10">10 分钟</a-radio>
|
||||||
<a-radio :value="30">30 分钟</a-radio>
|
<a-radio :value="30">30 分钟</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item> -->
|
</a-form-item> -->
|
||||||
|
|
||||||
<a-form-item label="监控周期" name="execCron">
|
<a-form-item label="监控周期" name="execCron">
|
||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
v-model="temp.execCron"
|
v-model:value="temp.execCron"
|
||||||
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
||||||
option-label-prop="value"
|
:options="CRON_DATA_SOURCE"
|
||||||
>
|
>
|
||||||
<template #dataSource>
|
<template #option="item"> {{ item.title }} {{ item.value }} </template>
|
||||||
<a-select-opt-group v-for="group in cronDataSource" :key="group.title">
|
|
||||||
<span #label>
|
|
||||||
{{ group.title }}
|
|
||||||
</span>
|
|
||||||
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.value">
|
|
||||||
{{ opt.title }} {{ opt.value }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select-opt-group>
|
|
||||||
</template>
|
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="监控项目" name="projects">
|
<a-form-item label="监控项目" name="projects">
|
||||||
<a-select
|
<a-select
|
||||||
option-label-prop="label"
|
option-label-prop="label"
|
||||||
v-model="projectKeys"
|
v-model:value="projectKeys"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
placeholder="选择要监控的项目,file 类型项目不可以监控"
|
placeholder="选择要监控的项目,file 类型项目不可以监控"
|
||||||
show-search
|
show-search
|
||||||
@ -151,19 +131,20 @@
|
|||||||
:disabled="!noFileModes.includes(project.runMode)"
|
:disabled="!noFileModes.includes(project.runMode)"
|
||||||
:key="project.id"
|
:key="project.id"
|
||||||
>
|
>
|
||||||
【{{ project.nodeName }}】{{ project.name }} - {{ project.runMode }}
|
【{{ project.nodeName }}】{{ project.name }} -
|
||||||
|
{{ project.runMode }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select-opt-group>
|
</a-select-opt-group>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item name="notifyUser" class="jpom-notify">
|
<a-form-item name="notifyUser" class="jpom-notify">
|
||||||
<template #label>
|
<template v-slot:label>
|
||||||
联系人
|
<a-tooltip>
|
||||||
<a-tooltip v-show="!temp.id">
|
联系人
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
如果这里的报警联系人无法选择,说明这里面的管理员没有设置邮箱,在右上角下拉菜单里面的用户资料里可以设置。
|
如果这里的报警联系人无法选择,说明这里面的管理员没有设置邮箱,在右上角下拉菜单里面的用户资料里可以设置。
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined v-show="!temp.id" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-transfer
|
<a-transfer
|
||||||
@ -179,25 +160,21 @@
|
|||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<template #render="item">
|
<template #render="item">
|
||||||
<span>
|
<template v-if="item.disabled">
|
||||||
<span v-if="item.disabled">
|
<a-tooltip title="如果不可以选择则表示对应的用户没有配置邮箱">
|
||||||
<a-tooltip title="如果不可以选择则表示对应的用户没有配置邮箱">
|
<WarningTwoTone />
|
||||||
<a-icon type="warning" theme="twoTone" />
|
{{ item.name }}
|
||||||
{{ item.name }}
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</template>
|
||||||
</span>
|
<template v-else> {{ item.name }}</template>
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
-
|
|
||||||
{{ item.name }}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</a-transfer>
|
</a-transfer>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item name="webhook">
|
<a-form-item name="webhook">
|
||||||
<template #label>
|
<template v-slot:label>
|
||||||
WebHooks
|
<a-tooltip>
|
||||||
<a-tooltip v-show="!temp.id">
|
WebHooks
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<ul>
|
<ul>
|
||||||
<li>发生报警时候请求</li>
|
<li>发生报警时候请求</li>
|
||||||
<li>
|
<li>
|
||||||
@ -206,15 +183,16 @@
|
|||||||
<li>runStatus 值为 true 表示项目当前为运行中(异常恢复),false 表示项目当前未运行(发生异常)</li>
|
<li>runStatus 值为 true 表示项目当前为运行中(异常恢复),false 表示项目当前未运行(发生异常)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined v-show="!temp.id" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-input v-model="temp.webhook" placeholder="接收报警消息,非必填,GET请求" />
|
<a-input v-model:value="temp.webhook" placeholder="接收报警消息,非必填,GET请求" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { deleteMonitor, editMonitor, getMonitorList } from '@/api/monitor'
|
import { deleteMonitor, editMonitor, getMonitorList } from '@/api/monitor'
|
||||||
import { noFileModes } from '@/api/node-project'
|
import { noFileModes } from '@/api/node-project'
|
||||||
@ -234,7 +212,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
cronDataSource: CRON_DATA_SOURCE,
|
CRON_DATA_SOURCE,
|
||||||
list: [],
|
list: [],
|
||||||
userList: [],
|
userList: [],
|
||||||
nodeProjectList: [],
|
nodeProjectList: [],
|
||||||
@ -248,30 +226,50 @@ export default {
|
|||||||
temp: {},
|
temp: {},
|
||||||
editMonitorVisible: false,
|
editMonitorVisible: false,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '名称', dataIndex: 'name', ellipsis: true, scopedSlots: { customRender: 'name' } },
|
{
|
||||||
{ title: '监控周期', dataIndex: 'execCron', ellipsis: true, scopedSlots: { customRender: 'execCron' } },
|
title: '名称',
|
||||||
{ title: '开启状态', dataIndex: 'status', ellipsis: true, scopedSlots: { customRender: 'status' }, width: 120 },
|
dataIndex: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '监控周期',
|
||||||
|
dataIndex: 'execCron',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开启状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '自动重启',
|
title: '自动重启',
|
||||||
dataIndex: 'autoRestart',
|
dataIndex: 'autoRestart',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'autoRestart' },
|
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '报警状态',
|
||||||
|
dataIndex: 'alarm',
|
||||||
|
ellipsis: true,
|
||||||
|
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{ title: '报警状态', dataIndex: 'alarm', ellipsis: true, scopedSlots: { customRender: 'alarm' }, width: 120 },
|
|
||||||
{
|
{
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
if (!text || text === '0') {
|
if (!text || text === '0') {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
@ -283,13 +281,20 @@ export default {
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'operation' },
|
fixed: 'right',
|
||||||
width: 120
|
width: '120px'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
name: [{ required: true, message: 'Please input monitor name', trigger: 'blur' }]
|
name: [
|
||||||
}
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入监控名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -302,24 +307,6 @@ export default {
|
|||||||
this.loadData()
|
this.loadData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 页面引导
|
|
||||||
introGuide() {
|
|
||||||
this.$store.dispatch('tryOpenGuide', {
|
|
||||||
key: 'monitor',
|
|
||||||
options: {
|
|
||||||
hidePrev: true,
|
|
||||||
steps: [
|
|
||||||
{
|
|
||||||
title: '导航助手',
|
|
||||||
element: document.querySelector('.jpom-notify'),
|
|
||||||
intro:
|
|
||||||
'如果这里的报警联系人无法选择,说明这里面的管理员没有设置邮箱,在右上角下拉菜单里面的用户资料里可以设置。'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
loadData(pointerEvent) {
|
loadData(pointerEvent) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
@ -336,7 +323,7 @@ export default {
|
|||||||
loadUserList(fn) {
|
loadUserList(fn) {
|
||||||
getUserListAll().then((res) => {
|
getUserListAll().then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.userList = res.data.map((element) => {
|
this.userList = res.data.map((element) => {
|
||||||
let canUse = element.email || element.dingDing || element.workWx
|
let canUse = element.email || element.dingDing || element.workWx
|
||||||
return { key: element.id, name: element.name, disabled: !canUse }
|
return { key: element.id, name: element.name, disabled: !canUse }
|
||||||
@ -387,11 +374,6 @@ export default {
|
|||||||
this.editMonitorVisible = true
|
this.editMonitorVisible = true
|
||||||
this.loadUserList()
|
this.loadUserList()
|
||||||
this.loadNodeProjectList()
|
this.loadNodeProjectList()
|
||||||
nextTick(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.introGuide()
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// 修改
|
// 修改
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
@ -425,10 +407,7 @@ export default {
|
|||||||
},
|
},
|
||||||
handleEditMonitorOk() {
|
handleEditMonitorOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editMonitorForm'].validate((valid) => {
|
this.$refs['editMonitorForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
let projects = this.nodeProjectList.filter((item) => {
|
let projects = this.nodeProjectList.filter((item) => {
|
||||||
return this.projectKeys.includes(item.id)
|
return this.projectKeys.includes(item.id)
|
||||||
})
|
})
|
||||||
@ -448,7 +427,7 @@ export default {
|
|||||||
.map((item) => item.key)
|
.map((item) => item.key)
|
||||||
|
|
||||||
if (targetKeysTemp.length <= 0 && !this.temp.webhook) {
|
if (targetKeysTemp.length <= 0 && !this.temp.webhook) {
|
||||||
$notification.warn({
|
this.$notification.warn({
|
||||||
message: '请选择一位报警联系人或者填写webhook'
|
message: '请选择一位报警联系人或者填写webhook'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@ -461,23 +440,29 @@ export default {
|
|||||||
projects: JSON.stringify(projects),
|
projects: JSON.stringify(projects),
|
||||||
notifyUser: JSON.stringify(targetKeysTemp)
|
notifyUser: JSON.stringify(targetKeysTemp)
|
||||||
}
|
}
|
||||||
editMonitor(params).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
editMonitor(params)
|
||||||
// 成功
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
this.$refs['editMonitorForm'].resetFields()
|
message: res.msg
|
||||||
this.editMonitorVisible = false
|
})
|
||||||
this.loadData()
|
this.$refs['editMonitorForm'].resetFields()
|
||||||
}
|
this.editMonitorVisible = false
|
||||||
})
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除监控么?',
|
content: '真的要删除监控么?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -485,7 +470,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteMonitor(record.id).then((res) => {
|
deleteMonitor(record.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -502,4 +487,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- <div ref="filter" class="filter"></div> -->
|
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="list"
|
:data-source="list"
|
||||||
@ -8,60 +7,72 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
bordered
|
bordered
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
@change="change"
|
@change="change"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-select v-model="listQuery.nodeId" allowClear placeholder="请选择节点" class="search-input-item">
|
<a-select v-model:value="listQuery.nodeId" allowClear placeholder="请选择节点" class="search-input-item">
|
||||||
<a-select-option v-for="(nodeName, key) in nodeMap" :key="key">{{ nodeName }}</a-select-option>
|
<a-select-option v-for="(nodeName, key) in nodeMap" :key="key">{{ nodeName }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.status" allowClear placeholder="报警状态" class="search-input-item">
|
<a-select v-model:value="listQuery.status" allowClear placeholder="报警状态" class="search-input-item">
|
||||||
<a-select-option :value="1">正常</a-select-option>
|
<a-select-option :value="1">正常</a-select-option>
|
||||||
<a-select-option :value="0">异常</a-select-option>
|
<a-select-option :value="0">异常</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select v-model="listQuery.notifyStatus" allowClear placeholder="通知状态" class="search-input-item">
|
<a-select v-model:value="listQuery.notifyStatus" allowClear placeholder="通知状态" class="search-input-item">
|
||||||
<a-select-option :value="1">成功</a-select-option>
|
<a-select-option :value="1">成功</a-select-option>
|
||||||
<a-select-option :value="0">失败</a-select-option>
|
<a-select-option :value="0">失败</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-range-picker
|
<a-range-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" @change="onchangeTime" />
|
||||||
class="search-input-item"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
@change="onchangeTime"
|
|
||||||
/>
|
|
||||||
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
||||||
<a-button :loading="loading" type="primary" @click="loadData">搜索</a-button>
|
<a-button :loading="loading" type="primary" @click="loadData">搜索</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #nodeId slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ nodeMap[text] }}</span>
|
<template v-if="column.dataIndex === 'nodeId'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-tooltip #tooltip slot-scope="text" placement="topLeft" :title="text">
|
<span>{{ nodeMap[text] }}</span>
|
||||||
<span>{{ text }}</span>
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</template>
|
||||||
<span #status slot-scope="text">{{ text ? '正常' : '异常' }}</span>
|
<template v-else-if="column.tooltip">
|
||||||
<template #notifyStyle slot-scope="text">
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
{{ notifyStyle[text] || '未知' }}
|
<span>{{ text }}</span>
|
||||||
</template>
|
</a-tooltip>
|
||||||
<span #notifyStatus slot-scope="text">{{ text ? '成功' : '失败' }}</span>
|
</template>
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
<a-button size="small" type="primary" @click="handleDetail(record)">详情</a-button>
|
<span>{{ text ? '正常' : '异常' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'notifyStyle'">
|
||||||
|
{{ notifyStyle[text] || '未知' }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'notifyStatus'">
|
||||||
|
<span>{{ text ? '成功' : '失败' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-button size="small" type="primary" @click="handleDetail(record)">详情</a-button>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 详情区 -->
|
<!-- 详情区 -->
|
||||||
<a-modal destroyOnClose v-model:visible="detailVisible" width="600px" title="详情信息" :footer="null">
|
<a-modal destroyOnClose v-model:open="detailVisible" width="600px" title="详情信息" :footer="null">
|
||||||
<a-list item-layout="horizontal" :data-source="detailData">
|
<a-list item-layout="horizontal" :data-source="detailData">
|
||||||
<a-list-item #renderItem slot-scope="item">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item-meta :description="item.description">
|
<a-list-item>
|
||||||
<h4 #title>{{ item.title }}</h4>
|
<a-list-item-meta :description="item.description">
|
||||||
</a-list-item-meta>
|
<template v-slot:title>
|
||||||
</a-list-item>
|
<h4>{{ item.title }}</h4>
|
||||||
|
</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
</a-list>
|
</a-list>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getMonitorLogList, notifyStyle } from '@/api/monitor'
|
import { getMonitorLogList, notifyStyle } from '@/api/monitor'
|
||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
@ -79,52 +90,59 @@ export default {
|
|||||||
notifyStyle,
|
notifyStyle,
|
||||||
detailData: [],
|
detailData: [],
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '报警标题', dataIndex: 'title', ellipsis: true, scopedSlots: { customRender: 'tooltip' } },
|
{
|
||||||
{ title: '节点名称', dataIndex: 'nodeId', width: 100, ellipsis: true, scopedSlots: { customRender: 'nodeId' } },
|
title: '报警标题',
|
||||||
|
dataIndex: 'title',
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '节点名称',
|
||||||
|
dataIndex: 'nodeId',
|
||||||
|
width: 100,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '项目 ID',
|
title: '项目 ID',
|
||||||
dataIndex: 'projectId',
|
dataIndex: 'projectId',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '报警状态',
|
title: '报警状态',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'status' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '报警方式',
|
title: '报警方式',
|
||||||
dataIndex: 'notifyStyle',
|
dataIndex: 'notifyStyle',
|
||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'notifyStyle' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '报警时间',
|
title: '报警时间',
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
width: 170
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '通知状态',
|
title: '通知状态',
|
||||||
dataIndex: 'notifyStatus',
|
dataIndex: 'notifyStatus',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'notifyStatus' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
fixed: 'right',
|
||||||
width: 80
|
width: '80px'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -186,12 +204,17 @@ export default {
|
|||||||
this.temp = Object.assign({}, record)
|
this.temp = Object.assign({}, record)
|
||||||
this.detailData.push({ title: '标题', description: this.temp.title })
|
this.detailData.push({ title: '标题', description: this.temp.title })
|
||||||
this.detailData.push({ title: '内容', description: this.temp.content })
|
this.detailData.push({ title: '内容', description: this.temp.content })
|
||||||
this.detailData.push({ title: '通知对象', description: this.temp.notifyObject })
|
this.detailData.push({
|
||||||
|
title: '通知对象',
|
||||||
|
description: this.temp.notifyObject
|
||||||
|
})
|
||||||
if (!this.temp.notifyStatus) {
|
if (!this.temp.notifyStatus) {
|
||||||
this.detailData.push({ title: '通知异常', description: this.temp.notifyError })
|
this.detailData.push({
|
||||||
|
title: '通知异常',
|
||||||
|
description: this.temp.notifyError
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
size="middle"
|
size="middle"
|
||||||
@ -8,17 +8,19 @@
|
|||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
bordered
|
bordered
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
placeholder="监控名称"
|
placeholder="监控名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-select v-model="listQuery.status" allowClear placeholder="开启状态" class="search-input-item">
|
<a-select v-model:value="listQuery.status" allowClear placeholder="开启状态" class="search-input-item">
|
||||||
<a-select-option :value="1">开启</a-select-option>
|
<a-select-option :value="1">开启</a-select-option>
|
||||||
<a-select-option :value="0">关闭</a-select-option>
|
<a-select-option :value="0">关闭</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@ -28,33 +30,31 @@
|
|||||||
<a-button type="primary" @click="handleAdd">新增</a-button>
|
<a-button type="primary" @click="handleAdd">新增</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #name slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.dataIndex === 'name'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-switch
|
<span>{{ text }}</span>
|
||||||
#status
|
</a-tooltip>
|
||||||
size="small"
|
</template>
|
||||||
slot-scope="text"
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
:checked="text"
|
<a-switch size="small" :checked="text" checked-children="开启" un-checked-children="关闭" />
|
||||||
checked-children="开启"
|
</template>
|
||||||
un-checked-children="关闭"
|
<!-- <a-switch slot="autoRestart" slot-scope="text" :checked="text" checked-children="是" un-checked-children="否" /> -->
|
||||||
/>
|
<!-- <a-switch slot="alarm" slot-scope="text" :checked="text" disabled checked-children="报警中" un-checked-children="未报警" /> -->
|
||||||
<!-- <a-switch #autoRestart slot-scope="text" :checked="text" checked-children="是" un-checked-children="否" /> -->
|
|
||||||
<!-- <a-switch #alarm slot-scope="text" :checked="text" disabled checked-children="报警中" un-checked-children="未报警" /> -->
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-tooltip #parent slot-scope="text" placement="topLeft" :title="text">
|
<a-space>
|
||||||
<span>{{ text }}</span>
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
</a-tooltip>
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
<template #operation slot-scope="text, record">
|
</a-space>
|
||||||
<a-space>
|
</template>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
|
||||||
<a-button size="small" type="danger" @click="handleDelete(record)">删除</a-button>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editOperateMonitorVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="editOperateMonitorVisible"
|
||||||
width="50vw"
|
width="50vw"
|
||||||
title="编辑监控"
|
title="编辑监控"
|
||||||
@ok="handleEditOperateMonitorOk"
|
@ok="handleEditOperateMonitorOk"
|
||||||
@ -62,10 +62,10 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="editMonitorForm" :rules="rules" :model="temp" :label-col="{ span: 5 }" :wrapper-col="{ span: 17 }">
|
<a-form ref="editMonitorForm" :rules="rules" :model="temp" :label-col="{ span: 5 }" :wrapper-col="{ span: 17 }">
|
||||||
<a-form-item label="监控名称" name="name">
|
<a-form-item label="监控名称" name="name">
|
||||||
<a-input v-model="temp.name" :maxLength="50" placeholder="监控名称" />
|
<a-input v-model:value="temp.name" :maxLength="50" placeholder="监控名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="开启状态" name="status">
|
<a-form-item label="开启状态" name="status">
|
||||||
<a-switch v-model="temp.start" checked-children="开" un-checked-children="关" />
|
<a-switch v-model:checked="temp.start" checked-children="开" un-checked-children="关" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="监控用户" name="monitorUser">
|
<a-form-item label="监控用户" name="monitorUser">
|
||||||
<a-transfer
|
<a-transfer
|
||||||
@ -101,13 +101,13 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item name="notifyUser" class="jpom-monitor-notify">
|
<a-form-item name="notifyUser" class="jpom-monitor-notify">
|
||||||
<template #label>
|
<template v-slot:label>
|
||||||
报警联系人
|
<a-tooltip>
|
||||||
<a-tooltip v-show="!temp.id">
|
报警联系人
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
如果这里的报警联系人无法选择,说明这里面的管理员没有设置邮箱,在右上角下拉菜单里面的用户资料里可以设置。
|
如果这里的报警联系人无法选择,说明这里面的管理员没有设置邮箱,在右上角下拉菜单里面的用户资料里可以设置。
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined v-show="!temp.id" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-transfer
|
<a-transfer
|
||||||
@ -124,6 +124,7 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
deleteMonitorOperate,
|
deleteMonitorOperate,
|
||||||
@ -152,14 +153,23 @@ export default {
|
|||||||
methodFeatureKeys: [],
|
methodFeatureKeys: [],
|
||||||
editOperateMonitorVisible: false,
|
editOperateMonitorVisible: false,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '名称', dataIndex: 'name', scopedSlots: { customRender: 'name' } },
|
{
|
||||||
{ title: '开启状态', dataIndex: 'status', scopedSlots: { customRender: 'status' } },
|
title: '名称',
|
||||||
{ title: '修改人', dataIndex: 'modifyUser', scopedSlots: { customRender: 'modifyUser' } },
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开启状态',
|
||||||
|
dataIndex: 'status'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '修改人',
|
||||||
|
dataIndex: 'modifyUser'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
if (!text || text === '0') {
|
if (!text || text === '0') {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
@ -171,13 +181,20 @@ export default {
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
fixed: 'right',
|
||||||
width: 120
|
width: '120px'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
name: [{ required: true, message: 'Please input monitor name', trigger: 'blur' }]
|
name: [
|
||||||
}
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入监控名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -191,23 +208,6 @@ export default {
|
|||||||
this.loadOptTypeData()
|
this.loadOptTypeData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 页面引导
|
|
||||||
introGuide() {
|
|
||||||
this.$store.dispatch('tryOpenGuide', {
|
|
||||||
key: 'operate-log',
|
|
||||||
options: {
|
|
||||||
hidePrev: true,
|
|
||||||
steps: [
|
|
||||||
{
|
|
||||||
title: '导航助手',
|
|
||||||
element: document.querySelector('.jpom-monitor-notify'),
|
|
||||||
intro: '这里面的报警联系人如果无法选择,您需要设置管理员的邮箱地址。'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
loadData(pointerEvent) {
|
loadData(pointerEvent) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
@ -263,11 +263,6 @@ export default {
|
|||||||
this.monitorUserKeys = []
|
this.monitorUserKeys = []
|
||||||
this.loadUserList()
|
this.loadUserList()
|
||||||
this.editOperateMonitorVisible = true
|
this.editOperateMonitorVisible = true
|
||||||
nextTick(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.introGuide()
|
|
||||||
}, 500)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// 修改
|
// 修改
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
@ -306,30 +301,27 @@ export default {
|
|||||||
// 提交
|
// 提交
|
||||||
handleEditOperateMonitorOk() {
|
handleEditOperateMonitorOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editMonitorForm'].validate((valid) => {
|
this.$refs['editMonitorForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.monitorUserKeys.length === 0) {
|
if (this.monitorUserKeys.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择监控用户'
|
message: '请选择监控用户'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.methodFeatureKeys.length === 0) {
|
if (this.methodFeatureKeys.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择监控操作'
|
message: '请选择监控操作'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.classFeatureKeys.length === 0) {
|
if (this.classFeatureKeys.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择监控的功能'
|
message: '请选择监控的功能'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.notifyUserKeys.length === 0) {
|
if (this.notifyUserKeys.length === 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择报警联系人'
|
message: '请选择报警联系人'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@ -340,23 +332,29 @@ export default {
|
|||||||
this.temp.monitorFeature = JSON.stringify(this.classFeatureKeys)
|
this.temp.monitorFeature = JSON.stringify(this.classFeatureKeys)
|
||||||
this.temp.notifyUser = JSON.stringify(this.notifyUserKeys)
|
this.temp.notifyUser = JSON.stringify(this.notifyUserKeys)
|
||||||
this.temp.start ? (this.temp.status = 'on') : (this.temp.status = 'no')
|
this.temp.start ? (this.temp.status = 'on') : (this.temp.status = 'no')
|
||||||
editMonitorOperate(this.temp).then((res) => {
|
this.confirmLoading = false
|
||||||
if (res.code === 200) {
|
editMonitorOperate(this.temp)
|
||||||
// 成功
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
this.$refs['editMonitorForm'].resetFields()
|
message: res.msg
|
||||||
this.editOperateMonitorVisible = false
|
})
|
||||||
this.loadData()
|
this.$refs['editMonitorForm'].resetFields()
|
||||||
}
|
this.editOperateMonitorVisible = false
|
||||||
})
|
this.loadData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除操作监控么?',
|
content: '真的要删除操作监控么?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -364,7 +362,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteMonitorOperate(record.id).then((res) => {
|
deleteMonitorOperate(record.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -381,4 +379,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<workspaceEnv ref="workspaceEnv" :workspaceId="this.getWorkspaceId()" :global="true" />
|
<workspaceEnv ref="workspaceEnv" :workspaceId="this.getWorkspaceId()" :global="true" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import workspaceEnv from '@/pages/system/workspace-env.vue'
|
import workspaceEnv from '@/pages/system/workspace-env.vue'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
|
import { useAppStore } from '@/stores/app'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -15,7 +17,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: { ...mapGetters(['getWorkspaceId']) },
|
computed: { ...mapState(useAppStore, ['getWorkspaceId']) },
|
||||||
created() {},
|
created() {},
|
||||||
methods: {}
|
methods: {}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="list"
|
:data-source="list"
|
||||||
@ -10,6 +10,9 @@
|
|||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -66,70 +69,72 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
<template #bodyCell="{ column, text, record }">
|
||||||
|
<template v-if="column.dataIndex === 'nodeId'">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ nodeMap[text] }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.tooltip">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'workspaceId'">
|
||||||
|
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
||||||
|
<a-tag v-else>工作空间</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
|
<a-space>
|
||||||
|
<template v-if="mode === 'manage'">
|
||||||
|
<a-button size="small" type="primary" @click="handleExec(record)">执行</a-button>
|
||||||
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
|
<a-button size="small" type="primary" @click="handleLog(record)">日志</a-button>
|
||||||
|
<a-dropdown>
|
||||||
|
<a @click="(e) => e.preventDefault()">
|
||||||
|
更多
|
||||||
|
<DownOutlined />
|
||||||
|
</a>
|
||||||
|
<template v-slot:overlay>
|
||||||
|
<a-menu>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-button size="small" type="primary" @click="handleTrigger(record)">触发器</a-button>
|
||||||
|
</a-menu-item>
|
||||||
|
|
||||||
<template v-slot:nodeId="text">
|
<a-menu-item>
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
<span>{{ nodeMap[text] }}</span>
|
</a-menu-item>
|
||||||
</a-tooltip>
|
<a-menu-item>
|
||||||
</template>
|
<a-button
|
||||||
<template v-slot:tooltip="text">
|
size="small"
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
type="primary"
|
||||||
<span>{{ text }}</span>
|
danger
|
||||||
</a-tooltip>
|
:disabled="!record.nodeIds"
|
||||||
</template>
|
@click="handleUnbind(record)"
|
||||||
<template v-slot:global="text">
|
>解绑</a-button
|
||||||
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
>
|
||||||
<a-tag v-else>工作空间</a-tag>
|
</a-menu-item>
|
||||||
</template>
|
</a-menu>
|
||||||
<template v-slot:operation="text, record">
|
</template>
|
||||||
<a-space>
|
</a-dropdown>
|
||||||
<template v-if="mode === 'manage'">
|
</template>
|
||||||
<a-button size="small" type="primary" @click="handleExec(record)">执行</a-button>
|
<template v-else>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
<a-button size="small" type="primary" @click="handleLog(record)">日志</a-button>
|
</template>
|
||||||
<a-dropdown>
|
</a-space>
|
||||||
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
|
</template>
|
||||||
更多
|
|
||||||
<a-icon type="down" />
|
|
||||||
</a>
|
|
||||||
<template v-slot:overlay>
|
|
||||||
<a-menu>
|
|
||||||
<a-menu-item>
|
|
||||||
<a-button size="small" type="primary" @click="handleTrigger(record)">触发器</a-button>
|
|
||||||
</a-menu-item>
|
|
||||||
|
|
||||||
<a-menu-item>
|
|
||||||
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item>
|
|
||||||
<a-button
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
danger
|
|
||||||
:disabled="!record.nodeIds"
|
|
||||||
@click="handleUnbind(record)"
|
|
||||||
>解绑</a-button
|
|
||||||
>
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
|
||||||
</template>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
:zIndex="1009"
|
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:value="editScriptVisible"
|
:zIndex="1009"
|
||||||
|
v-model:open="editScriptVisible"
|
||||||
title="编辑 Script"
|
title="编辑 Script"
|
||||||
@ok="handleEditScriptOk"
|
@ok="handleEditScriptOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
width="80vw"
|
width="80vw"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form ref="editScriptForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 19 }">
|
<a-form ref="editScriptForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 19 }">
|
||||||
<a-form-item v-if="temp.id" label="ScriptId" name="id">
|
<a-form-item v-if="temp.id" label="ScriptId" name="id">
|
||||||
@ -139,41 +144,41 @@
|
|||||||
<a-input :maxLength="50" v-model:value="temp.name" placeholder="名称" />
|
<a-input :maxLength="50" v-model:value="temp.name" placeholder="名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Script 内容" name="context">
|
<a-form-item label="Script 内容" name="context">
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<a-form-item-rest>
|
||||||
<code-editor
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
v-model:value="temp.context"
|
<code-editor v-model:content="temp.context" :options="{ mode: 'shell', tabSize: 2, theme: 'abcdef' }">
|
||||||
:options="{ mode: 'shell', tabSize: 2, theme: 'abcdef' }"
|
</code-editor>
|
||||||
></code-editor>
|
</div>
|
||||||
</div>
|
</a-form-item-rest>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- <a-form-item label="默认参数" name="defArgs">
|
<!-- <a-form-item label="默认参数" name="defArgs">
|
||||||
<a-input v-model="temp.defArgs" placeholder="默认参数" />
|
<a-input v-model="temp.defArgs" placeholder="默认参数" />
|
||||||
</a-form-item> -->
|
</a-form-item> -->
|
||||||
<a-form-item label="默认参数">
|
<a-form-item label="默认参数">
|
||||||
<div v-for="(item, index) in commandParams" :key="item.key">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-row type="flex" justify="center" align="middle">
|
<a-row v-for="(item, index) in commandParams" :key="item.key">
|
||||||
<a-col :span="22">
|
<a-col :span="22">
|
||||||
<a-input
|
<a-space direction="vertical" style="width: 100%">
|
||||||
:addon-before="`参数${index + 1}描述`"
|
<a-input
|
||||||
v-model:value="item.desc"
|
:addon-before="`参数${index + 1}描述`"
|
||||||
placeholder="参数描述,参数描述没有实际作用,仅是用于提示参数的含义"
|
v-model:value="item.desc"
|
||||||
/>
|
placeholder="参数描述,参数描述没有实际作用,仅是用于提示参数的含义" />
|
||||||
<a-input
|
<a-input
|
||||||
:addon-before="`参数${index + 1}值`"
|
:addon-before="`参数${index + 1}值`"
|
||||||
v-model:value="item.value"
|
v-model:value="item.value"
|
||||||
placeholder="参数值,添加默认参数后在手动执行脚本时需要填写参数值"
|
placeholder="参数值,添加默认参数后在手动执行脚本时需要填写参数值"
|
||||||
/>
|
/></a-space>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="2">
|
<a-col :span="2">
|
||||||
<a-row type="flex" justify="center" align="middle">
|
<a-row type="flex" justify="center" align="middle">
|
||||||
<a-col>
|
<a-col>
|
||||||
<a-icon @click="() => commandParams.splice(index, 1)" type="minus-circle" style="color: #ff0000" />
|
<MinusCircleOutlined @click="() => commandParams.splice(index, 1)" style="color: #ff0000" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-divider style="margin: 5px 0" />
|
<a-divider style="margin: 5px 0" />
|
||||||
</div>
|
</a-space>
|
||||||
|
|
||||||
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -181,27 +186,15 @@
|
|||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
v-model:value="temp.autoExecCron"
|
v-model:value="temp.autoExecCron"
|
||||||
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
||||||
option-label-prop="value"
|
:options="CRON_DATA_SOURCE"
|
||||||
>
|
>
|
||||||
<template v-slot:dataSource>
|
<template #option="item"> {{ item.title }} {{ item.value }} </template>
|
||||||
<a-select-opt-group v-for="group in cronDataSource" :key="group.title">
|
|
||||||
<template v-slot:label>
|
|
||||||
<span>
|
|
||||||
{{ group.title }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.value">
|
|
||||||
{{ opt.title }} {{ opt.value }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select-opt-group>
|
|
||||||
</template>
|
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="描述" name="description">
|
<a-form-item label="描述" name="description">
|
||||||
<a-input
|
<a-textarea
|
||||||
v-model:value="temp.description"
|
v-model:value="temp.description"
|
||||||
:maxLength="200"
|
:maxLength="200"
|
||||||
type="textarea"
|
|
||||||
:rows="3"
|
:rows="3"
|
||||||
style="resize: none"
|
style="resize: none"
|
||||||
placeholder="详细描述"
|
placeholder="详细描述"
|
||||||
@ -246,7 +239,7 @@
|
|||||||
:title="drawerTitle"
|
:title="drawerTitle"
|
||||||
placement="right"
|
placement="right"
|
||||||
width="85vw"
|
width="85vw"
|
||||||
:visible="drawerConsoleVisible"
|
:open="drawerConsoleVisible"
|
||||||
@close="onConsoleClose"
|
@close="onConsoleClose"
|
||||||
>
|
>
|
||||||
<script-console v-if="drawerConsoleVisible" :defArgs="temp.defArgs" :id="temp.id" />
|
<script-console v-if="drawerConsoleVisible" :defArgs="temp.defArgs" :id="temp.id" />
|
||||||
@ -254,12 +247,13 @@
|
|||||||
<!-- 同步到其他工作空间 -->
|
<!-- 同步到其他工作空间 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:value="syncToWorkspaceVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="syncToWorkspaceVisible"
|
||||||
title="同步到其他工作空间"
|
title="同步到其他工作空间"
|
||||||
@ok="handleSyncToWorkspace"
|
@ok="handleSyncToWorkspace"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning" show-icon>
|
||||||
<template v-slot:description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
<li>同步机制采用<b>脚本名称</b>确定是同一个脚本</li>
|
<li>同步机制采用<b>脚本名称</b>确定是同一个脚本</li>
|
||||||
@ -287,7 +281,7 @@
|
|||||||
<!-- 触发器 -->
|
<!-- 触发器 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:value="triggerVisible"
|
v-model:open="triggerVisible"
|
||||||
title="触发器"
|
title="触发器"
|
||||||
width="50%"
|
width="50%"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -295,13 +289,13 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="editTriggerForm" :rules="rules" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form ref="editTriggerForm" :rules="rules" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<template v-slot:tabBarExtraContent>
|
<template v-slot:rightExtra>
|
||||||
<a-tooltip title="重置触发器 token 信息,重置后之前的触发器 token 将失效">
|
<a-tooltip title="重置触发器 token 信息,重置后之前的触发器 token 将失效">
|
||||||
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-tab-pane key="1" tab="执行">
|
<a-tab-pane key="1" tab="执行">
|
||||||
<a-space style="display: block" direction="vertical" align="baseline">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning">
|
||||||
<template v-slot:description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
@ -313,52 +307,18 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a-alert
|
<a-alert type="info" :message="`单个触发器地址(点击可以复制)`">
|
||||||
v-clipboard:copy="temp.triggerUrl"
|
|
||||||
v-clipboard:success="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.success({
|
|
||||||
message: '复制成功'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({
|
|
||||||
message: '复制失败'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`单个触发器地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template v-slot:description>
|
<template v-slot:description>
|
||||||
<a-tag>GET</a-tag> <span>{{ temp.triggerUrl }} </span>
|
<a-typography-paragraph :copyable="{ text: temp.triggerUrl }">
|
||||||
<a-icon type="copy" />
|
<a-tag>GET</a-tag> <span>{{ temp.triggerUrl }} </span>
|
||||||
|
</a-typography-paragraph>
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a-alert
|
<a-alert type="info" :message="`批量触发器地址(点击可以复制)`">
|
||||||
v-clipboard:copy="temp.batchTriggerUrl"
|
|
||||||
v-clipboard:success="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.success({
|
|
||||||
message: '复制成功'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({
|
|
||||||
message: '复制失败'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`批量触发器地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template v-slot:description>
|
<template v-slot:description>
|
||||||
<a-tag>POST</a-tag> <span>{{ temp.batchTriggerUrl }} </span>
|
<a-typography-paragraph :copyable="{ text: temp.batchTriggerUrl }">
|
||||||
<a-icon type="copy" />
|
<a-tag>POST</a-tag> <span>{{ temp.batchTriggerUrl }} </span>
|
||||||
|
</a-typography-paragraph>
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</a-space>
|
</a-space>
|
||||||
@ -370,8 +330,8 @@
|
|||||||
<a-drawer
|
<a-drawer
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
title="脚本执行历史"
|
title="脚本执行历史"
|
||||||
width="50vw"
|
width="70vw"
|
||||||
:visible="drawerLogVisible"
|
:open="drawerLogVisible"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.drawerLogVisible = false
|
this.drawerLogVisible = false
|
||||||
@ -380,7 +340,7 @@
|
|||||||
>
|
>
|
||||||
<script-log v-if="drawerLogVisible" :scriptId="temp.id" />
|
<script-log v-if="drawerLogVisible" :scriptId="temp.id" />
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
<div style="padding-top: 50px" v-if="mode === 'choose'">
|
<!-- <div style="padding-top: 50px" v-if="mode === 'choose'">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -407,7 +367,7 @@
|
|||||||
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -425,10 +385,12 @@ import codeEditor from '@/components/codeEditor'
|
|||||||
import { getNodeListAll } from '@/api/node'
|
import { getNodeListAll } from '@/api/node'
|
||||||
import ScriptConsole from '@/pages/script/script-console'
|
import ScriptConsole from '@/pages/script/script-console'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, CRON_DATA_SOURCE, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, CRON_DATA_SOURCE, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import { getWorkSpaceListAll } from '@/api/workspace'
|
import { getWorkSpaceListAll } from '@/api/workspace'
|
||||||
import * as Vue from 'vue'
|
|
||||||
import ScriptLog from '@/pages/script/script-log'
|
import ScriptLog from '@/pages/script/script-log'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
|
import { useAppStore } from '@/stores/app'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ScriptConsole,
|
ScriptConsole,
|
||||||
@ -456,7 +418,7 @@ export default {
|
|||||||
// choose: this.choose,
|
// choose: this.choose,
|
||||||
loading: false,
|
loading: false,
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
cronDataSource: CRON_DATA_SOURCE,
|
CRON_DATA_SOURCE,
|
||||||
list: [],
|
list: [],
|
||||||
temp: {},
|
temp: {},
|
||||||
nodeList: [],
|
nodeList: [],
|
||||||
@ -469,8 +431,8 @@ export default {
|
|||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
width: 150,
|
width: 50,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '名称',
|
title: '名称',
|
||||||
@ -478,22 +440,22 @@ export default {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
width: 150,
|
width: 150,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '共享',
|
title: '共享',
|
||||||
dataIndex: 'workspaceId',
|
dataIndex: 'workspaceId',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'global' },
|
|
||||||
width: '90px'
|
width: '90px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '描述',
|
title: '描述',
|
||||||
dataIndex: 'description',
|
dataIndex: 'description',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 300,
|
width: 100,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '定时执行',
|
title: '定时执行',
|
||||||
@ -501,7 +463,7 @@ export default {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
width: '100px',
|
width: '100px',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改时间',
|
title: '修改时间',
|
||||||
@ -509,7 +471,7 @@ export default {
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
width: '170px',
|
width: '170px',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text)
|
customRender: ({ text }) => parseTime(text)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
@ -517,20 +479,20 @@ export default {
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
width: '170px',
|
width: '170px',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text)
|
customRender: ({ text }) => parseTime(text)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建人',
|
title: '创建人',
|
||||||
dataIndex: 'createUser',
|
dataIndex: 'createUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' },
|
tooltip: true,
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '修改人',
|
title: '修改人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' },
|
tooltip: true,
|
||||||
width: '120px'
|
width: '120px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -538,14 +500,14 @@ export default {
|
|||||||
dataIndex: 'lastRunUser',
|
dataIndex: 'lastRunUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: '120px',
|
width: '120px',
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
this.mode === 'manage'
|
this.mode === 'manage'
|
||||||
? {
|
? {
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: '240px'
|
width: '240px'
|
||||||
}
|
}
|
||||||
@ -553,7 +515,7 @@ export default {
|
|||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: '100px'
|
width: '100px'
|
||||||
}
|
}
|
||||||
@ -567,11 +529,12 @@ export default {
|
|||||||
workspaceList: [],
|
workspaceList: [],
|
||||||
triggerVisible: false,
|
triggerVisible: false,
|
||||||
commandParams: [],
|
commandParams: [],
|
||||||
drawerLogVisible: false
|
drawerLogVisible: false,
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getWorkspaceId']),
|
...mapState(useAppStore, ['getWorkspaceId']),
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
},
|
},
|
||||||
@ -662,10 +625,7 @@ export default {
|
|||||||
// 提交 Script 数据
|
// 提交 Script 数据
|
||||||
handleEditScriptOk() {
|
handleEditScriptOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editScriptForm'].validate((valid) => {
|
this.$refs['editScriptForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.commandParams && this.commandParams.length > 0) {
|
if (this.commandParams && this.commandParams.length > 0) {
|
||||||
for (let i = 0; i < this.commandParams.length; i++) {
|
for (let i = 0; i < this.commandParams.length; i++) {
|
||||||
if (!this.commandParams[i].desc) {
|
if (!this.commandParams[i].desc) {
|
||||||
@ -682,18 +642,23 @@ export default {
|
|||||||
// 提交数据
|
// 提交数据
|
||||||
this.temp.nodeIds = this.temp?.chooseNode?.join(',')
|
this.temp.nodeIds = this.temp?.chooseNode?.join(',')
|
||||||
delete this.temp.nodeList
|
delete this.temp.nodeList
|
||||||
editScript(this.temp).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
editScript(this.temp)
|
||||||
// 成功
|
.then((res) => {
|
||||||
this.$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
// 成功
|
||||||
})
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
|
||||||
this.editScriptVisible = false
|
this.editScriptVisible = false
|
||||||
this.loadData()
|
this.loadData()
|
||||||
this.$refs['editScriptForm'].resetFields()
|
this.$refs['editScriptForm'].resetFields()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
@ -748,9 +713,9 @@ export default {
|
|||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '危险操作!!!',
|
title: '危险操作!!!',
|
||||||
zIndex: 1009,
|
zIndex: 1009,
|
||||||
content: h('div', null, [h('p', { domProps: { innerHTML: html } }, null)]),
|
content: h('div', null, [h('p', { innerHTML: html }, null)]),
|
||||||
okButtonProps: { props: { type: 'danger', size: 'small' } },
|
okButtonProps: { type: 'primary', danger: true, size: 'small' },
|
||||||
cancelButtonProps: { props: { type: 'primary' } },
|
cancelButtonProps: { type: 'primary' },
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
@ -793,24 +758,29 @@ export default {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 同步
|
// 同步
|
||||||
|
this.confirmLoading = true
|
||||||
syncToWorkspace({
|
syncToWorkspace({
|
||||||
ids: this.tableSelections.join(','),
|
ids: this.tableSelections.join(','),
|
||||||
toWorkspaceId: this.temp.workspaceId
|
toWorkspaceId: this.temp.workspaceId
|
||||||
}).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
this.tableSelections = []
|
|
||||||
this.syncToWorkspaceVisible = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.tableSelections = []
|
||||||
|
this.syncToWorkspaceVisible = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 触发器
|
// 触发器
|
||||||
handleTrigger(record) {
|
handleTrigger(record) {
|
||||||
this.temp = Object.assign({}, record)
|
this.temp = Object.assign({}, record)
|
||||||
this.tempVue = Vue
|
|
||||||
getTriggerUrl({
|
getTriggerUrl({
|
||||||
id: record.id
|
id: record.id
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
@ -853,12 +823,12 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.choose === 'checkbox') {
|
if (this.choose === 'checkbox') {
|
||||||
$emit(this, 'confirm', this.tableSelections.join(','))
|
this.$emit('confirm', this.tableSelections.join(','))
|
||||||
} else {
|
} else {
|
||||||
const selectData = this.list.filter((item) => {
|
const selectData = this.list.filter((item) => {
|
||||||
return item.id === this.tableSelections[0]
|
return item.id === this.tableSelections[0]
|
||||||
})[0]
|
})[0]
|
||||||
$emit(this, 'confirm', `${selectData.id}`)
|
this.$emit('confirm', `${selectData.id}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,21 +1,51 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="">
|
<div class="">
|
||||||
<!-- 数据表格 -->
|
<!-- 数据表格 -->
|
||||||
<a-table :data-source="list" size="middle" :columns="columns" @change="changePage" :pagination="pagination" bordered rowKey="id">
|
<a-table
|
||||||
|
:data-source="list"
|
||||||
|
size="middle"
|
||||||
|
:columns="columns"
|
||||||
|
@change="changePage"
|
||||||
|
:pagination="pagination"
|
||||||
|
bordered
|
||||||
|
rowKey="id"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
|
>
|
||||||
<template v-slot:title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input v-model:value="listQuery['%scriptName%']" placeholder="名称" @pressEnter="loadData" allowClear class="search-input-item" />
|
<a-input
|
||||||
<a-select show-search option-filter-prop="children" v-model:value="listQuery.triggerExecType" allowClear placeholder="触发类型" class="search-input-item">
|
v-model:value="listQuery['%scriptName%']"
|
||||||
|
placeholder="名称"
|
||||||
|
@pressEnter="loadData"
|
||||||
|
allowClear
|
||||||
|
class="search-input-item"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
show-search
|
||||||
|
option-filter-prop="children"
|
||||||
|
v-model:value="listQuery.triggerExecType"
|
||||||
|
allowClear
|
||||||
|
placeholder="触发类型"
|
||||||
|
class="search-input-item"
|
||||||
|
>
|
||||||
<a-select-option v-for="(val, key) in triggerExecTypeMap" :key="key">{{ val }}</a-select-option>
|
<a-select-option v-for="(val, key) in triggerExecTypeMap" :key="key">{{ val }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-select show-search option-filter-prop="children" v-model:value="listQuery.status" allowClear placeholder="状态" class="search-input-item">
|
<a-select
|
||||||
|
show-search
|
||||||
|
option-filter-prop="children"
|
||||||
|
v-model:value="listQuery.status"
|
||||||
|
allowClear
|
||||||
|
placeholder="状态"
|
||||||
|
class="search-input-item"
|
||||||
|
>
|
||||||
<a-select-option v-for="(val, key) in statusMap" :key="key">{{ val }}</a-select-option>
|
<a-select-option v-for="(val, key) in statusMap" :key="key">{{ val }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-range-picker
|
<a-range-picker
|
||||||
v-model:value="listQuery['createTimeMillis']"
|
v-model:value="listQuery['createTimeMillis']"
|
||||||
allowClear
|
allowClear
|
||||||
inputReadOnly
|
inputReadOnly
|
||||||
class="search-input-item"
|
|
||||||
:show-time="{ format: 'HH:mm:ss' }"
|
:show-time="{ format: 'HH:mm:ss' }"
|
||||||
:placeholder="['执行时间开始', '执行时间结束']"
|
:placeholder="['执行时间开始', '执行时间结束']"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
@ -26,41 +56,43 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:scriptName="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
<template v-if="column.dataIndex === 'scriptName'">
|
||||||
<span>{{ text }}</span>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
</a-tooltip>
|
<span>{{ text }}</span>
|
||||||
</template>
|
</a-tooltip>
|
||||||
<template v-slot:modifyUser="text">
|
</template>
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
<template v-else-if="column.dataIndex === 'modifyUser'">
|
||||||
<span>{{ text }}</span>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
</a-tooltip>
|
<span>{{ text }}</span>
|
||||||
</template>
|
</a-tooltip>
|
||||||
<template v-slot:triggerExecTypeMap="text">
|
</template>
|
||||||
<span>{{ triggerExecTypeMap[text] || "未知" }}</span>
|
<template v-else-if="column.dataIndex === 'triggerExecType'">
|
||||||
</template>
|
<span>{{ triggerExecTypeMap[text] || '未知' }}</span>
|
||||||
<template v-slot:global="text">
|
</template>
|
||||||
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
<template v-else-if="column.dataIndex === 'workspaceId'">
|
||||||
<a-tag v-else>工作空间</a-tag>
|
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
||||||
</template>
|
<a-tag v-else>工作空间</a-tag>
|
||||||
<template v-slot:createTimeMillis="text, record">
|
</template>
|
||||||
<a-tooltip :title="`${parseTime(record.createTimeMillis)}`">
|
<template v-else-if="column.dataIndex === 'createTimeMillis'">
|
||||||
<span>{{ parseTime(record.createTimeMillis) }}</span>
|
<a-tooltip :title="`${parseTime(record.createTimeMillis)}`">
|
||||||
</a-tooltip>
|
<span>{{ parseTime(record.createTimeMillis) }}</span>
|
||||||
</template>
|
</a-tooltip>
|
||||||
<template v-slot:exitCode="text">
|
</template>
|
||||||
<a-tag v-if="text == 0" color="green">成功</a-tag>
|
<template v-else-if="column.dataIndex === 'exitCode'">
|
||||||
<a-tag v-else color="orange">{{ text || "-" }}</a-tag>
|
<a-tag v-if="text == 0" color="green">成功</a-tag>
|
||||||
</template>
|
<a-tag v-else color="orange">{{ text || '-' }}</a-tag>
|
||||||
<template v-slot:status="text">
|
</template>
|
||||||
<span>{{ statusMap[text] || "" }}</span>
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
</template>
|
<span>{{ statusMap[text] || '' }}</span>
|
||||||
<template v-slot:operation="text, record">
|
</template>
|
||||||
<a-space>
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-button type="primary" size="small" @click="viewLog(record)">查看日志</a-button>
|
<a-space>
|
||||||
|
<a-button type="primary" size="small" @click="viewLog(record)">查看日志</a-button>
|
||||||
|
|
||||||
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 日志 -->
|
<!-- 日志 -->
|
||||||
@ -70,7 +102,7 @@
|
|||||||
:visible="logVisible != 0"
|
:visible="logVisible != 0"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
logVisible = 0;
|
logVisible = 0
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:temp="temp"
|
:temp="temp"
|
||||||
@ -79,20 +111,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getScriptLogList, scriptDel, triggerExecTypeMap } from "@/api/server-script";
|
import { getScriptLogList, scriptDel, triggerExecTypeMap } from '@/api/server-script'
|
||||||
import ScriptLogView from "@/pages/script/script-log-view";
|
import ScriptLogView from '@/pages/script/script-log-view'
|
||||||
import { statusMap } from "@/api/command";
|
import { statusMap } from '@/api/command'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from "@/utils/const";
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ScriptLogView,
|
ScriptLogView
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
scriptId: {
|
scriptId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: ''
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -105,123 +137,123 @@ export default {
|
|||||||
logVisible: 0,
|
logVisible: 0,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: "名称",
|
title: '名称',
|
||||||
dataIndex: "scriptName",
|
dataIndex: 'scriptName',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "scriptName" },
|
scopedSlots: { customRender: 'scriptName' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "执行时间",
|
title: '执行时间',
|
||||||
dataIndex: "createTimeMillis",
|
dataIndex: 'createTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: "160px",
|
width: '160px',
|
||||||
scopedSlots: { customRender: "createTimeMillis" },
|
scopedSlots: { customRender: 'createTimeMillis' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "触发类型",
|
title: '触发类型',
|
||||||
dataIndex: "triggerExecType",
|
dataIndex: 'triggerExecType',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "triggerExecTypeMap" },
|
scopedSlots: { customRender: 'triggerExecTypeMap' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "状态",
|
title: '状态',
|
||||||
dataIndex: "status",
|
dataIndex: 'status',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "status" },
|
scopedSlots: { customRender: 'status' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "执行域",
|
title: '执行域',
|
||||||
dataIndex: "workspaceId",
|
dataIndex: 'workspaceId',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "global" },
|
scopedSlots: { customRender: 'global' },
|
||||||
width: "90px",
|
width: '90px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "退出码",
|
title: '退出码',
|
||||||
dataIndex: "exitCode",
|
dataIndex: 'exitCode',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "exitCode" },
|
scopedSlots: { customRender: 'exitCode' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "执行人",
|
title: '执行人',
|
||||||
dataIndex: "modifyUser",
|
dataIndex: 'modifyUser',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: "100px",
|
width: '100px',
|
||||||
scopedSlots: { customRender: "modifyUser" },
|
scopedSlots: { customRender: 'modifyUser' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: '操作',
|
||||||
dataIndex: "operation",
|
dataIndex: 'operation',
|
||||||
align: "center",
|
align: 'center',
|
||||||
fixed: "right",
|
fixed: 'right',
|
||||||
scopedSlots: { customRender: "operation" },
|
scopedSlots: { customRender: 'operation' },
|
||||||
width: "150px",
|
width: '150px'
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery);
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadData();
|
this.loadData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 加载数据
|
// 加载数据
|
||||||
loadData(pointerEvent) {
|
loadData(pointerEvent) {
|
||||||
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page;
|
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page
|
||||||
this.listQuery.scriptId = this.scriptId;
|
this.listQuery.scriptId = this.scriptId
|
||||||
this.loading = true;
|
this.loading = true
|
||||||
getScriptLogList(this.listQuery).then((res) => {
|
getScriptLogList(this.listQuery).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.list = res.data.result;
|
this.list = res.data.result
|
||||||
this.listQuery.total = res.data.total;
|
this.listQuery.total = res.data.total
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
parseTime,
|
parseTime,
|
||||||
viewLog(record) {
|
viewLog(record) {
|
||||||
this.logVisible = new Date() * Math.random();
|
this.logVisible = new Date() * Math.random()
|
||||||
this.temp = record;
|
this.temp = record
|
||||||
},
|
},
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: "系统提示",
|
title: '系统提示',
|
||||||
content: "真的要删除执行记录么?",
|
content: '真的要删除执行记录么?',
|
||||||
zIndex: 1009,
|
zIndex: 1009,
|
||||||
okText: "确认",
|
okText: '确认',
|
||||||
cancelText: "取消",
|
cancelText: '取消',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
// 组装参数
|
// 组装参数
|
||||||
const params = {
|
const params = {
|
||||||
id: record.scriptId,
|
id: record.scriptId,
|
||||||
executeId: record.id,
|
executeId: record.id
|
||||||
};
|
}
|
||||||
// 删除
|
// 删除
|
||||||
scriptDel(params).then((res) => {
|
scriptDel(params).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg,
|
message: res.msg
|
||||||
});
|
})
|
||||||
this.loadData();
|
this.loadData()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 分页、排序、筛选变化时触发
|
// 分页、排序、筛选变化时触发
|
||||||
changePage(pagination, filters, sorter) {
|
changePage(pagination, filters, sorter) {
|
||||||
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter });
|
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter })
|
||||||
this.loadData();
|
this.loadData()
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<a-table
|
<a-table
|
||||||
size="middle"
|
size="middle"
|
||||||
:data-source="commandList"
|
:data-source="commandList"
|
||||||
@ -7,18 +7,20 @@
|
|||||||
bordered
|
bordered
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
:rowKey="(record, index) => index"
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%commandName%']"
|
v-model:value="listQuery['%commandName%']"
|
||||||
@pressEnter="getCommandLogData"
|
@pressEnter="getCommandLogData"
|
||||||
placeholder="搜索命令名称"
|
placeholder="搜索命令名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%sshName%']"
|
v-model:value="listQuery['%sshName%']"
|
||||||
@pressEnter="getCommandLogData"
|
@pressEnter="getCommandLogData"
|
||||||
placeholder="搜索ssh名称"
|
placeholder="搜索ssh名称"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -26,7 +28,7 @@
|
|||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
v-model="listQuery.status"
|
v-model:value="listQuery.status"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="状态"
|
placeholder="状态"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -36,7 +38,7 @@
|
|||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
v-model="listQuery.triggerExecType"
|
v-model:value="listQuery.triggerExecType"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="触发类型"
|
placeholder="触发类型"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -48,39 +50,51 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #sshName slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.dataIndex === 'sshName'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-tooltip #commandName slot-scope="text" placement="topLeft" :title="text">
|
<span>{{ text }}</span>
|
||||||
<span>{{ text }}</span>
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</template>
|
||||||
<template #status slot-scope="text">
|
<template v-else-if="column.dataIndex === 'commandName'">
|
||||||
<span>{{ statusMap[text] || '未知' }}</span>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
</template>
|
<span>{{ text }}</span>
|
||||||
<template #triggerExecTypeMap slot-scope="text">
|
</a-tooltip>
|
||||||
<span>{{ triggerExecTypeMap[text] || '未知' }}</span>
|
</template>
|
||||||
</template>
|
<template v-else-if="column.dataIndex === 'status'">
|
||||||
|
<span>{{ statusMap[text] || '未知' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'triggerExecType'">
|
||||||
|
<span>{{ triggerExecTypeMap[text] || '未知' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'exitCode'">
|
||||||
|
<a-tag v-if="text == 0" color="green">成功</a-tag>
|
||||||
|
<a-tag v-else color="orange">{{ text || '-' }}</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="primary" size="small" :disabled="!record.hasLog" @click="handleView(record)">查看</a-button>
|
<a-button type="primary" size="small" :disabled="!record.hasLog" @click="handleView(record)">查看</a-button>
|
||||||
<a-button type="primary" size="small" :disabled="!record.hasLog" @click="handleDownload(record)"
|
<a-button type="primary" size="small" :disabled="!record.hasLog" @click="handleDownload(record)"
|
||||||
><a-icon type="download" />日志</a-button
|
><DownloadOutlined />日志</a-button
|
||||||
>
|
>
|
||||||
<a-button type="danger" size="small" @click="handleDelete(record)">删除</a-button>
|
<a-button type="primary" danger size="small" @click="handleDelete(record)">删除</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 构建日志 -->
|
<!-- 构建日志 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:width="'80vw'"
|
:width="style.width"
|
||||||
v-model:visible="logVisible"
|
:bodyStyle="style.bodyStyle"
|
||||||
|
:style="style.style"
|
||||||
|
v-model:open="logVisible"
|
||||||
title="执行日志"
|
title="执行日志"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<command-log v-if="logVisible" :temp="temp" />
|
<command-log :height="style.bodyStyle.height" v-if="logVisible" :temp="temp" />
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -89,7 +103,8 @@
|
|||||||
import { deleteCommandLog, downloadLog, getCommandLogList, statusMap, triggerExecTypeMap } from '@/api/command'
|
import { deleteCommandLog, downloadLog, getCommandLogList, statusMap, triggerExecTypeMap } from '@/api/command'
|
||||||
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime } from '@/utils/const'
|
||||||
import CommandLog from './command-view-log'
|
import CommandLog from './command-view-log'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
|
import { useGuideStore } from '@/stores/guide'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CommandLog
|
CommandLog
|
||||||
@ -104,58 +119,80 @@ export default {
|
|||||||
triggerExecTypeMap: triggerExecTypeMap,
|
triggerExecTypeMap: triggerExecTypeMap,
|
||||||
logVisible: false,
|
logVisible: false,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: 'ssh 名称', dataIndex: 'sshName', ellipsis: true, scopedSlots: { customRender: 'sshName' } },
|
{
|
||||||
{ title: '命令名称', dataIndex: 'commandName', ellipsis: true, scopedSlots: { customRender: 'commandName' } },
|
title: 'ssh 名称',
|
||||||
{ title: '状态', dataIndex: 'status', width: 100, ellipsis: true, scopedSlots: { customRender: 'status' } },
|
dataIndex: 'sshName',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '命令名称',
|
||||||
|
dataIndex: 'commandName',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
width: 100,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '退出码',
|
||||||
|
dataIndex: 'exitCode',
|
||||||
|
width: 100,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '触发类型',
|
title: '触发类型',
|
||||||
dataIndex: 'triggerExecType',
|
dataIndex: 'triggerExecType',
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'triggerExecTypeMap' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '执行时间',
|
title: '执行时间',
|
||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
width: 170
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '结束时间',
|
title: '结束时间',
|
||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
width: 170
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '执行人',
|
title: '执行人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
width: 120,
|
width: 120,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'modifyUser' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
fixed: 'right',
|
||||||
width: 200
|
width: '200px'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState(useGuideStore, ['getFullscreenViewLogStyle']),
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
|
},
|
||||||
|
style() {
|
||||||
|
return this.getFullscreenViewLogStyle()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getCommandLogData()
|
this.getCommandLogData()
|
||||||
},
|
},
|
||||||
@ -184,8 +221,9 @@ export default {
|
|||||||
},
|
},
|
||||||
// 删除命令
|
// 删除命令
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除该执行记录吗?',
|
content: '真的要删除该执行记录吗?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -193,7 +231,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteCommandLog(row.id).then((res) => {
|
deleteCommandLog(row.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.getCommandLogData()
|
this.getCommandLogData()
|
||||||
@ -209,4 +247,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,27 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="margin-top: -10px">
|
<div>
|
||||||
<a-tabs :activeKey="activeKey" @change="tabCallback">
|
<a-tabs :activeKey="activeKey" @change="tabCallback">
|
||||||
<a-tab-pane v-for="item in logList" :key="item.id">
|
<a-tab-pane v-for="item in logList" :key="item.id">
|
||||||
<span #tab>
|
<template v-slot:tab>
|
||||||
<a-icon v-if="!logMap[item.id] || logMap[item.id].run" type="loading" />
|
<span>
|
||||||
{{ item.sshName }}
|
<LoadingOutlined v-if="!logMap[item.id] || logMap[item.id].run" />
|
||||||
</span>
|
{{ item.sshName }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<!-- <a-input :id="`build-log-textarea-${item.id}`" v-model="logMap[item.id].logText" type="textarea" class="console" readOnly style="resize: none; height: 60vh" /> -->
|
<!-- <a-input :id="`build-log-textarea-${item.id}`" v-model="logMap[item.id].logText" type="textarea" class="console" readOnly style="resize: none; height: 60vh" /> -->
|
||||||
<log-view :ref="`logView-${item.id}`" height="60vh" />
|
<log-view1 :ref="`logView-${item.id}`" :height="`calc(${height} - 130px)`" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCommandLogBarchList, getCommandLogInfo } from '@/api/command'
|
import { getCommandLogBarchList, getCommandLogInfo } from '@/api/command'
|
||||||
import LogView from '@/components/logView'
|
import LogView1 from '@/components/logView/index2'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
LogView
|
LogView1
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
temp: {
|
temp: {
|
||||||
type: Object
|
type: Object
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '60vh'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -32,7 +39,7 @@ export default {
|
|||||||
logMap: {}
|
logMap: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
if (this.logTimerMap) {
|
if (this.logTimerMap) {
|
||||||
this.logList.forEach((item) => {
|
this.logList.forEach((item) => {
|
||||||
clearInterval(this.logTimerMap[item.id])
|
clearInterval(this.logTimerMap[item.id])
|
||||||
@ -79,7 +86,7 @@ export default {
|
|||||||
getCommandLogInfo(params).then((res) => {
|
getCommandLogInfo(params).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (!res.data) {
|
if (!res.data) {
|
||||||
$notification.warning({
|
this.$notification.warning({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.logMap[item.id].tryCount = this.logMap[item.id].tryCount + 1
|
this.logMap[item.id].tryCount = this.logMap[item.id].tryCount + 1
|
||||||
@ -115,7 +122,7 @@ export default {
|
|||||||
this.logMap[item.id].line = res.data.line
|
this.logMap[item.id].line = res.data.line
|
||||||
// if (lines.length) {
|
// if (lines.length) {
|
||||||
// // 自动滚动到底部
|
// // 自动滚动到底部
|
||||||
// nextTick(() => {
|
// this.$nextTick(() => {
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// const textarea = document.getElementById("build-log-textarea-" + item.id);
|
// const textarea = document.getElementById("build-log-textarea-" + item.id);
|
||||||
// if (textarea) {
|
// if (textarea) {
|
||||||
@ -135,7 +142,7 @@ export default {
|
|||||||
if (this.logTimerMap[key]) {
|
if (this.logTimerMap[key]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const index = this.logList
|
const index = this.logList
|
||||||
.map((item1, index) => {
|
.map((item1, index) => {
|
||||||
return item1.id == key ? index : -1
|
return item1.id == key ? index : -1
|
||||||
@ -147,6 +154,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* .console {
|
/* .console {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<a-table
|
<a-table
|
||||||
:data-source="commandList"
|
:data-source="commandList"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
@ -9,23 +9,26 @@
|
|||||||
@change="changePage"
|
@change="changePage"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
@pressEnter="getCommandData"
|
@pressEnter="getCommandData"
|
||||||
placeholder="搜索命令"
|
placeholder="搜索命令"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%desc%']"
|
v-model:value="listQuery['%desc%']"
|
||||||
@pressEnter="getCommandData"
|
@pressEnter="getCommandData"
|
||||||
placeholder="描述"
|
placeholder="描述"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
/>
|
/>
|
||||||
<a-input
|
<a-input
|
||||||
v-model="listQuery['%autoExecCron%']"
|
v-model:value="listQuery['%autoExecCron%']"
|
||||||
@pressEnter="getCommandData"
|
@pressEnter="getCommandData"
|
||||||
placeholder="定时执行"
|
placeholder="定时执行"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -35,8 +38,8 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-button type="primary" @click="createCommand">新建命令</a-button>
|
<a-button type="primary" @click="createCommand">新建命令</a-button>
|
||||||
<a-dropdown>
|
<a-dropdown>
|
||||||
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()"> 更多 <down-outlined /> </a>
|
<a @click="(e) => e.preventDefault()"> 更多 <DownOutlined /> </a>
|
||||||
<template #overlay>
|
<template v-slot:overlay>
|
||||||
<a-menu>
|
<a-menu>
|
||||||
<a-menu-item>
|
<a-menu-item>
|
||||||
<a-button
|
<a-button
|
||||||
@ -50,7 +53,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<div>命令模版是用于在线管理一些脚本命令,如初始化软件环境、管理应用程序等</div>
|
<div>命令模版是用于在线管理一些脚本命令,如初始化软件环境、管理应用程序等</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -61,63 +64,76 @@
|
|||||||
命令文件、并自动加载环境变量:/etc/profile、/etc/bashrc、~/.bashrc、~/.bash_profile
|
命令文件、并自动加载环境变量:/etc/profile、/etc/bashrc、~/.bashrc、~/.bash_profile
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
执行命令包含:<b>#disabled-template-auto-evn</b> 将取消自动加载环境变量(注意是整行不能包含空格)
|
执行命令包含:<b>#disabled-template-auto-evn</b>
|
||||||
|
将取消自动加载环境变量(注意是整行不能包含空格)
|
||||||
</li>
|
</li>
|
||||||
<li>命令文件将上传至 ${user.home}/.jpom/xxxx.sh 执行完成将自动删除</li>
|
<li>命令文件将上传至 ${user.home}/.jpom/xxxx.sh 执行完成将自动删除</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #name slot-scope="text" placement="topLeft" :title="text">
|
<template #bodyCell="{ column, text, record }">
|
||||||
<span>{{ text }}</span>
|
<template v-if="column.dataIndex === 'name'">
|
||||||
</a-tooltip>
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
<a-tooltip #desc slot-scope="text" placement="topLeft" :title="text">
|
<span>{{ text }}</span>
|
||||||
<span>{{ text }}</span>
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex === 'desc'">
|
||||||
|
<a-tooltip placement="topLeft" :title="text">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #operation slot-scope="text, record">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button size="small" type="primary" @click="handleExecute(record)">执行</a-button>
|
<a-button size="small" type="primary" @click="handleExecute(record)">执行</a-button>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
<a-button size="small" type="primary" @click="handleTrigger(record)">触发器</a-button>
|
<a-button size="small" type="primary" @click="handleTrigger(record)">触发器</a-button>
|
||||||
<a-button size="small" type="danger" @click="handleDelete(record)">删除</a-button>
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑命令 -->
|
<!-- 编辑命令 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editCommandVisible"
|
v-model:open="editCommandVisible"
|
||||||
width="80vw"
|
width="80vw"
|
||||||
title="编辑 命令"
|
title="编辑 命令"
|
||||||
@ok="handleEditCommandOk"
|
@ok="handleEditCommandOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form ref="editCommandForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 20 }">
|
<a-form ref="editCommandForm" :rules="rules" :model="temp" :label-col="{ span: 3 }" :wrapper-col="{ span: 20 }">
|
||||||
<a-form-item label="命令名称" name="name">
|
<a-form-item label="命令名称" name="name">
|
||||||
<a-input v-model="temp.name" :maxLength="100" placeholder="命令名称" />
|
<a-input v-model:value="temp.name" :maxLength="100" placeholder="命令名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
name="command"
|
name="command"
|
||||||
help="脚本存放路径:${user.home}/.jpom/xxxx.sh,执行脚本路径:${user.home},执行脚本方式:bash ${user.home}/.jpom/xxxx.sh par1 par2"
|
help="脚本存放路径:${user.home}/.jpom/xxxx.sh,执行脚本路径:${user.home},执行脚本方式:bash ${user.home}/.jpom/xxxx.sh par1 par2"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template v-slot:label>
|
||||||
命令内容
|
<a-tooltip>
|
||||||
<a-tooltip v-show="!temp.id">
|
命令内容
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<ul>
|
<ul>
|
||||||
<li>可以引用工作空间的环境变量 变量占位符 ${xxxx} xxxx 为变量名称</li>
|
<li>可以引用工作空间的环境变量 变量占位符 ${xxxx} xxxx 为变量名称</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined v-show="!temp.id" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<div style="height: 40vh; overflow-y: scroll">
|
<div style="height: 40vh; overflow-y: scroll">
|
||||||
<code-editor v-model="temp.command" :options="{ mode: 'shell', tabSize: 2, theme: 'abcdef' }"></code-editor>
|
<a-form-item-rest>
|
||||||
|
<code-editor
|
||||||
|
v-model:content="temp.command"
|
||||||
|
:options="{ mode: 'shell', tabSize: 2, theme: 'abcdef' }"
|
||||||
|
></code-editor>
|
||||||
|
</a-form-item-rest>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="SSH节点">
|
<a-form-item label="SSH节点">
|
||||||
@ -126,7 +142,7 @@
|
|||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
placeholder="请选择SSH节点"
|
placeholder="请选择SSH节点"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="chooseSsh"
|
v-model:value="chooseSsh"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="item in sshList" :key="item.id" :value="item.id">
|
<a-select-option v-for="item in sshList" :key="item.id" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
@ -135,56 +151,49 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="默认参数">
|
<a-form-item label="默认参数">
|
||||||
<div v-for="(item, index) in commandParams" :key="item.key">
|
<a-form-item-rest>
|
||||||
<a-row type="flex" justify="center" align="middle">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-col :span="22">
|
<a-row v-for="(item, index) in commandParams" :key="item.key">
|
||||||
<a-input
|
<a-col :span="22">
|
||||||
:addon-before="`参数${index + 1}描述`"
|
<a-space direction="vertical" style="width: 100%">
|
||||||
v-model="item.desc"
|
<a-input
|
||||||
placeholder="参数描述,参数描述没有实际作用,仅是用于提示参数的含义"
|
:addon-before="`参数${index + 1}描述`"
|
||||||
/>
|
v-model:value="item.desc"
|
||||||
<a-input
|
placeholder="参数描述,参数描述没有实际作用,仅是用于提示参数的含义"
|
||||||
:addon-before="`参数${index + 1}值`"
|
/>
|
||||||
v-model="item.value"
|
<a-input
|
||||||
placeholder="参数值,添加默认参数后在手动执行脚本时需要填写参数值"
|
:addon-before="`参数${index + 1}值`"
|
||||||
/>
|
v-model:value="item.value"
|
||||||
</a-col>
|
placeholder="参数值,添加默认参数后在手动执行脚本时需要填写参数值"
|
||||||
<a-col :span="2">
|
/>
|
||||||
<a-row type="flex" justify="center" align="middle">
|
</a-space>
|
||||||
<a-col>
|
</a-col>
|
||||||
<a-icon @click="() => commandParams.splice(index, 1)" type="minus-circle" style="color: #ff0000" />
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
<a-divider style="margin: 5px 0" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
<a-col :span="2">
|
||||||
|
<a-row type="flex" justify="center" align="middle">
|
||||||
|
<a-col>
|
||||||
|
<MinusCircleOutlined @click="() => commandParams.splice(index, 1)" style="color: #ff0000" />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item-rest>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="自动执行" name="autoExecCron">
|
<a-form-item label="自动执行" name="autoExecCron">
|
||||||
<a-auto-complete
|
<a-auto-complete
|
||||||
v-model="temp.autoExecCron"
|
v-model:value="temp.autoExecCron"
|
||||||
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
placeholder="如果需要定时自动执行则填写,cron 表达式.默认未开启秒级别,需要去修改配置文件中:[system.timerMatchSecond])"
|
||||||
option-label-prop="value"
|
:options="CRON_DATA_SOURCE"
|
||||||
>
|
>
|
||||||
<template #dataSource>
|
<template #option="item"> {{ item.title }} {{ item.value }} </template>
|
||||||
<a-select-opt-group v-for="group in cronDataSource" :key="group.title">
|
|
||||||
<span #label>
|
|
||||||
{{ group.title }}
|
|
||||||
</span>
|
|
||||||
<a-select-option v-for="opt in group.children" :key="opt.title" :value="opt.value">
|
|
||||||
{{ opt.title }} {{ opt.value }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select-opt-group>
|
|
||||||
</template>
|
|
||||||
</a-auto-complete>
|
</a-auto-complete>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="命令描述" name="desc">
|
<a-form-item label="命令描述" name="desc">
|
||||||
<a-input
|
<a-textarea
|
||||||
v-model="temp.desc"
|
v-model:value="temp.desc"
|
||||||
:maxLength="255"
|
:maxLength="255"
|
||||||
type="textarea"
|
|
||||||
:rows="3"
|
:rows="3"
|
||||||
style="resize: none"
|
style="resize: none"
|
||||||
placeholder="命令详细描述"
|
placeholder="命令详细描述"
|
||||||
@ -195,15 +204,16 @@
|
|||||||
|
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="executeCommandVisible"
|
v-model:open="executeCommandVisible"
|
||||||
width="600px"
|
width="600px"
|
||||||
title="执行 命令"
|
title="执行 命令"
|
||||||
@ok="handleExecuteCommandOk"
|
@ok="handleExecuteCommandOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="命令名称" name="name">
|
<a-form-item label="命令名称" name="name">
|
||||||
<a-input v-model="temp.name" :disabled="true" placeholder="命令名称" />
|
<a-input v-model:value="temp.name" :disabled="true" placeholder="命令名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="SSH节点" required>
|
<a-form-item label="SSH节点" required>
|
||||||
@ -211,7 +221,7 @@
|
|||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
v-model="chooseSsh"
|
v-model:value="chooseSsh"
|
||||||
placeholder="请选择 SSH节点"
|
placeholder="请选择 SSH节点"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="item in sshList" :key="item.id" :value="item.id">
|
<a-select-option v-for="item in sshList" :key="item.id" :value="item.id">
|
||||||
@ -228,30 +238,32 @@
|
|||||||
: ''
|
: ''
|
||||||
}`"
|
}`"
|
||||||
>
|
>
|
||||||
<a-row v-for="(item, index) in commandParams" :key="item.key">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-col :span="22">
|
<a-row v-for="(item, index) in commandParams" :key="item.key">
|
||||||
<a-input
|
<a-col :span="22">
|
||||||
:addon-before="`参数${index + 1}值`"
|
<a-input
|
||||||
v-model="item.value"
|
:addon-before="`参数${index + 1}值`"
|
||||||
:placeholder="`参数值 ${item.desc ? ',' + item.desc : ''}`"
|
v-model:value="item.value"
|
||||||
>
|
:placeholder="`参数值 ${item.desc ? ',' + item.desc : ''}`"
|
||||||
<template #suffix>
|
>
|
||||||
<a-tooltip v-if="item.desc" :title="item.desc">
|
<template v-slot:suffix>
|
||||||
<a-icon type="info-circle" style="color: rgba(0, 0, 0, 0.45)" />
|
<a-tooltip v-if="item.desc" :title="item.desc">
|
||||||
</a-tooltip>
|
<InfoCircleOutlined />
|
||||||
</template>
|
</a-tooltip>
|
||||||
</a-input>
|
</template>
|
||||||
</a-col>
|
</a-input>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
<a-col v-if="!item.desc" :span="2">
|
<a-col v-if="!item.desc" :span="2">
|
||||||
<a-row type="flex" justify="center" align="middle">
|
<a-row type="flex" justify="center" align="middle">
|
||||||
<a-col>
|
<a-col>
|
||||||
<a-icon type="minus-circle" style="color: #ff0000" @click="() => commandParams.splice(index, 1)" />
|
<MinusCircleOutlined style="color: #ff0000" @click="() => commandParams.splice(index, 1)" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
<a-button type="primary" @click="() => commandParams.push({})">添加参数</a-button>
|
||||||
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
@ -259,7 +271,7 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:width="'80vw'"
|
:width="'80vw'"
|
||||||
v-model:visible="logVisible"
|
v-model:open="logVisible"
|
||||||
title="执行日志"
|
title="执行日志"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
@ -269,13 +281,14 @@
|
|||||||
<!-- 同步到其他工作空间 -->
|
<!-- 同步到其他工作空间 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="syncToWorkspaceVisible"
|
:confirmLoading="confirmLoading"
|
||||||
|
v-model:open="syncToWorkspaceVisible"
|
||||||
title="同步到其他工作空间"
|
title="同步到其他工作空间"
|
||||||
@ok="handleSyncToWorkspace"
|
@ok="handleSyncToWorkspace"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning" show-icon>
|
||||||
<template #description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
<li>同步机制采用<b>脚本名称</b>确定是同一个脚本</li>
|
<li>同步机制采用<b>脚本名称</b>确定是同一个脚本</li>
|
||||||
<li>当目标工作空间不存在对应的 脚本 时候将自动创建一个新的 脚本</li>
|
<li>当目标工作空间不存在对应的 脚本 时候将自动创建一个新的 脚本</li>
|
||||||
@ -286,7 +299,12 @@
|
|||||||
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item> </a-form-item>
|
<a-form-item> </a-form-item>
|
||||||
<a-form-item label="选择工作空间" name="workspaceId">
|
<a-form-item label="选择工作空间" name="workspaceId">
|
||||||
<a-select show-search option-filter-prop="children" v-model="temp.workspaceId" placeholder="请选择工作空间">
|
<a-select
|
||||||
|
show-search
|
||||||
|
option-filter-prop="children"
|
||||||
|
v-model:value="temp.workspaceId"
|
||||||
|
placeholder="请选择工作空间"
|
||||||
|
>
|
||||||
<a-select-option :disabled="getWorkspaceId() === item.id" v-for="item in workspaceList" :key="item.id">{{
|
<a-select-option :disabled="getWorkspaceId() === item.id" v-for="item in workspaceList" :key="item.id">{{
|
||||||
item.name
|
item.name
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
@ -298,7 +316,7 @@
|
|||||||
<!-- 触发器 -->
|
<!-- 触发器 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model:visible="triggerVisible"
|
v-model:open="triggerVisible"
|
||||||
title="触发器"
|
title="触发器"
|
||||||
width="50%"
|
width="50%"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -306,15 +324,15 @@
|
|||||||
>
|
>
|
||||||
<a-form ref="editTriggerForm" :rules="rules" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
<a-form ref="editTriggerForm" :rules="rules" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
||||||
<a-tabs default-active-key="1">
|
<a-tabs default-active-key="1">
|
||||||
<template #tabBarExtraContent>
|
<template v-slot:tabBarExtraContent>
|
||||||
<a-tooltip title="重置触发器 token 信息,重置后之前的触发器 token 将失效">
|
<a-tooltip title="重置触发器 token 信息,重置后之前的触发器 token 将失效">
|
||||||
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
<a-button type="primary" size="small" @click="resetTrigger">重置</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-tab-pane key="1" tab="执行">
|
<a-tab-pane key="1" tab="执行">
|
||||||
<a-space style="display: block" direction="vertical" align="baseline">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning">
|
||||||
<template #description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
<li>单个触发器地址中:第一个随机字符串为命令脚本ID,第二个随机字符串为 token</li>
|
<li>单个触发器地址中:第一个随机字符串为命令脚本ID,第二个随机字符串为 token</li>
|
||||||
<li>
|
<li>
|
||||||
@ -324,44 +342,18 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a-alert
|
<a-alert type="info" :message="`单个触发器地址(点击可以复制)`">
|
||||||
v-clipboard:copy="temp.triggerUrl"
|
<template v-slot:description>
|
||||||
v-clipboard:success="
|
<a-typography-paragraph :copyable="{ tooltip: false, text: temp.triggerUrl }">
|
||||||
() => {
|
<a-tag>GET</a-tag> <span>{{ temp.triggerUrl }} </span>
|
||||||
tempVue.prototype.$notification.success({ message: '复制成功' })
|
</a-typography-paragraph>
|
||||||
}
|
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({ message: '复制失败' })
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`单个触发器地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template #description>
|
|
||||||
<a-tag>GET</a-tag> <span>{{ temp.triggerUrl }} </span>
|
|
||||||
<a-icon type="copy" />
|
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
<a-alert
|
<a-alert type="info" :message="`批量触发器地址(点击可以复制)`">
|
||||||
v-clipboard:copy="temp.batchTriggerUrl"
|
<template v-slot:description>
|
||||||
v-clipboard:success="
|
<a-typography-paragraph :copyable="{ tooltip: false, text: temp.batchTriggerUrl }">
|
||||||
() => {
|
<a-tag>POST</a-tag> <span>{{ temp.batchTriggerUrl }} </span>
|
||||||
tempVue.prototype.$notification.success({ message: '复制成功' })
|
</a-typography-paragraph>
|
||||||
}
|
|
||||||
"
|
|
||||||
v-clipboard:error="
|
|
||||||
() => {
|
|
||||||
tempVue.prototype.$notification.error({ message: '复制失败' })
|
|
||||||
}
|
|
||||||
"
|
|
||||||
type="info"
|
|
||||||
:message="`批量触发器地址(点击可以复制)`"
|
|
||||||
>
|
|
||||||
<template #description>
|
|
||||||
<a-tag>POST</a-tag> <span>{{ temp.batchTriggerUrl }} </span>
|
|
||||||
<a-icon type="copy" />
|
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</a-space>
|
</a-space>
|
||||||
@ -378,16 +370,16 @@ import { CHANGE_PAGE, COMPUTED_PAGINATION, CRON_DATA_SOURCE, PAGE_DEFAULT_LIST_Q
|
|||||||
import { getSshListAll } from '@/api/ssh'
|
import { getSshListAll } from '@/api/ssh'
|
||||||
import codeEditor from '@/components/codeEditor'
|
import codeEditor from '@/components/codeEditor'
|
||||||
import CommandLog from './command-view-log'
|
import CommandLog from './command-view-log'
|
||||||
import { mapState } from 'pinia'
|
import { mapGetters } from 'vuex'
|
||||||
import { getWorkSpaceListAll } from '@/api/workspace'
|
import { getWorkSpaceListAll } from '@/api/workspace'
|
||||||
// import Vue from 'vue'
|
import { mapState } from 'pinia'
|
||||||
|
import { useAppStore } from '@/stores/app'
|
||||||
export default {
|
export default {
|
||||||
components: { codeEditor, CommandLog },
|
components: { codeEditor, CommandLog },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
||||||
cronDataSource: CRON_DATA_SOURCE,
|
CRON_DATA_SOURCE,
|
||||||
commandList: [],
|
commandList: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
editCommandVisible: false,
|
editCommandVisible: false,
|
||||||
@ -402,21 +394,30 @@ export default {
|
|||||||
command: [{ required: true, message: 'Please input command', trigger: 'blur' }]
|
command: [{ required: true, message: 'Please input command', trigger: 'blur' }]
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{ title: '命令名称', dataIndex: 'name', ellipsis: true, width: 200, scopedSlots: { customRender: 'name' } },
|
{
|
||||||
{ title: '命令描述', dataIndex: 'desc', ellipsis: true, width: 250, scopedSlots: { customRender: 'desc' } },
|
title: '命令名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '命令描述',
|
||||||
|
dataIndex: 'desc',
|
||||||
|
ellipsis: true,
|
||||||
|
width: 250
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '定时执行',
|
title: '定时执行',
|
||||||
dataIndex: 'autoExecCron',
|
dataIndex: 'autoExecCron',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
width: 120,
|
width: 120
|
||||||
scopedSlots: { customRender: 'autoExecCron' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
},
|
},
|
||||||
width: '170px'
|
width: '170px'
|
||||||
@ -427,7 +428,7 @@ export default {
|
|||||||
width: '170px',
|
width: '170px',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => {
|
customRender: ({ text }) => {
|
||||||
return parseTime(text)
|
return parseTime(text)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -435,14 +436,13 @@ export default {
|
|||||||
title: '最后操作人',
|
title: '最后操作人',
|
||||||
dataIndex: 'modifyUser',
|
dataIndex: 'modifyUser',
|
||||||
width: 120,
|
width: 120,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'modifyUser' }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: '240px'
|
width: '240px'
|
||||||
}
|
}
|
||||||
@ -450,11 +450,12 @@ export default {
|
|||||||
tableSelections: [],
|
tableSelections: [],
|
||||||
syncToWorkspaceVisible: false,
|
syncToWorkspaceVisible: false,
|
||||||
workspaceList: [],
|
workspaceList: [],
|
||||||
triggerVisible: false
|
triggerVisible: false,
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getWorkspaceId']),
|
...mapState(useAppStore, ['getWorkspaceId']),
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
},
|
},
|
||||||
@ -474,15 +475,11 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
// 编辑命令信息
|
// 编辑命令信息
|
||||||
handleEditCommandOk() {
|
handleEditCommandOk() {
|
||||||
this.$refs['editCommandForm'].validate((valid) => {
|
this.$refs['editCommandForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
this.formLoading = true
|
|
||||||
if (this.commandParams && this.commandParams.length > 0) {
|
if (this.commandParams && this.commandParams.length > 0) {
|
||||||
for (let i = 0; i < this.commandParams.length; i++) {
|
for (let i = 0; i < this.commandParams.length; i++) {
|
||||||
if (!this.commandParams[i].desc) {
|
if (!this.commandParams[i].desc) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请填写第' + (i + 1) + '个参数的描述'
|
message: '请填写第' + (i + 1) + '个参数的描述'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
@ -493,17 +490,21 @@ export default {
|
|||||||
this.temp.defParams = ''
|
this.temp.defParams = ''
|
||||||
}
|
}
|
||||||
this.temp.sshIds = this.chooseSsh.join(',')
|
this.temp.sshIds = this.chooseSsh.join(',')
|
||||||
editCommand(this.temp).then((res) => {
|
this.confirmLoading = true
|
||||||
this.formLoading = false
|
editCommand(this.temp)
|
||||||
if (res.code === 200) {
|
.then((res) => {
|
||||||
$notification.success({
|
if (res.code === 200) {
|
||||||
message: res.msg
|
this.$notification.success({
|
||||||
})
|
message: res.msg
|
||||||
this.editCommandVisible = false
|
})
|
||||||
|
this.editCommandVisible = false
|
||||||
|
|
||||||
this.getCommandData()
|
this.getCommandData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 获取命令数据
|
// 获取命令数据
|
||||||
@ -561,8 +562,9 @@ export default {
|
|||||||
},
|
},
|
||||||
// 删除命令
|
// 删除命令
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除“' + row.name + '”命令?',
|
content: '真的要删除“' + row.name + '”命令?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -570,7 +572,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteCommand(row.id).then((res) => {
|
deleteCommand(row.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.getCommandData()
|
this.getCommandData()
|
||||||
@ -588,29 +590,33 @@ export default {
|
|||||||
|
|
||||||
handleExecuteCommandOk() {
|
handleExecuteCommandOk() {
|
||||||
if (!this.chooseSsh || this.chooseSsh.length <= 0) {
|
if (!this.chooseSsh || this.chooseSsh.length <= 0) {
|
||||||
$notification.error({
|
this.$notification.error({
|
||||||
message: '请选择执行节点'
|
message: '请选择执行节点'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
this.confirmLoading = true
|
||||||
executeBatch({
|
executeBatch({
|
||||||
id: this.temp.id,
|
id: this.temp.id,
|
||||||
params: JSON.stringify(this.commandParams),
|
params: JSON.stringify(this.commandParams),
|
||||||
nodes: this.chooseSsh.join(',')
|
nodes: this.chooseSsh.join(',')
|
||||||
}).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
this.executeCommandVisible = false
|
|
||||||
this.temp = {
|
|
||||||
commandId: this.temp.id,
|
|
||||||
batchId: res.data
|
|
||||||
}
|
|
||||||
this.logVisible = true
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.executeCommandVisible = false
|
||||||
|
this.temp = {
|
||||||
|
commandId: this.temp.id,
|
||||||
|
batchId: res.data
|
||||||
|
}
|
||||||
|
this.logVisible = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 加载工作空间数据
|
// 加载工作空间数据
|
||||||
loadWorkSpaceListAll() {
|
loadWorkSpaceListAll() {
|
||||||
@ -631,25 +637,30 @@ export default {
|
|||||||
//
|
//
|
||||||
handleSyncToWorkspace() {
|
handleSyncToWorkspace() {
|
||||||
if (!this.temp.workspaceId) {
|
if (!this.temp.workspaceId) {
|
||||||
$notification.warn({
|
this.$notification.warn({
|
||||||
message: '请选择工作空间'
|
message: '请选择工作空间'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 同步
|
// 同步
|
||||||
|
this.confirmLoading = true
|
||||||
syncToWorkspace({
|
syncToWorkspace({
|
||||||
ids: this.tableSelections.join(','),
|
ids: this.tableSelections.join(','),
|
||||||
toWorkspaceId: this.temp.workspaceId
|
toWorkspaceId: this.temp.workspaceId
|
||||||
}).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
this.tableSelections = []
|
|
||||||
this.syncToWorkspaceVisible = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.tableSelections = []
|
||||||
|
this.syncToWorkspaceVisible = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 触发器
|
// 触发器
|
||||||
handleTrigger(record) {
|
handleTrigger(record) {
|
||||||
@ -671,7 +682,7 @@ export default {
|
|||||||
rest: 'rest'
|
rest: 'rest'
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.fillTriggerResult(res)
|
this.fillTriggerResult(res)
|
||||||
@ -687,6 +698,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.config-editor {
|
.config-editor {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
@ -10,17 +10,20 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<template v-if="sshData">
|
<template v-if="sshData">
|
||||||
<a-space>
|
<a-space>
|
||||||
<div>{{ sshData.name }} ({{ sshData.host }})</div>
|
<div>
|
||||||
|
{{ sshData.name }}
|
||||||
|
<template v-if="sshData.host">({{ sshData.host }})</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-button size="small" type="primary" :disabled="!sshData.fileDirs" @click="handleFile()">文件</a-button>
|
<a-button size="small" type="primary" :disabled="!sshData.fileDirs" @click="handleFile()">文件</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>loading</template>
|
<template v-else>loading</template>
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template v-slot:extra>
|
||||||
<a href="#"></a>
|
<a href="#"></a>
|
||||||
</template>
|
</template>
|
||||||
<terminal v-if="sshData" :sshId="sshData.id" />
|
<terminal1 v-if="sshData" :sshId="sshData.id" />
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-result status="404" title="不能操作" sub-title="没有对应的SSH">
|
<a-result status="404" title="不能操作" sub-title="没有对应的SSH">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
@ -33,27 +36,23 @@
|
|||||||
</a-card>
|
</a-card>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
<!-- 文件管理 -->
|
<!-- 文件管理 -->
|
||||||
<a-drawer
|
<a-drawer destroyOnClose v-if="sshData" placement="right" width="90vw" :open="drawerVisible" @close="onClose">
|
||||||
destroyOnClose
|
<template #title>
|
||||||
v-if="sshData"
|
{{ sshData.name }}<template v-if="sshData.host"> ({{ sshData.host }}) </template>文件管理
|
||||||
:title="`${sshData.name} (${sshData.host}) 文件管理`"
|
</template>
|
||||||
placement="right"
|
<ssh-file v-if="drawerVisible" :sshId="sshData.id" />
|
||||||
width="90vw"
|
|
||||||
:visible="drawerVisible"
|
|
||||||
@close="onClose"
|
|
||||||
>
|
|
||||||
<ssh-file v-if="drawerVisible" :ssh="sshData" />
|
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import terminal from './terminal'
|
import terminal1 from './terminal'
|
||||||
import { getItem } from '@/api/ssh'
|
import { getItem } from '@/api/ssh'
|
||||||
import SshFile from '@/pages/ssh/ssh-file'
|
import SshFile from '@/pages/ssh/ssh-file'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
terminal,
|
terminal1,
|
||||||
SshFile
|
SshFile
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ export default {
|
|||||||
this.loadItemData()
|
this.loadItemData()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeDestroy() {},
|
beforeUnmount() {},
|
||||||
methods: {
|
methods: {
|
||||||
loadItemData() {
|
loadItemData() {
|
||||||
getItem({
|
getItem({
|
||||||
|
208
web-vue3/src/pages/ssh/ssh-tabs.vue
Normal file
208
web-vue3/src/pages/ssh/ssh-tabs.vue
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
<template>
|
||||||
|
<a-layout style="padding: 5px 0; background: #fff">
|
||||||
|
<a-layout-sider
|
||||||
|
width="200"
|
||||||
|
:style="{
|
||||||
|
background: '#fff',
|
||||||
|
height: `calc(100vh - 10px)`,
|
||||||
|
borderRight: '1px solid #e8e8e8',
|
||||||
|
overflowX: 'scroll'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-directory-tree
|
||||||
|
v-if="treeList.length"
|
||||||
|
multiple
|
||||||
|
default-expand-all
|
||||||
|
:treeData="treeList"
|
||||||
|
:fieldNames="replaceFields"
|
||||||
|
@select="select"
|
||||||
|
>
|
||||||
|
</a-directory-tree>
|
||||||
|
<a-empty v-else></a-empty>
|
||||||
|
</a-layout-sider>
|
||||||
|
<a-layout-content :style="{ padding: '0 5px', height: `calc(100vh - 10px)` }">
|
||||||
|
<a-tabs
|
||||||
|
v-if="selectPanes.length"
|
||||||
|
v-model:value="activeKey"
|
||||||
|
type="editable-card"
|
||||||
|
hide-add
|
||||||
|
@edit="onEdit"
|
||||||
|
@change="change"
|
||||||
|
>
|
||||||
|
<template v-slot:rightExtra>
|
||||||
|
<a-button type="primary" :disabled="!activeKey" @click="changeFileVisible(activeKey, true)">
|
||||||
|
文件管理
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<a-tab-pane
|
||||||
|
v-for="pane in selectPanes"
|
||||||
|
:key="pane.id"
|
||||||
|
:tab="pane.name"
|
||||||
|
:closable="true"
|
||||||
|
:ref="`pene-${pane.id}`"
|
||||||
|
>
|
||||||
|
<div :id="`paneDom${pane.id}`">
|
||||||
|
<div v-if="pane.open" :style="{ height: `calc(100vh - 70px) ` }">
|
||||||
|
<terminal1 :sshId="pane.id" />
|
||||||
|
</div>
|
||||||
|
<a-result v-else status="warning" title="未开启当前终端">
|
||||||
|
<template #extra>
|
||||||
|
<a-button type="primary" @click="open(pane.id)"> 打开终端 </a-button>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
|
<!-- 文件管理 -->
|
||||||
|
<a-drawer
|
||||||
|
v-if="pane.openFile"
|
||||||
|
:getContainer="`#paneDom${pane.id}`"
|
||||||
|
:title="`${pane.name}文件管理`"
|
||||||
|
placement="right"
|
||||||
|
width="90vw"
|
||||||
|
:visible="pane.fileVisible"
|
||||||
|
@close="changeFileVisible(pane.id, false)"
|
||||||
|
>
|
||||||
|
<ssh-file v-if="pane.openFile" :sshId="pane.id" />
|
||||||
|
</a-drawer>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
<a-empty v-else description="未选择ssh"></a-empty>
|
||||||
|
</a-layout-content>
|
||||||
|
</a-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getSshListTree } from '@/api/ssh'
|
||||||
|
import terminal1 from './terminal'
|
||||||
|
import SshFile from '@/pages/ssh/ssh-file'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
terminal1,
|
||||||
|
SshFile
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeKey: '',
|
||||||
|
selectPanes: [],
|
||||||
|
treeList: [],
|
||||||
|
replaceFields: {
|
||||||
|
children: 'children',
|
||||||
|
title: 'name',
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
created() {
|
||||||
|
this.listData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
findItemById(list, id) {
|
||||||
|
// 每次进来使用find遍历一次
|
||||||
|
let res = list.find((item) => item.id == id)
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
return res
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (list[i].children instanceof Array && list[i].children.length > 0) {
|
||||||
|
res = this.findItemById(list[i].children, id)
|
||||||
|
|
||||||
|
if (res) return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 查询树
|
||||||
|
listData() {
|
||||||
|
getSshListTree().then((res) => {
|
||||||
|
if (res.code == 200 && res.data) {
|
||||||
|
this.treeList = res.data.children || []
|
||||||
|
try {
|
||||||
|
const cache = JSON.parse(localStorage.getItem('ssh-tabs-cache') || '{}')
|
||||||
|
const cacheIds = (cache.selectPanes || []).map((item) => item.id)
|
||||||
|
this.selectPanes =
|
||||||
|
cacheIds
|
||||||
|
.map((item) => {
|
||||||
|
return this.findItemById(this.treeList, item)
|
||||||
|
})
|
||||||
|
.filter((item) => item)
|
||||||
|
.map((item) => {
|
||||||
|
// 默认关闭
|
||||||
|
item.open = false
|
||||||
|
return item
|
||||||
|
}) || []
|
||||||
|
|
||||||
|
const activeKey = this.selectPanes.find((item) => item.id === cache.activeKey)
|
||||||
|
if (activeKey) {
|
||||||
|
this.activeKey = activeKey.id
|
||||||
|
} else if (this.selectPanes.length) {
|
||||||
|
this.activeKey = this.selectPanes[0].id
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 编辑 tabs
|
||||||
|
onEdit(targetKey, action) {
|
||||||
|
if (action === 'remove') {
|
||||||
|
this.selectPanes = this.selectPanes.filter((pane) => pane.id !== targetKey)
|
||||||
|
if (this.activeKey === targetKey) {
|
||||||
|
this.activeKey = this.selectPanes[0] && this.selectPanes[0].id
|
||||||
|
}
|
||||||
|
this.cache()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 切换
|
||||||
|
change() {
|
||||||
|
this.cache()
|
||||||
|
},
|
||||||
|
open(activeKey) {
|
||||||
|
this.selectPanes = this.selectPanes.map((item) => {
|
||||||
|
if (item.id === activeKey) {
|
||||||
|
item.open = true
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
},
|
||||||
|
select(selectedKeys, { node }) {
|
||||||
|
if (!node.dataRef.isLeaf) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const findPane = this.selectPanes.find((item) => item.id === node.dataRef.id)
|
||||||
|
if (findPane) {
|
||||||
|
this.activeKey = findPane.id
|
||||||
|
} else {
|
||||||
|
const data = { ...node.dataRef, open: true }
|
||||||
|
this.selectPanes.push(data)
|
||||||
|
this.activeKey = node.dataRef.id
|
||||||
|
}
|
||||||
|
this.cache()
|
||||||
|
},
|
||||||
|
cache() {
|
||||||
|
localStorage.setItem(
|
||||||
|
'ssh-tabs-cache',
|
||||||
|
JSON.stringify({
|
||||||
|
activeKey: this.activeKey,
|
||||||
|
selectPanes: this.selectPanes
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// 文件管理状态切换
|
||||||
|
changeFileVisible(activeKey, value) {
|
||||||
|
this.selectPanes = this.selectPanes.map((item) => {
|
||||||
|
if (item.id === activeKey) {
|
||||||
|
item.fileVisible = value
|
||||||
|
if (value && !item.openFile) {
|
||||||
|
item.openFile = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="full-content">
|
<div>
|
||||||
<template v-if="useSuggestions">
|
<template v-if="this.useSuggestions">
|
||||||
<a-result
|
<a-result
|
||||||
title="当前工作空间还没有SSH"
|
title="当前工作空间还没有SSH"
|
||||||
sub-title="请到【系统管理】-> 【资产管理】-> 【SSH管理】添加SSH,或者将已添加的SSH授权关联、分配到此工作空间"
|
sub-title="请到【系统管理】-> 【资产管理】-> 【SSH管理】添加SSH,或者将已添加的SSH授权关联、分配到此工作空间"
|
||||||
@ -23,19 +23,22 @@
|
|||||||
bordered
|
bordered
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
:row-selection="rowSelection"
|
:row-selection="rowSelection"
|
||||||
|
:scroll="{
|
||||||
|
x: 'max-content'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@pressEnter="loadData"
|
@pressEnter="loadData"
|
||||||
v-model="listQuery['%name%']"
|
v-model:value="listQuery['%name%']"
|
||||||
placeholder="ssh名称"
|
placeholder="ssh名称"
|
||||||
/>
|
/>
|
||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
option-filter-prop="children"
|
option-filter-prop="children"
|
||||||
v-model="listQuery.group"
|
v-model:value="listQuery.group"
|
||||||
allowClear
|
allowClear
|
||||||
placeholder="分组"
|
placeholder="分组"
|
||||||
class="search-input-item"
|
class="search-input-item"
|
||||||
@ -49,8 +52,9 @@
|
|||||||
<a-button type="primary" :disabled="!tableSelections || !tableSelections.length" @click="syncToWorkspaceShow"
|
<a-button type="primary" :disabled="!tableSelections || !tableSelections.length" @click="syncToWorkspaceShow"
|
||||||
>工作空间同步</a-button
|
>工作空间同步</a-button
|
||||||
>
|
>
|
||||||
|
<a-button type="primary" @click="toSshTabs">管理面板</a-button>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>
|
<template v-slot:title>
|
||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>关联节点数据是异步获取有一定时间延迟</li>
|
<li>关联节点数据是异步获取有一定时间延迟</li>
|
||||||
@ -59,167 +63,202 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<question-circle-filled />
|
<QuestionCircleOutlined />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip #tooltip slot-scope="text" :title="text"> {{ text }}</a-tooltip>
|
<template #bodyCell="{ column, text, record }">
|
||||||
<a-tooltip
|
<template v-if="column.tooltip">
|
||||||
#host
|
<a-tooltip :title="text"> {{ text }}</a-tooltip>
|
||||||
slot-scope="text, record"
|
|
||||||
:title="`${record.machineSsh && record.machineSsh.host}:${record.machineSsh && record.machineSsh.port}`"
|
|
||||||
>
|
|
||||||
{{ record.machineSsh && record.machineSsh.host }}:{{ record.machineSsh && record.machineSsh.port }}
|
|
||||||
</a-tooltip>
|
|
||||||
<template #status slot-scope="text, record">
|
|
||||||
<a-tooltip :title="record.machineSsh && record.machineSsh.statusMsg">
|
|
||||||
<a-tag :color="record.machineSsh && record.machineSsh.status === 1 ? 'green' : 'red'">{{
|
|
||||||
record.machineSsh && record.machineSsh.status === 1 ? '正常' : '无法连接'
|
|
||||||
}}</a-tag>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<a-popover title="系统信息" #osName slot-scope="text, record">
|
|
||||||
<template #content>
|
|
||||||
<p>系统名:{{ record.machineSsh && record.machineSsh.osName }}</p>
|
|
||||||
<p>系统版本:{{ record.machineSsh && record.machineSsh.osVersion }}</p>
|
|
||||||
<p>CPU型号:{{ record.machineSsh && record.machineSsh.osCpuIdentifierName }}</p>
|
|
||||||
<p>主机名:{{ record.machineSsh && record.machineSsh.hostName }}</p>
|
|
||||||
<p>开机时间:{{ formatDuration(record.machineSsh && record.machineSsh.osSystemUptime) }}</p>
|
|
||||||
</template>
|
</template>
|
||||||
{{ text || '未知' }}
|
<template v-else-if="column.dataIndex === 'host'">
|
||||||
</a-popover>
|
<a-tooltip
|
||||||
<a-tooltip
|
:title="`${record.machineSsh && record.machineSsh.host}:${record.machineSsh && record.machineSsh.port}`"
|
||||||
#osOccupyMemory
|
>
|
||||||
slot-scope="text, record"
|
{{ record.machineSsh && record.machineSsh.host }}:{{ record.machineSsh && record.machineSsh.port }}
|
||||||
placement="topLeft"
|
|
||||||
:title="`内存使用率:${formatPercent(
|
|
||||||
record.machineSsh && record.machineSsh.osOccupyMemory
|
|
||||||
)},总内存:${renderSize(record.machineSsh && record.machineSsh.osMoneyTotal)}`"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
>{{ formatPercent(record.machineSsh && record.machineSsh.osOccupyMemory) }}/{{
|
|
||||||
renderSize(record.machineSsh && record.machineSsh.osMoneyTotal)
|
|
||||||
}}</span
|
|
||||||
>
|
|
||||||
</a-tooltip>
|
|
||||||
|
|
||||||
<a-tooltip
|
|
||||||
#osOccupyCpu
|
|
||||||
slot-scope="text, record"
|
|
||||||
placement="topLeft"
|
|
||||||
:title="`CPU使用率:${formatPercent2Number(record.machineSsh && record.machineSsh.osOccupyCpu)}%,CPU数:${
|
|
||||||
record.machineSsh && record.machineSsh.osCpuCores
|
|
||||||
}`"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
>{{ (formatPercent2Number(record.machineSsh && record.machineSsh.osOccupyCpu) || '-') + '%' }} /
|
|
||||||
{{ record.machineSsh && record.machineSsh.osCpuCores }}</span
|
|
||||||
>
|
|
||||||
</a-tooltip>
|
|
||||||
|
|
||||||
<a-popover title="硬盘信息" #osMaxOccupyDisk slot-scope="text, record">
|
|
||||||
<template #content>
|
|
||||||
<p>硬盘总量:{{ renderSize(record.machineSsh && record.machineSsh.osMoneyTotal) }}</p>
|
|
||||||
<p>硬盘最大的使用率:{{ formatPercent(record.machineSsh && record.machineSsh.osMaxOccupyDisk) }}</p>
|
|
||||||
<p>使用率最大的分区:{{ record.machineSsh && record.machineSsh.osMaxOccupyDiskName }}</p>
|
|
||||||
</template>
|
|
||||||
<span
|
|
||||||
>{{ formatPercent(record.machineSsh && record.machineSsh.osMaxOccupyDisk) }} /
|
|
||||||
{{ renderSize(record.machineSsh && record.machineSsh.osMoneyTotal) }}</span
|
|
||||||
>
|
|
||||||
</a-popover>
|
|
||||||
|
|
||||||
<template #nodeId slot-scope="text, record">
|
|
||||||
<template v-if="record.linkNode">
|
|
||||||
<a-tooltip placement="topLeft" :title="`节点名称:${record.linkNode.name}`">
|
|
||||||
<a-button
|
|
||||||
size="small"
|
|
||||||
style="width: 90px; padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
|
||||||
type=""
|
|
||||||
@click="toNode(record.linkNode)"
|
|
||||||
>
|
|
||||||
{{ record.linkNode.name }}
|
|
||||||
</a-button>
|
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>-</template>
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('status')">
|
||||||
</template>
|
<a-tooltip :title="record.machineSsh && record.machineSsh.statusMsg">
|
||||||
<template #operation slot-scope="text, record">
|
<a-tag
|
||||||
<a-space>
|
:color="
|
||||||
<a-dropdown>
|
statusMap[record.machineSsh && record.machineSsh.status] &&
|
||||||
<a-button size="small" type="primary" @click="handleTerminal(record, false)">
|
statusMap[record.machineSsh && record.machineSsh.status].color
|
||||||
终端<down-outlined />
|
"
|
||||||
</a-button>
|
|
||||||
<template #overlay>
|
|
||||||
<a-menu>
|
|
||||||
<a-menu-item key="1">
|
|
||||||
<a-button size="small" type="primary" icon="fullscreen" @click="handleTerminal(record, true)"
|
|
||||||
>全屏终端</a-button
|
|
||||||
>
|
|
||||||
</a-menu-item>
|
|
||||||
<a-menu-item key="2">
|
|
||||||
<router-link
|
|
||||||
target="_blank"
|
|
||||||
:to="{ path: '/full-terminal', query: { id: record.id, wid: getWorkspaceId() } }"
|
|
||||||
>
|
|
||||||
<a-button size="small" type="primary" icon="fullscreen"> 新标签终端</a-button>
|
|
||||||
</router-link>
|
|
||||||
</a-menu-item>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</a-dropdown>
|
|
||||||
<template v-if="record.fileDirs">
|
|
||||||
<a-button size="small" type="primary" @click="handleFile(record)">文件</a-button>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-tooltip
|
|
||||||
placement="topLeft"
|
|
||||||
title="如果按钮不可用,请去资产管理 ssh 列表的关联中添加当前工作空间允许管理的授权文件夹"
|
|
||||||
>
|
>
|
||||||
<a-button size="small" type="primary" :disabled="true">文件</a-button>
|
{{
|
||||||
|
(statusMap[record.machineSsh && record.machineSsh.status] &&
|
||||||
|
statusMap[record.machineSsh && record.machineSsh.status].desc) ||
|
||||||
|
'未知'
|
||||||
|
}}
|
||||||
|
</a-tag>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('osName')">
|
||||||
|
<a-popover title="系统信息">
|
||||||
|
<template v-slot:content>
|
||||||
|
<p>系统名:{{ record.machineSsh && record.machineSsh.osName }}</p>
|
||||||
|
<p>系统版本:{{ record.machineSsh && record.machineSsh.osVersion }}</p>
|
||||||
|
<p>CPU型号:{{ record.machineSsh && record.machineSsh.osCpuIdentifierName }}</p>
|
||||||
|
<p>主机名:{{ record.machineSsh && record.machineSsh.hostName }}</p>
|
||||||
|
<p>开机时间:{{ formatDuration(record.machineSsh && record.machineSsh.osSystemUptime) }}</p>
|
||||||
|
</template>
|
||||||
|
{{ text || '未知' }}
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('osOccupyMemory')">
|
||||||
|
<a-tooltip
|
||||||
|
placement="topLeft"
|
||||||
|
:title="`内存使用率:${formatPercent(
|
||||||
|
record.machineSsh && record.machineSsh.osOccupyMemory
|
||||||
|
)},总内存:${renderSize(record.machineSsh && record.machineSsh.osMoneyTotal)}`"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
>{{ formatPercent(record.machineSsh && record.machineSsh.osOccupyMemory) }}/{{
|
||||||
|
renderSize(record.machineSsh && record.machineSsh.osMoneyTotal)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('osOccupyCpu')">
|
||||||
|
<a-tooltip
|
||||||
|
placement="topLeft"
|
||||||
|
:title="`CPU使用率:${formatPercent2Number(record.machineSsh && record.machineSsh.osOccupyCpu)}%,CPU数:${
|
||||||
|
record.machineSsh && record.machineSsh.osCpuCores
|
||||||
|
}`"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
>{{ (formatPercent2Number(record.machineSsh && record.machineSsh.osOccupyCpu) || '-') + '%' }} /
|
||||||
|
{{ record.machineSsh && record.machineSsh.osCpuCores }}</span
|
||||||
|
>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex instanceof Array && column.dataIndex.includes('osMaxOccupyDisk')">
|
||||||
|
<a-popover title="硬盘信息">
|
||||||
|
<template v-slot:content>
|
||||||
|
<p>内存总量:{{ renderSize(record.machineSsh && record.machineSsh.osMoneyTotal) }}</p>
|
||||||
|
<p>硬盘最大的使用率:{{ formatPercent(record.machineSsh && record.machineSsh.osMaxOccupyDisk) }}</p>
|
||||||
|
<p>使用率最大的分区:{{ record.machineSsh && record.machineSsh.osMaxOccupyDiskName }}</p>
|
||||||
|
</template>
|
||||||
|
<span
|
||||||
|
>{{ formatPercent(record.machineSsh && record.machineSsh.osMaxOccupyDisk) }}
|
||||||
|
/
|
||||||
|
{{ renderSize(record.machineSsh && record.machineSsh.osMoneyTotal) }}</span
|
||||||
|
>
|
||||||
|
</a-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="column.dataIndex === 'nodeId'">
|
||||||
|
<template v-if="record.linkNode">
|
||||||
|
<a-tooltip placement="topLeft" :title="`节点名称:${record.linkNode.name}`">
|
||||||
|
<a-button
|
||||||
|
size="small"
|
||||||
|
style="width: 90px; padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
|
||||||
|
type="link"
|
||||||
|
@click="toNode(record.linkNode)"
|
||||||
|
>
|
||||||
|
{{ record.linkNode.name }}
|
||||||
|
</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else>-</template>
|
||||||
<a-dropdown>
|
</template>
|
||||||
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()">
|
<template v-else-if="column.dataIndex === 'operation'">
|
||||||
更多
|
<a-space>
|
||||||
<down-outlined />
|
<a-dropdown>
|
||||||
</a>
|
<a-button size="small" type="primary" @click="handleTerminal(record, false)"
|
||||||
<template #overlay>
|
>终端<DownOutlined
|
||||||
<a-menu>
|
/></a-button>
|
||||||
<a-menu-item>
|
<template v-slot:overlay>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
<a-menu>
|
||||||
</a-menu-item>
|
<a-menu-item key="1">
|
||||||
<a-menu-item>
|
<a-button size="small" type="primary" @click="handleTerminal(record, true)"
|
||||||
<a-button size="small" type="danger" @click="handleDelete(record)">删除</a-button>
|
><FullscreenOutlined />全屏终端</a-button
|
||||||
</a-menu-item>
|
>
|
||||||
<a-menu-item>
|
</a-menu-item>
|
||||||
<a-button size="small" type="primary" @click="handleViewLog(record)">终端日志</a-button>
|
<a-menu-item key="2">
|
||||||
</a-menu-item>
|
<router-link
|
||||||
</a-menu>
|
target="_blank"
|
||||||
|
:to="{
|
||||||
|
path: '/full-terminal',
|
||||||
|
query: { id: record.id, wid: getWorkspaceId() }
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<a-button size="small" type="primary"> <FullscreenOutlined />新标签终端</a-button>
|
||||||
|
</router-link>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
<template v-if="record.fileDirs">
|
||||||
|
<a-button size="small" type="primary" @click="handleFile(record)">文件</a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
<template v-else>
|
||||||
</a-space>
|
<a-tooltip
|
||||||
|
placement="topLeft"
|
||||||
|
title="如果按钮不可用,请去资产管理 ssh 列表的关联中添加当前工作空间允许管理的授权文件夹"
|
||||||
|
>
|
||||||
|
<a-button size="small" type="primary" :disabled="true">文件</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-dropdown>
|
||||||
|
<a @click="(e) => e.preventDefault()">
|
||||||
|
更多
|
||||||
|
<DownOutlined />
|
||||||
|
</a>
|
||||||
|
<template v-slot:overlay>
|
||||||
|
<a-menu>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-button size="small" type="primary" danger @click="handleDelete(record)">删除</a-button>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item>
|
||||||
|
<a-button size="small" type="primary" @click="handleViewLog(record)">终端日志</a-button>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
<!-- 编辑区 -->
|
<!-- 编辑区 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="editSshVisible"
|
v-model:open="editSshVisible"
|
||||||
width="600px"
|
width="600px"
|
||||||
title="编辑 SSH"
|
title="编辑 SSH"
|
||||||
@ok="handleEditSshOk"
|
@ok="handleEditSshOk"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
>
|
>
|
||||||
<a-form ref="editSshForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form ref="editSshForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
|
<template v-if="this.getUserInfo && this.getUserInfo.systemUser">
|
||||||
|
<a-alert type="info" show-icon style="width: 100%; margin-bottom: 10px">
|
||||||
|
<template v-slot:message>
|
||||||
|
<ul>
|
||||||
|
<li>此编辑仅能编辑当前 SSH 在此工作空间的名称信息</li>
|
||||||
|
<li>如果要配置 SSH 请到【系统管理】-> 【资产管理】-> 【SSH 管理】中去配置。</li>
|
||||||
|
<li>
|
||||||
|
当前 SSH 的授权目录(文件目录、文件后缀、禁止命令)需要请到 【系统管理】-> 【资产管理】-> 【SSH
|
||||||
|
管理】-> 操作栏中->关联按钮->对应工作空间->操作栏中->配置按钮
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
</template>
|
||||||
<a-form-item label="SSH 名称" name="name">
|
<a-form-item label="SSH 名称" name="name">
|
||||||
<a-input v-model="temp.name" :maxLength="50" placeholder="SSH 名称" />
|
<a-input v-model:value="temp.name" :maxLength="50" placeholder="SSH 名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="分组名称" name="group">
|
<a-form-item label="分组名称" name="group">
|
||||||
<custom-select
|
<custom-select
|
||||||
v-model="temp.group"
|
v-model:value="temp.group"
|
||||||
:data="groupList"
|
:data="groupList"
|
||||||
suffixIcon=""
|
|
||||||
inputPlaceholder="添加分组"
|
inputPlaceholder="添加分组"
|
||||||
selectPlaceholder="选择分组名"
|
selectPlaceholder="选择分组名"
|
||||||
>
|
>
|
||||||
@ -231,7 +270,7 @@
|
|||||||
<!-- 文件管理 -->
|
<!-- 文件管理 -->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:visible="drawerVisible"
|
:open="drawerVisible"
|
||||||
@close="
|
@close="
|
||||||
() => {
|
() => {
|
||||||
this.drawerVisible = false
|
this.drawerVisible = false
|
||||||
@ -246,29 +285,31 @@
|
|||||||
<!-- Terminal -->
|
<!-- Terminal -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
:dialogStyle="{
|
:style="{
|
||||||
maxWidth: '100vw',
|
maxWidth: '100vw',
|
||||||
top: this.terminalFullscreen ? 0 : false,
|
top: this.terminalFullscreen ? 0 : false,
|
||||||
paddingBottom: 0
|
paddingBottom: 0
|
||||||
}"
|
}"
|
||||||
:width="terminalFullscreen ? '100vw' : '80vw'"
|
:width="this.terminalFullscreen ? '100vw' : '80vw'"
|
||||||
:bodyStyle="{
|
:bodyStyle="{
|
||||||
padding: '0 10px',
|
padding: '0 5px',
|
||||||
paddingTop: '10px',
|
paddingTop: '10px',
|
||||||
marginRight: '10px',
|
marginRight: '10px',
|
||||||
height: `${this.terminalFullscreen ? 'calc(100vh - 56px)' : '70vh'}`
|
height: `${this.terminalFullscreen ? 'calc(100vh - 80px)' : '70vh'}`
|
||||||
}"
|
}"
|
||||||
v-model="terminalVisible"
|
v-model:open="terminalVisible"
|
||||||
:title="temp.name"
|
:title="temp.name"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<terminal v-if="terminalVisible" :sshId="temp.id" />
|
<div :style="`height: ${this.terminalFullscreen ? 'calc(100vh - 70px - 20px)' : 'calc(70vh - 20px)'}`">
|
||||||
|
<terminal1 v-if="terminalVisible" :sshId="temp.id" />
|
||||||
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 操作日志 -->
|
<!-- 操作日志 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="viewOperationLog"
|
v-model:open="viewOperationLog"
|
||||||
title="操作日志"
|
title="操作日志"
|
||||||
width="80vw"
|
width="80vw"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -279,13 +320,14 @@
|
|||||||
<!-- 同步到其他工作空间 -->
|
<!-- 同步到其他工作空间 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
v-model="syncToWorkspaceVisible"
|
v-model:open="syncToWorkspaceVisible"
|
||||||
title="同步到其他工作空间"
|
title="同步到其他工作空间"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
@ok="handleSyncToWorkspace"
|
@ok="handleSyncToWorkspace"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
>
|
>
|
||||||
<a-alert message="温馨提示" type="warning">
|
<a-alert message="温馨提示" type="warning" show-icon>
|
||||||
<template #description>
|
<template v-slot:description>
|
||||||
<ul>
|
<ul>
|
||||||
<li>同步机制采用 IP+PORT+连接方式 确定是同一个服务器</li>
|
<li>同步机制采用 IP+PORT+连接方式 确定是同一个服务器</li>
|
||||||
<li>当目标工作空间不存在对应的 SSH 时候将自动创建一个新的 SSH</li>
|
<li>当目标工作空间不存在对应的 SSH 时候将自动创建一个新的 SSH</li>
|
||||||
@ -296,7 +338,12 @@
|
|||||||
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item> </a-form-item>
|
<a-form-item> </a-form-item>
|
||||||
<a-form-item label="选择工作空间" name="workspaceId">
|
<a-form-item label="选择工作空间" name="workspaceId">
|
||||||
<a-select show-search option-filter-prop="children" v-model="temp.workspaceId" placeholder="请选择工作空间">
|
<a-select
|
||||||
|
show-search
|
||||||
|
option-filter-prop="children"
|
||||||
|
v-model:value="temp.workspaceId"
|
||||||
|
placeholder="请选择工作空间"
|
||||||
|
>
|
||||||
<a-select-option :disabled="getWorkspaceId() === item.id" v-for="item in workspaceList" :key="item.id">{{
|
<a-select-option :disabled="getWorkspaceId() === item.id" v-for="item in workspaceList" :key="item.id">{{
|
||||||
item.name
|
item.name
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
@ -306,10 +353,12 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { deleteSsh, editSsh, getSshList, syncToWorkspace, getSshGroupAll } from '@/api/ssh'
|
import { deleteSsh, editSsh, getSshList, syncToWorkspace, getSshGroupAll } from '@/api/ssh'
|
||||||
|
import { statusMap } from '@/api/system/assets-ssh'
|
||||||
import SshFile from '@/pages/ssh/ssh-file'
|
import SshFile from '@/pages/ssh/ssh-file'
|
||||||
import Terminal from '@/pages/ssh/terminal'
|
import Terminal1 from '@/pages/ssh/terminal'
|
||||||
import {
|
import {
|
||||||
CHANGE_PAGE,
|
CHANGE_PAGE,
|
||||||
COMPUTED_PAGINATION,
|
COMPUTED_PAGINATION,
|
||||||
@ -323,13 +372,15 @@ import {
|
|||||||
import { getWorkSpaceListAll } from '@/api/workspace'
|
import { getWorkSpaceListAll } from '@/api/workspace'
|
||||||
|
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { useAppStore } from '@/stores/app'
|
||||||
import OperationLog from '@/pages/system/assets/ssh/operation-log'
|
import OperationLog from '@/pages/system/assets/ssh/operation-log'
|
||||||
import CustomSelect from '@/components/customSelect'
|
import CustomSelect from '@/components/customSelect'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SshFile,
|
SshFile,
|
||||||
Terminal,
|
Terminal1,
|
||||||
OperationLog,
|
OperationLog,
|
||||||
CustomSelect
|
CustomSelect
|
||||||
},
|
},
|
||||||
@ -346,9 +397,7 @@ export default {
|
|||||||
workspaceList: [],
|
workspaceList: [],
|
||||||
tempNode: {},
|
tempNode: {},
|
||||||
// fileList: [],
|
// fileList: [],
|
||||||
sshAgentInfo: {},
|
statusMap,
|
||||||
agentData: {},
|
|
||||||
formLoading: false,
|
|
||||||
|
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
terminalVisible: false,
|
terminalVisible: false,
|
||||||
@ -362,50 +411,47 @@ export default {
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
tooltip: true
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: 'Host',
|
title: 'Host',
|
||||||
dataIndex: 'machineSsh.host',
|
dataIndex: ['machineSsh', 'host'],
|
||||||
width: 100,
|
width: 100,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'host' }
|
|
||||||
},
|
},
|
||||||
// { title: "Port", dataIndex: "machineSsh.port", sorter: true, width: 80, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
// { title: "Port", dataIndex: "machineSsh.port", sorter: true, width: 80, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{
|
{
|
||||||
title: '用户名',
|
title: '用户名',
|
||||||
dataIndex: 'machineSsh.user',
|
dataIndex: ['machineSsh', 'user'],
|
||||||
width: '100px',
|
width: '100px',
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: '系统名',
|
title: '系统名',
|
||||||
dataIndex: 'machineSsh.osName',
|
dataIndex: ['machineSsh', 'osName'],
|
||||||
width: 80,
|
width: 80,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'osName' }
|
|
||||||
},
|
},
|
||||||
// { title: "系统版本", dataIndex: "machineSsh.osVersion", sorter: true, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
// { title: "系统版本", dataIndex: "machineSsh.osVersion", sorter: true, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{
|
{
|
||||||
title: 'CPU',
|
title: 'CPU',
|
||||||
dataIndex: 'machineSsh.osOccupyCpu',
|
dataIndex: ['machineSsh', 'osOccupyCpu'],
|
||||||
width: 80,
|
width: 80,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'osOccupyCpu' }
|
// scopedSlots: { customRender: 'osOccupyCpu' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '内存',
|
title: '内存',
|
||||||
dataIndex: 'machineSsh.osOccupyMemory',
|
dataIndex: ['machineSsh', 'osOccupyMemory'],
|
||||||
width: 80,
|
width: 80,
|
||||||
ellipsis: true,
|
ellipsis: true
|
||||||
scopedSlots: { customRender: 'osOccupyMemory' }
|
// scopedSlots: { customRender: 'osOccupyMemory' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '硬盘',
|
title: '硬盘',
|
||||||
dataIndex: 'machineSsh.osMaxOccupyDisk',
|
dataIndex: ['machineSsh', 'osMaxOccupyDisk'],
|
||||||
width: 80,
|
width: 80,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: 'osMaxOccupyDisk' }
|
scopedSlots: { customRender: 'osMaxOccupyDisk' }
|
||||||
@ -413,17 +459,16 @@ export default {
|
|||||||
// { title: "编码格式", dataIndex: "charset", sorter: true, width: 120, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
// { title: "编码格式", dataIndex: "charset", sorter: true, width: 120, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{
|
{
|
||||||
title: '连接状态',
|
title: '连接状态',
|
||||||
dataIndex: 'machineSsh.status',
|
dataIndex: ['machineSsh', 'status'],
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: '90px',
|
width: '90px'
|
||||||
scopedSlots: { customRender: 'status' }
|
|
||||||
},
|
},
|
||||||
// { title: "编码格式", dataIndex: "machineSsh.charset", sorter: true, width: 120, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
// { title: "编码格式", dataIndex: "machineSsh.charset", sorter: true, width: 120, ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{
|
{
|
||||||
title: '关联节点',
|
title: '关联节点',
|
||||||
dataIndex: 'nodeId',
|
dataIndex: 'nodeId',
|
||||||
scopedSlots: { customRender: 'nodeId' },
|
|
||||||
width: '100px',
|
width: '100px',
|
||||||
ellipsis: true
|
ellipsis: true
|
||||||
},
|
},
|
||||||
@ -432,7 +477,7 @@ export default {
|
|||||||
dataIndex: 'createTimeMillis',
|
dataIndex: 'createTimeMillis',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -440,13 +485,13 @@ export default {
|
|||||||
dataIndex: 'modifyTimeMillis',
|
dataIndex: 'modifyTimeMillis',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: (text) => parseTime(text),
|
customRender: ({ text }) => parseTime(text),
|
||||||
width: '170px'
|
width: '170px'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
scopedSlots: { customRender: 'operation' },
|
|
||||||
width: '200px',
|
width: '200px',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
// ellipsis: true,
|
// ellipsis: true,
|
||||||
@ -459,12 +504,13 @@ export default {
|
|||||||
name: [{ required: true, message: '请输入 SSH 名称', trigger: 'blur' }]
|
name: [{ required: true, message: '请输入 SSH 名称', trigger: 'blur' }]
|
||||||
},
|
},
|
||||||
|
|
||||||
groupList: []
|
groupList: [],
|
||||||
|
confirmLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getWorkspaceId', 'getUserInfo']),
|
...mapState(useUserStore, ['getUserInfo']),
|
||||||
|
...mapState(useAppStore, ['getWorkspaceId']),
|
||||||
pagination() {
|
pagination() {
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
return COMPUTED_PAGINATION(this.listQuery)
|
||||||
},
|
},
|
||||||
@ -537,23 +583,25 @@ export default {
|
|||||||
// 提交 SSH 数据
|
// 提交 SSH 数据
|
||||||
handleEditSshOk() {
|
handleEditSshOk() {
|
||||||
// 检验表单
|
// 检验表单
|
||||||
this.$refs['editSshForm'].validate((valid) => {
|
this.$refs['editSshForm'].validate().then(() => {
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// 提交数据
|
// 提交数据
|
||||||
editSsh(this.temp).then((res) => {
|
this.confirmLoading = true
|
||||||
if (res.code === 200) {
|
editSsh(this.temp)
|
||||||
$notification.success({
|
.then((res) => {
|
||||||
message: res.msg
|
if (res.code === 200) {
|
||||||
})
|
this.$notification.success({
|
||||||
//this.$refs['editSshForm'].resetFields();
|
message: res.msg
|
||||||
// this.fileList = [];
|
})
|
||||||
this.editSshVisible = false
|
//this.$refs['editSshForm'].resetFields();
|
||||||
this.loadData()
|
// this.fileList = [];
|
||||||
this.loadGroupList()
|
this.editSshVisible = false
|
||||||
}
|
this.loadData()
|
||||||
})
|
this.loadGroupList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 进入终端
|
// 进入终端
|
||||||
@ -576,8 +624,9 @@ export default {
|
|||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
$confirm({
|
this.$confirm({
|
||||||
title: '系统提示',
|
title: '系统提示',
|
||||||
|
zIndex: 1009,
|
||||||
content: '真的要删除 SSH 么?',
|
content: '真的要删除 SSH 么?',
|
||||||
okText: '确认',
|
okText: '确认',
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
@ -585,7 +634,7 @@ export default {
|
|||||||
// 删除
|
// 删除
|
||||||
deleteSsh(record.id).then((res) => {
|
deleteSsh(record.id).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg
|
message: res.msg
|
||||||
})
|
})
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@ -597,7 +646,6 @@ export default {
|
|||||||
// 前往节点
|
// 前往节点
|
||||||
toNode(node) {
|
toNode(node) {
|
||||||
const newpage = this.$router.resolve({
|
const newpage = this.$router.resolve({
|
||||||
name: 'node_' + node.id,
|
|
||||||
path: '/node/list',
|
path: '/node/list',
|
||||||
query: {
|
query: {
|
||||||
...this.$route.query,
|
...this.$route.query,
|
||||||
@ -618,7 +666,15 @@ export default {
|
|||||||
// },
|
// },
|
||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
|
toSshTabs() {
|
||||||
|
const newpage = this.$router.resolve({
|
||||||
|
path: '/ssh-tabs',
|
||||||
|
query: {
|
||||||
|
wid: this.getWorkspaceId()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
window.open(newpage.href, '_blank')
|
||||||
|
},
|
||||||
// 分页、排序、筛选变化时触发
|
// 分页、排序、筛选变化时触发
|
||||||
changePage(pagination, filters, sorter) {
|
changePage(pagination, filters, sorter) {
|
||||||
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter })
|
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter })
|
||||||
@ -644,27 +700,31 @@ export default {
|
|||||||
//
|
//
|
||||||
handleSyncToWorkspace() {
|
handleSyncToWorkspace() {
|
||||||
if (!this.temp.workspaceId) {
|
if (!this.temp.workspaceId) {
|
||||||
$notification.warn({
|
this.$notification.warn({
|
||||||
message: '请选择工作空间'
|
message: '请选择工作空间'
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 同步
|
// 同步
|
||||||
|
this.confirmLoading = true
|
||||||
syncToWorkspace({
|
syncToWorkspace({
|
||||||
ids: this.tableSelections.join(','),
|
ids: this.tableSelections.join(','),
|
||||||
toWorkspaceId: this.temp.workspaceId
|
toWorkspaceId: this.temp.workspaceId
|
||||||
}).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
this.tableSelections = []
|
|
||||||
this.syncToWorkspaceVisible = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
this.$notification.success({
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
this.tableSelections = []
|
||||||
|
this.syncToWorkspaceVisible = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,345 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<a-table
|
|
||||||
:data-source="list"
|
|
||||||
size="middle"
|
|
||||||
:loading="loading"
|
|
||||||
:columns="columns"
|
|
||||||
:pagination="pagination"
|
|
||||||
@change="
|
|
||||||
(pagination, filters, sorter) => {
|
|
||||||
this.listQuery = CHANGE_PAGE(this.listQuery, { pagination, sorter })
|
|
||||||
this.loadData()
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:row-selection="rowSelection"
|
|
||||||
bordered
|
|
||||||
rowKey="id"
|
|
||||||
>
|
|
||||||
<template v-slot:title>
|
|
||||||
<a-space>
|
|
||||||
<a-space>
|
|
||||||
<a-input
|
|
||||||
allowClear
|
|
||||||
class="search-input-item"
|
|
||||||
@pressEnter="loadData"
|
|
||||||
v-model:value="listQuery['%issuerDnName%']"
|
|
||||||
placeholder="颁发者"
|
|
||||||
/>
|
|
||||||
<a-input
|
|
||||||
allowClear
|
|
||||||
class="search-input-item"
|
|
||||||
@pressEnter="loadData"
|
|
||||||
v-model:value="listQuery['%subjectDnName%']"
|
|
||||||
placeholder="主题"
|
|
||||||
/>
|
|
||||||
<a-tooltip title="按住 Ctr 或者 Alt/Option 键点击按钮快速回到第一页">
|
|
||||||
<a-button type="primary" :loading="loading" @click="loadData">搜索</a-button>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-button type="primary" @click="handleAdd">导入证书</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<template v-slot:tooltip="text">
|
|
||||||
<a-tooltip placement="topLeft" :title="text">
|
|
||||||
<span>{{ text }}</span>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
<template v-slot:name="text, item">
|
|
||||||
<a-popover title="证书描述">
|
|
||||||
<template v-slot:content>
|
|
||||||
<p>描述:{{ item.description }}</p>
|
|
||||||
</template>
|
|
||||||
<!-- {{ text }} -->
|
|
||||||
{{ text }}
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
|
||||||
<template v-slot:fileExists="text">
|
|
||||||
<a-tag v-if="text" color="green">存在</a-tag>
|
|
||||||
<a-tag v-else color="red">丢失</a-tag>
|
|
||||||
</template>
|
|
||||||
<template v-slot:global="text">
|
|
||||||
<a-tag v-if="text === 'GLOBAL'">全局</a-tag>
|
|
||||||
<a-tag v-else>工作空间</a-tag>
|
|
||||||
</template>
|
|
||||||
</a-table>
|
|
||||||
<!-- 导入 -->
|
|
||||||
<a-modal
|
|
||||||
destroyOnClose
|
|
||||||
:zIndex="1009"
|
|
||||||
v-model:value="editCertVisible"
|
|
||||||
width="700px"
|
|
||||||
title="导入证书"
|
|
||||||
@ok="handleEditCertOk"
|
|
||||||
:maskClosable="false"
|
|
||||||
>
|
|
||||||
<a-form ref="importCertForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
|
||||||
<a-form-item
|
|
||||||
label="证书文件"
|
|
||||||
name="file"
|
|
||||||
help="请上传 zip 压缩包,并且包里面必须包含:ca.pem、key.pem、cert.pem 三个文件"
|
|
||||||
>
|
|
||||||
<a-upload
|
|
||||||
:file-list="uploadFileList"
|
|
||||||
:remove="
|
|
||||||
() => {
|
|
||||||
uploadFileList = []
|
|
||||||
}
|
|
||||||
"
|
|
||||||
:before-upload="
|
|
||||||
(file) => {
|
|
||||||
this.uploadFileList = [file]
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
"
|
|
||||||
accept=".zip"
|
|
||||||
>
|
|
||||||
<a-button><a-icon type="upload" />选择文件</a-button>
|
|
||||||
</a-upload>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-modal>
|
|
||||||
<div style="padding: 40px">
|
|
||||||
<div
|
|
||||||
:style="{
|
|
||||||
position: 'absolute',
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
width: '100%',
|
|
||||||
borderTop: '1px solid #e9e9e9',
|
|
||||||
padding: '10px 16px',
|
|
||||||
background: '#fff',
|
|
||||||
textAlign: 'right',
|
|
||||||
zIndex: 1
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<a-space>
|
|
||||||
<a-button
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
this.$emit('cancel')
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
取消
|
|
||||||
</a-button>
|
|
||||||
<a-button type="primary" @click="handerConfirm"> 确定 </a-button>
|
|
||||||
</a-space>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { dockerImportTls } from '@/api/system/assets-docker'
|
|
||||||
import { certListAll } from '@/api/tools/certificate'
|
|
||||||
import { parseTime, CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY } from '@/utils/const'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
|
|
||||||
|
|
||||||
list: [],
|
|
||||||
uploadFileList: [],
|
|
||||||
|
|
||||||
temp: {},
|
|
||||||
editCertVisible: false,
|
|
||||||
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
title: '序列号 (SN)',
|
|
||||||
dataIndex: 'serialNumberStr',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 150,
|
|
||||||
scopedSlots: { customRender: 'name' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '证书类型',
|
|
||||||
dataIndex: 'keyType',
|
|
||||||
ellipsis: true,
|
|
||||||
width: '80px',
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '文件状态',
|
|
||||||
dataIndex: 'fileExists',
|
|
||||||
ellipsis: true,
|
|
||||||
scopedSlots: { customRender: 'fileExists' },
|
|
||||||
width: '80px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '共享',
|
|
||||||
dataIndex: 'workspaceId',
|
|
||||||
ellipsis: true,
|
|
||||||
scopedSlots: { customRender: 'global' },
|
|
||||||
width: '90px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '颁发者',
|
|
||||||
dataIndex: 'issuerDnName',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 200,
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '主题',
|
|
||||||
dataIndex: 'subjectDnName',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 150,
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '密钥算法',
|
|
||||||
dataIndex: 'sigAlgName',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 150,
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '算法 OID',
|
|
||||||
dataIndex: 'sigAlgOid',
|
|
||||||
ellipsis: true,
|
|
||||||
width: 150,
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: '生效时间',
|
|
||||||
dataIndex: 'effectiveTime',
|
|
||||||
customRender: (text) => parseTime(text),
|
|
||||||
sorter: true,
|
|
||||||
width: '160px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '到期时间',
|
|
||||||
dataIndex: 'expirationTime',
|
|
||||||
sorter: true,
|
|
||||||
customRender: (text) => parseTime(text),
|
|
||||||
width: '160px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '版本号',
|
|
||||||
dataIndex: 'certVersion',
|
|
||||||
ellipsis: true,
|
|
||||||
width: '80px',
|
|
||||||
scopedSlots: { customRender: 'tooltip' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '创建人',
|
|
||||||
dataIndex: 'createUser',
|
|
||||||
ellipsis: true,
|
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: '120px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '修改人',
|
|
||||||
dataIndex: 'modifyUser',
|
|
||||||
ellipsis: true,
|
|
||||||
scopedSlots: { customRender: 'modifyUser' },
|
|
||||||
width: '120px'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '创建时间',
|
|
||||||
dataIndex: 'createTimeMillis',
|
|
||||||
sorter: true,
|
|
||||||
ellipsis: true,
|
|
||||||
customRender: (text) => parseTime(text),
|
|
||||||
width: '160px'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
rules: {},
|
|
||||||
tableSelections: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
pagination() {
|
|
||||||
return COMPUTED_PAGINATION(this.listQuery)
|
|
||||||
},
|
|
||||||
rowSelection() {
|
|
||||||
return {
|
|
||||||
onChange: (selectedRowKeys) => {
|
|
||||||
this.tableSelections = selectedRowKeys
|
|
||||||
},
|
|
||||||
selectedRowKeys: this.tableSelections,
|
|
||||||
type: 'radio'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.loadData()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
CHANGE_PAGE,
|
|
||||||
// 加载数据
|
|
||||||
loadData(pointerEvent) {
|
|
||||||
this.loading = true
|
|
||||||
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page
|
|
||||||
this.loading = true
|
|
||||||
certListAll(this.listQuery).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.list = res.data.result
|
|
||||||
this.listQuery.total = res.data.total
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 添加
|
|
||||||
handleAdd() {
|
|
||||||
this.editCertVisible = true
|
|
||||||
this.uploadFileList = []
|
|
||||||
this.$refs['importCertForm']?.resetFields()
|
|
||||||
},
|
|
||||||
|
|
||||||
// 提交 Cert 数据
|
|
||||||
handleEditCertOk() {
|
|
||||||
// 检验表单
|
|
||||||
this.$refs['importCertForm'].validate((valid) => {
|
|
||||||
if (!valid) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (this.uploadFileList.length === 0) {
|
|
||||||
this.$notification.error({
|
|
||||||
message: '请选择证书文件'
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const formData = new FormData()
|
|
||||||
formData.append('file', this.uploadFileList[0])
|
|
||||||
|
|
||||||
// 提交数据
|
|
||||||
dockerImportTls(formData).then((res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
// 成功
|
|
||||||
this.$notification.success({
|
|
||||||
message: res.msg
|
|
||||||
})
|
|
||||||
|
|
||||||
this.editCertVisible = false
|
|
||||||
this.loadData()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 确认
|
|
||||||
handerConfirm() {
|
|
||||||
if (!this.tableSelections.length) {
|
|
||||||
this.$notification.warning({
|
|
||||||
message: '请选择要使用的证书'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const selectData = this.list.filter((item) => {
|
|
||||||
return item.id === this.tableSelections[0]
|
|
||||||
})[0]
|
|
||||||
|
|
||||||
$emit(this, 'confirm', `${selectData.serialNumberStr}:${selectData.keyType}`)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emits: ['cancel', 'confirm']
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -468,9 +468,11 @@
|
|||||||
this.certificateVisible = false
|
this.certificateVisible = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
>
|
>
|
||||||
<certificate
|
<certificate
|
||||||
v-if="certificateVisible"
|
v-if="certificateVisible"
|
||||||
|
ref="certificate"
|
||||||
@confirm="
|
@confirm="
|
||||||
(certInfo) => {
|
(certInfo) => {
|
||||||
this.temp = { ...this.temp, certInfo: certInfo }
|
this.temp = { ...this.temp, certInfo: certInfo }
|
||||||
@ -483,6 +485,29 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
></certificate>
|
></certificate>
|
||||||
|
<template #footer>
|
||||||
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.chooseVisible = 0
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
this.$refs['certificate'].handerConfirm()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -507,7 +532,7 @@ import { getWorkSpaceListAll } from '@/api/workspace'
|
|||||||
import Console from '@/pages/docker/console'
|
import Console from '@/pages/docker/console'
|
||||||
import SwarmConsole from '@/pages/docker/swarm/console.vue'
|
import SwarmConsole from '@/pages/docker/swarm/console.vue'
|
||||||
|
|
||||||
import certificate from './certificate.vue'
|
import certificate from '@/pages/certificate/list.vue'
|
||||||
import CustomSelect from '@/components/customSelect'
|
import CustomSelect from '@/components/customSelect'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -134,6 +134,11 @@ const children = [
|
|||||||
name: 'file-storage-release-task',
|
name: 'file-storage-release-task',
|
||||||
component: () => import('../pages/file-manager/release-task/list.vue')
|
component: () => import('../pages/file-manager/release-task/list.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/file-manager/static-file-storage',
|
||||||
|
name: 'static-file-storage',
|
||||||
|
component: () => import('../pages/file-manager/staticFileStorage/list.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/certificate/list',
|
path: '/certificate/list',
|
||||||
name: '/certificate-list',
|
name: '/certificate-list',
|
||||||
@ -160,7 +165,7 @@ const management = [
|
|||||||
{
|
{
|
||||||
path: '/system/assets/repository-list',
|
path: '/system/assets/repository-list',
|
||||||
name: 'system-global-repository',
|
name: 'system-global-repository',
|
||||||
component: () => import('../pages/repository/global-repository')
|
component: () => import('../pages/repository/global-repository.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/user/permission-group',
|
path: '/user/permission-group',
|
||||||
@ -277,6 +282,11 @@ const router = createRouter({
|
|||||||
name: 'full-terminal',
|
name: 'full-terminal',
|
||||||
component: () => import('../pages/ssh/full-terminal.vue')
|
component: () => import('../pages/ssh/full-terminal.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/ssh-tabs',
|
||||||
|
name: 'ssh-tabs',
|
||||||
|
component: () => import('../pages/ssh/ssh-tabs.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/*',
|
path: '/*',
|
||||||
name: '404',
|
name: '404',
|
||||||
|
Loading…
Reference in New Issue
Block a user