This commit is contained in:
ann 2023-05-26 10:39:47 +08:00
parent 32aaa2c3f0
commit 7354dcb715
15 changed files with 785 additions and 88 deletions

11
package-lock.json generated
View File

@ -40,6 +40,7 @@
"screenfull": "4.2.0",
"script-loader": "0.7.2",
"sortablejs": "1.8.4",
"spark-md5": "^3.0.2",
"three": "^0.126.1",
"three.meshline": "^1.4.0",
"vue": "2.6.10",
@ -20210,6 +20211,11 @@
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
"deprecated": "See https://github.com/lydell/source-map-url#deprecated"
},
"node_modules/spark-md5": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz",
"integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="
},
"node_modules/spdx-correct": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
@ -40088,6 +40094,11 @@
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
},
"spark-md5": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz",
"integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="
},
"spdx-correct": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",

View File

@ -46,6 +46,7 @@
"screenfull": "4.2.0",
"script-loader": "0.7.2",
"sortablejs": "1.8.4",
"spark-md5": "^3.0.2",
"three": "^0.126.1",
"three.meshline": "^1.4.0",
"vue": "2.6.10",

View File

@ -0,0 +1,29 @@
import request from '@/utils/request'
// 公共资源管理--镜像管理 --镜像列表
export function getImageList(params) {
return request({
url: '/pcm/v1/image/list',
method: 'get',
params
})
}
// 上传
export function sliceUpload(data) {
return request({
url: '/pcm/v1/image/upload',
method: 'post',
data
})
}
// 合并
export function mergeUpload(data) {
return request({
url: '/pcm/v1/image/chunk',
method: 'get',
params: data
})
}

View File

@ -56,3 +56,20 @@ export function getStorageData() {
method: 'get'
})
}
// 配置图片上传接口
export function uploadImage(data) {
return request({
url: 'jcc-cloudStorage/storage/upload/pcm',
method: 'post',
data
})
}
// 获取配置数据
export function getMonitorSetting() {
return request({
url: 'pcm/v1/core/getResourcePanelConfigHandler',
method: 'get'
})
}

View File

@ -66,6 +66,12 @@
<el-dropdown-item v-if="menus.includes('monitorManagement')" @click.native="toMonitorManagement">
告警中心
</el-dropdown-item>
<el-dropdown-item v-if="menus.includes('setting')" @click.native="toSetting">
设置中心
</el-dropdown-item>
<el-dropdown-item v-if="menus.includes('resourceManagement')" @click.native="toResourceManagement">
公共资源管理
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">
<span style="display:block;">退出登录</span>
</el-dropdown-item>
@ -145,6 +151,14 @@ export default {
this.$store.dispatch('user/setRouteType', 'monitorManagement')
this.$router.push({ path: '/monitorManagement/warnList' })
},
toSetting() {
this.$store.dispatch('user/setRouteType', 'setting')
this.$router.push({ path: '/setting/monitor' })
},
toResourceManagement() {
this.$store.dispatch('user/setRouteType', 'resourceManagement')
this.$router.push({ path: '/resourceManagement/imageManagement' })
},
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},

282
src/mixin/sliceUpload.js Normal file
View File

@ -0,0 +1,282 @@
const SparkMD5 = require('spark-md5')
import { getUploadStatus, sliceUpload, mergeUpload } from '@/api/container/imageManagement'
// 切片大小(单位:B)
const CHUNK_SIZE = 5 * 1024 * 1024
/**
* @description: 分块计算文件的md5值
* @param {*} file 文件
* @param {*} chunkSize 分片大小
* @returns {*}
*/
function calculateFileMd5(file, chunkSize) {
return new Promise((resolve, reject) => {
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
const chunks = Math.ceil(file.size / chunkSize)
let currentChunk = 0
const spark = new SparkMD5.ArrayBuffer()
const fileReader = new FileReader()
fileReader.onload = function(e) {
spark.append(e.target.result)
currentChunk++
if (currentChunk < chunks) {
loadNext()
} else {
const md5 = spark.end()
resolve(md5)
}
}
fileReader.onerror = function(e) {
reject(e)
}
function loadNext() {
const start = currentChunk * chunkSize
let end = start + chunkSize
if (end > file.size) {
end = file.size
}
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
}
loadNext()
})
}
/**
* @description: 分块计算文件的md5值
* @param {*} file 文件
* @returns {Promise}
*/
function calculateFileMd5ByDefaultChunkSize(file) {
return calculateFileMd5(file, CHUNK_SIZE)
}
/**
* @description: 文件切片
* @param {*} file
* @param {*} size 切片大小
* @returns [{file}]
*/
function createFileChunk(file, size = CHUNK_SIZE) {
const chunks = []
let cur = 0
while (cur < file.size) {
chunks.push({ file: file.slice(cur, cur + size) })
cur += size
}
return chunks
}
/**
* @description: 获取文件的后缀名
*/
function getFileType(fileName) {
return fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase()
}
/**
* @description: 根据文件的md5值判断文件是否已经上传过了
* @param {*} md5 文件的md5
* @param {*} 准备上传的文件
* @returns {Promise}
*/
function checkMd5(md5, file) {
return new Promise(resolve => {
getUploadStatus({ md5 })
.then(res => {
if (res.data.code === 20000) {
// 文件已经存在了,秒传(后端直接返回已上传的文件)
resolve({
uploaded: true,
url: res.data.msg,
code: res.data.code
})
} else if (res.data.code === 40004) {
// 文件不存在需要上传
resolve({ uploaded: false, url: '', code: res.data.code })
} else {
resolve({ uploaded: false, url: '', code: 500 })
}
})
.catch(() => {
resolve({ uploaded: false, url: '', code: 500 })
})
})
}
/**
* @description: 执行分片上传
* @param {*} file 上传的文件
* @param {*} i 第几分片从0开始
* @param {*} md5 文件的md5值
* @param {*} vm 虚拟 dom 指向组件 this
* @returns {Promise}
*/
function PostFile(file, i, md5, vm) {
const name = file.name // 文件名
const size = file.size // 总大小
const shardCount = Math.ceil(size / CHUNK_SIZE) // 总片数
if (i >= shardCount) {
return
}
const start = i * CHUNK_SIZE
const end = start + CHUNK_SIZE
const packet = file.slice(start, end) // 将文件进行切片
/* 构建form表单进行提交 */
const form = new FormData()
form.append('md5', md5) // 前端生成uuid作为标识符传个后台每个文件都是一个uuid防止文件串了
form.append('file', packet) // slice方法用于切出文件的一部分
form.append('name', name)
form.append('totalSize', size)
form.append('total', shardCount) // 总片数
form.append('index', i + 1) // 当前是第几片
return new Promise((resolve, reject) => {
sliceUpload(form)
.then(res => {
if (res.data.code === 20001) {
// 拿到已上传过的切片
resolve({
uploadedList: res.data.chunkList ? res.data.chunkList.map(item => `${md5}-${item}`) : []
})
} else if (res.data.code === 20002) {
resolve({ uploadedList: [] })
} else {
resolve({ uploadedList: [], code: 500 })
// reject()
}
})
.catch(() => {
// reject()
resolve({ uploadedList: [], code: 500 })
})
})
}
/**
* @description: 合并文件
* @param {*} shardCount 分片数
* @param {*} fileName 文件名
* @param {*} md5 文件md值
* @param {*} fileType 文件类型
* @param {*} fileSize 文件大小
* @returns {Promise}
*/
function merge(shardCount, fileName, md5, fileType, fileSize) {
return mergeUpload({ shardCount, fileName, md5, fileType, fileSize })
}
export default {
data() {
return {
chunks: [],
percent: 0,
percentCount: 0,
stopUpload: false // 在需要的时机或场合阻止上传
}
},
methods: {
/**
* @description: 上传文件
* @param {*} file 文件
* @returns {Object} 包含成功的文件地址名称等
*/
async chunksUpload(file) {
this.chunks = []
// step1 获取文件切片
const initChunks = createFileChunk(file)
// step2 获取文件 md5 值
const md5 = await calculateFileMd5ByDefaultChunkSize(file)
// step3 获取文件的上传状态
const { uploaded, url, code } = await checkMd5(md5, file)
if (uploaded) {
// step4 如果上传成功
this.percent = 100
// step5 拿到结果
return url
}
if (!uploaded && code === 500) {
return this.errorInfo()
}
// step4 如果文件未传成功,执行切片上传
const { uploadedList } = await PostFile(file, 0, md5, this)
// todo 方法1逐次发送请求
const requestList = [] // 请求集合
initChunks.forEach(async(chunk, index) => {
// 过滤掉已上传的切片
if (uploadedList.indexOf(md5 + '-' + (index + 1)) < 0) {
const fn = () => {
return PostFile(file, index, md5, this)
}
requestList.push(fn)
}
})
let reqNum = 0 // 记录发送的请求个数
const send = async() => {
if (reqNum >= requestList.length) {
// step5 如果所有切片已上传,执行合并
const res = await merge(initChunks.length, file.name, md5, getFileType(file.name), file.size)
if (res.data.code === 20000) {
return res.data.msg
} else {
this.errorInfo()
return {}
}
}
if (this.stopUpload) return {} // 阻止上传
const sliceRes = await requestList[reqNum]()
if (sliceRes.code && sliceRes.code === 500) {
return this.errorInfo()
}
// 计算当下所上传切片数
const count = initChunks.length - uploadedList.length
if (this.percentCount === 0) {
this.percentCount = 100 / count
}
this.percent += this.percentCount
reqNum++
return send()
}
const mergeResult = await send()
return mergeResult
// todo 方法2使用Promise.all 统一发送请求
// const requestList = initChunks.map(async(chunk, index) => {
// // 过滤掉已上传的切片
// if (uploadedList.indexOf(md5 + '-' + (index + 1)) < 0) {
// return PostFile(file, index, md5, this)
// }
// })
// return Promise.all(requestList)
// .then(async() => {
// const res = await merge(initChunks.length, file.name, md5, getFileType(file.name), file.size)
// if (res.data.code === 20000) {
// return res.data.msg
// }
// })
// .catch(() => {
// return this.$message.error('出错了,请稍后重试!')
// })
},
/**
* @description: 错误提示
*/
errorInfo() {
this.$message.error('出错了,请稍后重试!')
}
}
}

View File

@ -13,6 +13,8 @@ import permissionRouter from './modules/permissionManagement'
import monitorRouter from './modules/monitorManagement'
import scheduleRouter from './modules/jccSchedule'
import hpc from './modules/hpc'
import settingRouter from './modules/setting'
import resourceManagementRouter from './modules/resourceManagement'
/* Router Modules */
// import componentsRouter from './modules/components'
// import tableRouter from './modules/table'
@ -128,7 +130,9 @@ export const constantRoutes = [
permissionRouter,
monitorRouter,
scheduleRouter,
hpc
hpc,
settingRouter,
resourceManagementRouter
]
const createRouter = () => new Router({

View File

@ -0,0 +1,28 @@
import Layout from '@/layout'
import emptyLayout from '@/layout/emptyLayout'
const permissionRouter = {
path: '/resourceManagement',
component: Layout,
name: '公共资源管理',
meta: {
title: '公共资源管理',
icon: 'yunweijiankongmokuai'
},
children: [
{
path: 'imageManagement',
component: emptyLayout,
redirect: 'imageManagement',
children: [
{
path: '',
component: () => import('@/views/resourceManagement/imageManagement/list'),
name: 'imageManagement',
meta: { title: '镜像管理', icon: 'xunijiguanli-zhuji', affix: true },
hidden: false
}
]
}
]
}
export default permissionRouter

View File

@ -0,0 +1,28 @@
import Layout from '@/layout'
import emptyLayout from '@/layout/emptyLayout'
const permissionRouter = {
path: '/setting',
component: Layout,
name: '设置',
meta: {
title: '设置中心',
icon: 'yunweijiankongmokuai'
},
children: [
{
path: 'monitor',
component: emptyLayout,
redirect: 'monitor',
children: [
{
path: '',
component: () => import('@/views/setting/monitor/index'),
name: 'monitor',
meta: { title: '监控设置', icon: 'xunijiguanli-zhuji', affix: true },
hidden: false
}
]
}
]
}
export default permissionRouter

View File

@ -1,29 +0,0 @@
<template>
<div class="dashboard-container">
<HeadNav :mini="true" />
<Console />
<Footer />
</div>
</template>
<script>
import HeadNav from '../components/headNav.vue'
import Console from '../components/console.vue'
import Footer from '../components/footer.vue'
export default {
name: 'Index',
components: { HeadNav, Console, Footer },
data() {
return {
}
},
computed: {
},
created() {
// if (!this.roles.includes('admin')) {
// this.currentRole = 'editorDashboard'
// }
}
}
</script>

View File

@ -1,29 +0,0 @@
<template>
<div class="dashboard-container">
<HeadNav />
<RequirementCatalogue />
<Footer />
</div>
</template>
<script>
import HeadNav from '../components/headNav.vue'
import RequirementCatalogue from '../components/requirementList.vue'
import Footer from '../components/footer.vue'
export default {
name: 'RequirementList',
components: { HeadNav, RequirementCatalogue, Footer },
data() {
return {
}
},
computed: {
},
created() {
// if (!this.roles.includes('admin')) {
// this.currentRole = 'editorDashboard'
// }
}
}
</script>

View File

@ -0,0 +1,167 @@
<template>
<div class="projectInfo">
<el-row>
<el-card class="basicInfo">
<img src="@/assets/images/node.png" class="sidebar-logo" alt="项目">
<h4>镜像列表</h4>
</el-card>
</el-row>
<el-row>
<el-card>
<List
ref="multipleTable"
class="multipleTable"
:columns="columns"
:table-list-data="imageList"
:pagination="true"
tooltip-effect="dark"
>
<template v-slot:filterBtns>
<el-button size="medium" type="primary" @click="dialogVisible = true">创建镜像</el-button>
</template>
</List>
</el-card>
</el-row>
<el-dialog
:close-on-click-modal="false"
title="上传镜像"
:visible.sync="dialogVisible"
width="60%"
>
<el-upload
action
:limit="1"
accept=".jar"
:auto-upload="false"
:show-file-list="false"
:on-change="onFileChange"
>
<el-button size="small" type="primary">上传jar包</el-button>
<div slot="tip" class="el-upload__tip">只能上传jar文件</div>
</el-upload>
<div>上传进度: {{ percent.toFixed()+ '%' }}</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitFile()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import List from '@/components/list'
import { getImageList } from '@/api/container/imageManagement'
import chunksUpload from '@/mixin/sliceUpload.js'
export default {
name: 'ProjectForm',
components: { List },
mixins: [chunksUpload],
data() {
return {
getImageList,
dialogVisible: false,
imageList: [],
columns: [
{ prop: 'ruleName', label: '规则标题' },
{ prop: 'type', label: '告警类型' },
{ prop: 'alarmLevel', label: '告警级别' },
{ prop: 'clusters', label: '生效集群' },
{ prop: 'interval', label: '执行频率' },
{ prop: 'duration', label: '持续时长' },
{ prop: 'note', label: '规则备注' },
{ prop: 'more', width: '80', label: '操作', formatter: (row) => {
return <div>
<el-dropdown>
<el-button size='mini' className='el-dropdown-link' icon='el-icon-more' circle>
</el-button>
<el-dropdown-menu slot='dropdown'>
{/* <span onClick={() => this.editBaseInfo(row)}> <el-dropdown-item> 下载 </el-dropdown-item> </span> */}
<span onClick={() => this.deleteItem(row)}> <el-dropdown-item> 删除</el-dropdown-item> </span>
</el-dropdown-menu>
</el-dropdown>
</div>
} }
]
}
},
created() {
getImageList().then(e => {
this.imageList = e.data.repositories
})
},
destroyed() {
//
this.stopUpload = true
},
methods: {
httpRequest(data) {
const isJar = data.file.name.indexOf('.jar') === (data.file.name.length - 4)
if (!isJar) {
this.$message.error('上传文件只能是 jar 格式!')
} else {
this.rs.set('file', data.file)
}
},
submitFile() {
console.log('r')
// const chunkSize = 100 * 1024 * 1024 // chunk2
// const blobSlice =
// File.prototype.slice ||
// File.prototype.mozSlice ||
// File.prototype.webkitSlice
},
async onFileChange(file) {
this.clearVideoUpload()
// const fileType = file.raw.type
// const fileSize = file.raw.size / 1024 / 1024
// if (fileType !== 'jar') return this.$message.error(' jar ')
// if (fileSize > 1000) return this.$message.error(' 1G')
const res = await this.chunksUpload(file.raw)
console.log('上传结果', res)
},
clearVideoUpload() {
this.videoUrl = ''
this.percent = 0
}
},
deleteItem(row) {
this.$confirm('是否要删除该镜像', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// deleteWarningRule(row.id).then(response => {
// this.$message({
// message: '',
// type: 'success',
// duration: 1000
// })
// this.$refs.multipleTable.getList()
// })
})
},
handleDialogConfirm() {
this.$refs.warningRule.validate((valid) => {
if (valid) {
// postWarningRule(this.warningRule).then(e => {
// if (e.code === 200) {
// this.$message.success('')
// this.dialogVisible = false
// this.$refs.multipleTable.getList()
// }
// })
}
})
}
// }
}
</script>
<style lang="scss" scoped>
.projectInfo{
text-align: left;
}
</style>

View File

@ -1,29 +0,0 @@
<template>
<div class="dashboard-container">
<HeadNav />
<ServiceCatalogue />
<Footer />
</div>
</template>
<script>
import HeadNav from '../components/headNav.vue'
import ServiceCatalogue from '../components/serviceList.vue'
import Footer from '../components/footer.vue'
export default {
name: 'ServiceList',
components: { HeadNav, ServiceCatalogue, Footer },
data() {
return {
}
},
computed: {
},
created() {
// if (!this.roles.includes('admin')) {
// this.currentRole = 'editorDashboard'
// }
}
}
</script>

View File

@ -0,0 +1,198 @@
<template>
<div class="">
<el-card class="basicInfo">
<el-form ref="monitorSettingForm" :model="monitorSettingForm">
<el-form-item label="标题" required="">
<el-input v-model="monitorSettingForm.title" />
</el-form-item>
<el-form-item label="标题颜色" required="">
<el-input v-model="monitorSettingForm.titleColor" />
<el-color-picker
v-model="monitorSettingForm.titleColor"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="主色调" required="">
<el-input v-model="monitorSettingForm.mainColor" />
<el-color-picker
v-model="monitorSettingForm.mainColor"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="次色调" required="">
<el-input v-model="monitorSettingForm.mainColor2" />
<el-color-picker
v-model="monitorSettingForm.mainColor2"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="文字颜色" required="">
<el-input v-model="monitorSettingForm.textColor" />
<el-color-picker
v-model="monitorSettingForm.textColor"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="背景颜色" required="">
<el-input v-model="monitorSettingForm.backgroundColor" />
<el-color-picker
v-model="monitorSettingForm.backgroundColor"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="中心点" required="">
<el-input v-model="monitorSettingForm.center" />
</el-form-item>
<el-form-item label="中心点坐标" required="">
<el-input v-model="monitorSettingForm.centerPosition" />
</el-form-item>
<el-form-item label="省份背景色" required="">
<el-input v-model="monitorSettingForm.provinceBgColor" />
<el-color-picker
v-model="monitorSettingForm.provinceBgColor"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="接入中状态svg" required>
<el-upload
class="avatar-uploader"
action="/apis/jcc-cloudStorage/storage/upload/pcm"
:show-file-list="false"
:on-success="handleAvatarSuccess"
>
<img v-if="monitorSettingForm.statusIng" :src="monitorSettingForm.statusIng" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon" />
</el-upload>
</el-form-item>
<!-- 'statusIng': 'black',
'statusUn': '未接入',
'statusEnd': '已接入', -->
<el-form-item label="数字颜色" required="">
<el-input v-model="monitorSettingForm.numberBg" />
<el-color-picker
v-model="monitorSettingForm.numberBg"
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
class="theme-picker"
show-alpha
popper-class="theme-picker-dropdown"
/>
</el-form-item>
<el-form-item label="任务模块底图" required="">
<el-input v-model="monitorSettingForm.taskBg" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button icon="el-icon-check" circle @click="ok" />
</div>
</el-card>
</div>
</template>
<script>
import { getMonitorSetting } from '@/api/container/monitorSelect'
export default {
name: 'MonitorSetting',
data() {
return {
rules: {},
monitorSettingForm: {
'title': '广域协同智能计算系统面板',
'titleColor': '#409EFF',
'mainColor': 'blue',
'mainColor2': 'blue',
'textColor': 'blue',
'backgroundColor': 'blue',
'center': 'blue',
'centerPosition': 'blue',
'provinceBgColor': 'blue',
'statusIng': 'black',
'statusUn': '未接入',
'statusEnd': '已接入',
'titleIcon': 'blue',
'subTitleIcon': 'blue',
'numberBg': 'blue',
'taskBg': 'blue'
}
}
},
created() {
getMonitorSetting().then(e => {
this.monitorSettingForm = e.data
})
},
methods: {
ok() {
},
handleAvatarSuccess(res, file) {
console.log(res)
// this.imageUrl = URL.createObjectURL(file.raw)
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
}
}
}
</script>
<style lang="scss" scoped>
.projectInfo{
text-align: left;
}
.basicInfo{
.el-form-item .el-input {
width: 200px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
display: block;
}
}
</style>

View File

@ -11508,6 +11508,11 @@
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
"version" "0.6.1"
"spark-md5@^3.0.2":
"integrity" "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw=="
"resolved" "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz"
"version" "3.0.2"
"spdx-correct@^3.0.0":
"integrity" "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w=="
"resolved" "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz"