This commit is contained in:
ann 2022-03-04 09:17:20 +08:00
parent 42f6d9c617
commit cf34290f20
39 changed files with 2167 additions and 802 deletions

View File

@ -0,0 +1,47 @@
import request from '@/utils/request'
// 计量计费获取集群及成员集群列表接口
export function getClusterList(params) {
return request({
url: process.env.VUE_APP_BASE_API + `/kapis/resources.kubesphere.io/v1alpha3/clusters`,
method: 'get',
params
})
}
// 计量计费获取集群-节点列表接口
export function getNodeList(cluster, params) {
return request({
url: process.env.VUE_APP_BASE_API + `/kapis/clusters/${cluster}/resources.kubesphere.io/v1alpha3/nodes`,
method: 'get',
params
})
}
// 消费账单接口
export function getBillNum(params) {
return request({
url: process.env.VUE_APP_BASE_API + `/kapis/clusters/${params.resources_filter}/metering.kubesphere.io/v1alpha1/cluster`,
method: 'get',
params
})
}
// 截止到昨天的消费历史
export function getHistoryCost(params) {
return request({
url: process.env.VUE_APP_BASE_API + '/kapis/resources.kubesphere.io/v1alpha3/clusters',
method: 'get',
params
})
}
// 当前包含的资源
export function getResource(params) {
return request({
url: process.env.VUE_APP_BASE_API + `/kapis/clusters/${params.clusterName}/metering.kubesphere.io/v1alpha1/nodes`,
method: 'get',
params
})
}
0

View File

@ -0,0 +1,120 @@
// 大屏云厂商服务器数量查询接口
import request from '@/utils/request'
export function getTotalName() {
return request({
url: process.env.VUE_APP_FUNCTION_API + '/function/device/queryByManufacturer',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 大屏服务器数量统计接口
export function getTotalNum() {
return request({
url: process.env.VUE_APP_FUNCTION_API + '/function/device/queryDeviceCount',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 大屏地球地区查询接口
export function getEarthRegion() {
return request({
url: process.env.VUE_APP_FUNCTION_API + '/function/device/queryByArea',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 大屏地球各个区域服务器资源详细接口
export function getEarthDetails(area) {
return request({
url: process.env.VUE_APP_FUNCTION_API + '/function/device/queryResDetailByArea?area=' + area,
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// CPU平均使用率接口
export function getCpuAverage(start, end, step) {
return request({
url: '/monitoringscreen/api/v1/query_range?query=avg(1%20-%20avg(rate(node_cpu_seconds_total%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%2Cmode%3D%22idle%22%7D%5B2m%5D))%20by%20(instance))%20*%20100' + '&start=' + start + '&end=' + end + '&step=' + step + '&_=1642578431700',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 内存平均使用率接口
export function getRamAverage(start, end, step) {
return request({
url: '/monitoringscreen/api/v1/query_range?query=(sum(node_memory_MemTotal_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D%20-%20node_memory_MemAvailable_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D)%20%2F%20sum(node_memory_MemTotal_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D))*100' + '&start=' + start + '&end=' + end + '&step=' + step + '&_=1642578431700',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 计量计费接口总价格
export function getMeasure(start, end, step) {
return request({
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/fedjcce-ten002/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=fedjcce-ten002',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 内存整体负载接口
export function getRamLoad(start, end, step) {
return request({
url: '/monitoringscreen/api/v1/query_range?query=sum(node_memory_MemTotal_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D%20-%20node_memory_MemAvailable_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D)&start=' + start + '&end=' + end + '&step=' + step + '&_=1642669327729',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// 计量计费列表接口
export function getMeteringList(start, end, step) {
return request({
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/fedjcce-ten002/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=fedjcce-ten002',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}
// CPU整体负载接口
export function getCpuAllload(start, end) {
return request({
url: '/monitoringscreen/api/v1/query_range?query=node_load15%7Binstance%3D~%22jcc-txy-001%22%7D&start=' + start + '&end=' + end + '&step=900&_=1645409802467',
method: 'get',
data: JSON,
headers: {
'Content-Type': 'application/json'
}
})
}

BIN
src/assets/img/node1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/assets/img/node2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/assets/img/node3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/assets/img/node4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,50 +1,98 @@
<template>
<!-- 添加容器镜像 -->
<!-- 初始容器 其他 -->
<el-dialog v-if="dialogVisible" width="80%" title="容器" :visible.sync="dialogVisible">
<p>
容器设置
<span class="tips">对容器的名称及容器的计算资源进行设置</span>
</p>
<el-form ref="createContainerForm" :model="createContainerForm">
<el-form-item label="镜像" required="">
<el-input v-model="createContainerForm.mirror" placeholder="点击右侧图标可选择镜像,或直接输入名称 例nginx:latest">
<template slot="prepend">DockerHub</template>
</el-input>
<el-dialog v-if="dialogVisible" width="80%" :title="(!createContainerForm.name?'添加':'编辑')+'容器'" :visible.sync="dialogVisible">
<el-select v-model="createContainerForm.volumes" filterable class="selectPro" placeholder="选择已有镜像">
<el-option
v-for="item in volumesList"
:key="item.label"
:label="item.label"
:value="item.label"
<el-form ref="createContainerForm" :model="createContainerForm">
<div class="border">
<p>
容器设置
<span class="tips">对容器的名称及容器的计算资源进行设置</span>
</p>
<el-form-item label="镜像" required="">
<el-input v-model="createContainerForm.image" placeholder="点击右侧图标可选择镜像,或直接输入名称 例nginx:latest">
<template slot="prepend">DockerHub</template>
<el-select slot="append" v-model="createContainerForm.image" filterable class="selectPro" placeholder="选择已有镜像" @change="selectMirror">
<el-option
v-for="item in imageList"
:key="item.name"
:label="item.name"
:value="item.name"
>
<el-image
style="display:block;float:left;width: 30px; height: 30px"
:src="item.imgUrl"
fit="fit"
/>
<span style="width:20%; display:block;float:left">{{ item.name }}</span>
<span style="width:60%;display:block;float:left; color: #8492a6; font-size: 13px">{{ item.description }}</span>
<span style="width:10%; display:block;float:left; text-align:right"><i class="el-icon-star-on" />{{ item.star }}</span>
</el-option>
</el-select>
</el-input>
<el-card v-loading="loading" class="grayCard" shadow="never">
<span v-if="!imageData">{{ !noImage ? '请选择容器镜像' : '没有找到此镜像' }}</span>
<div v-if="imageData" style="">
<el-button style="float:right" round @click="useDefaultPorts">使用默认端口</el-button>
<p>{{ createContainerForm.image }}</p>
<span class="tips">
{{ moment(imageData.createTime).fromNow() + ', ' +(imageData.size/1024/1024).toFixed(2) + `MB,` + imageData.layers + '层级' }}
</span>
<table class="el-table">
<tr>
<td>tag</td>
<td>
{{ imageData.imageTag }}
</td>
<td>端口</td>
<td>{{ imageData.exposedPorts.join(';') || '暂无默认端口配置' }}</td>
<td>
{{ imageData.registry }}
仓库
</td>
</tr>
</table>
</div>
</el-card>
</el-form-item>
</div>
<div class="border">
<p>
端口设置
<span class="tips">设置容器的访问策略</span>
</p>
<div>
<el-form-item
v-for="(tag, index) in createContainerForm.ports"
:key="'tag'+index"
label=""
>
<span style="width:50%; display:block;float:left">{{ item.label }}{{ item.alias?'('+item.alias+')':'' }}存储类型{{ item.storageClassName }}</span>
<span style="width:10%;display:block;float:left; color: #8492a6; font-size: 13px">容量{{ item.storage }}</span>
<span style="width:40%; display:block;float:left; text-align:right">访问模式{{ item.accessModes }}</span>
</el-option>
</el-select>
<!-- </el-option>
</el-select> -->
</el-form-item>
</el-form-item>
<table>
<tr>
<td>容器</td>
<td>container-9lxa15</td>
<td>
<el-select v-model="createContainerForm.readOnly">
<el-option
v-for="item in mountOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</td>
<td><el-input v-model="createContainerForm.mountPath" :disabled="!createContainerForm.readOnly || createContainerForm.readOnly === 'null'" placeholder="容器挂载路径, 例如: /data" /></td>
</tr>
</table>
</el-form>
<table>
<tr>
<td>容器</td>
<td>container-9lxa15</td>
<td>
<el-select v-model="createContainerForm.readOnly">
<el-option
v-for="item in mountOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</td>
<td><el-input v-model="createContainerForm.mountPath" :disabled="!createContainerForm.readOnly || createContainerForm.readOnly === 'null'" placeholder="容器挂载路径, 例如: /data" /></td>
</tr>
</table>
</div></div></el-form>
<div slot="footer" class="dialog-footer">
<el-button icon="el-icon-close" circle @click="dialogVisible = false" />
<el-button icon="el-icon-check" circle @click="ok" />
@ -53,7 +101,10 @@
</template>
<script>
import { mountOptions } from '@/utils/map'
import moment from 'moment'
import { isEmpty } from 'lodash'
import generate from 'nanoid/generate'
import { mountOptions, imagePullPolicyOptions, protocolOptions } from '@/utils/map'
export default {
props: {
value: {
@ -63,18 +114,31 @@ export default {
formData: {
type: Object,
default: () => {}
},
isEdit: {
type: Boolean,
default: false
}
// isEdit: {
// type: Boolean,
// default: false
// }
},
data() {
return {
createContainerForm: {},
volumesList: [],
createContainerForm: {
ports: [],
securityContext: {
seLinuxOptions: {}
}
},
imageList: [],
activeName: 'first',
mountOptions
namespace: '',
imageData: undefined,
noImage: false,
loading: false,
mountOptions,
editInfoForm: {},
imagePullPolicyOptions,
protocolOptions,
moment
}
},
computed: {
@ -92,37 +156,112 @@ export default {
set(value) {
this.$emit('input', value)
}
},
addTagNumCheck() {
let flag = false
this.createContainerForm.ports.forEach(e => {
if (e.containerPort === '') {
flag = true
}
})
return flag
}
},
watch: {
// 'createContainerForm.image'(newVal) {
// throttle(this.selectMirror(), 300)
// }
},
mounted() {
this.getVolumeList()
},
methods: {
getVolumeList() {
this.$Api.getVolume(this.clusterName).then(res => {
const arr = res.items.map(e => { return { label: e.metadata.name, alias: e.metadata.annotations['kubesphere.io/alias-name'], accessModes: e.spec.accessModes.join(','), storage: e.spec.resources.requests.storage, storageClassName: e.spec.storageClassName } })
this.volumesList = arr
selectPolicy(tag) {
tag.name = tag.protocol.toLowerCase() + '-'
},
addTag() {
this.createContainerForm.ports.push({ protocol: 'HTTP', name: 'http-', containerPort: '' })
},
removeTag(tag, index) {
this.createContainerForm.ports.splice(index, 1)
// this.blurInput()
},
selectMirror() {
//
this.loading = true
this.$Api.getImagesInfo(this.namespace, this.createContainerForm.image).then(res => {
// if status === 'fail'
//
// if status === 'succeeded'
console.log(res.status)
if (res.status === 'succeeded') {
const layers = res.imageManifest.layers
const size = layers.reduce((prev, layer) => prev + layer.size, 0)
this.imageData = {
imageTag: res.imageTag,
message: res.message || '',
registry: res.registry,
layers: layers.length,
createTime: res.imageBlob.created,
size,
exposedPorts: Object.keys(
res.imageBlob.container_config.ExposedPorts || {}
),
status: res.status,
slug: res.slug || ''
}
} else {
this.imageData = undefined
}
this.noImage = false
this.loading = false
}).catch(() => {
this.noImage = true
this.loading = false
})
},
getImageList() {
this.$Api.getImagesList().then(res => {
const arr = res.summaries.map(e => {
return { name: e.name, description: e.short_description, star: e.star_count, imgUrl: e.logo_url.large || e.logo_url.small }
})
this.imageList = arr
})
},
useDefaultPorts() {
//
const ports = this.imageData.exposedPorts.map(port => {
const protocol = port.split('/')[1]
const containerPort = Number(port.split('/')[0])
return {
name: `${protocol}-${containerPort}`,
protocol: protocol.toUpperCase(),
containerPort,
servicePort: containerPort
}
})
console.log(ports)
if (!isEmpty(ports)) {
this.createContainerForm.ports = ports
}
},
ok() {
const val = {}
// generate('0123456789abcdefghijklmnopqrstuvwxyz', length || 6)
const container = Object.assign(this.createContainerForm)
if (!this.createContainerForm.name) {
container.name = 'container-' + generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)
this.$emit('addImage', container)
} else {
this.$emit('editImage', container)
}
this.dialogVisible = false
//
// if(this.createContainerForm.readOnly !== 'null'){
// this.formData.spec.template.spec.containers.forEach(e=>{
// })
// }
switch (this.activeName) {
case 'first':
break
case 'second':
break
}
return this.$emit('addVolumes', val)
},
handleClick() {}
}

View File

@ -1,17 +1,27 @@
<template>
<!-- 列表信息可编辑修改 -->
<div>
<div class="dataList">
<div v-for="(item, index) in dataList" :key="index" class="dataList">
<i :class="`'el-icon-'${iconName||'receiving'}`" />
<div>{{ dataList.key }}</div>
<div />
<div />
</div>
</div>
</template>
<script>
export default {
props: {
dataList: {
type: Array,
default: () => []
}
},
data() {
return {
dataList: []
}
}
}

View File

@ -1,6 +1,5 @@
<template>
<div>
{{ editInfoForm }}
<el-form ref="editInfoForm" :rules="rules" :model="editInfoForm">
<el-row :gutter="20">
<el-col :span="12">
@ -61,6 +60,7 @@
</template>
<script>
import { set } from 'lodash'
export default {
props: {
value: {
@ -127,40 +127,56 @@ export default {
})
},
submitInfoEdit() {
this.formData = {
apiVersion: 'v1',
kind: 'Namespace',
metadata: {
labels: {
app: this.editInfoForm.name
},
name: this.editInfoForm.name,
annotations: {
'kubesphere.io/alias-name': this.editInfoForm.alias,
'kubesphere.io/description': this.editInfoForm.description,
'kubesphere.io/creator': 'admin'
},
namespace: this.editInfoForm.namespace
},
spec: {
replicas: 1, // ,
selector: {
matchLabels: {
app: this.editInfoForm.name
}
},
template: {
metadata: {
labels: {
app: this.editInfoForm.name
}, //
annotations: {
'logging.kubesphere.io/logsidecar-config': '{}'
}
}
}
}
}
// when formData is empty do this
const { name, alias, description, namespace } = this.editInfoForm
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'metadata.name', name)
set(this.formData, 'metadata.labels.app', name)
set(this.formData, 'spec.selector.matchLabels.app', name)
set(this.formData, 'spec.template.metadata.lables.app', name)
set(this.formData, 'metadata.annotations[kubesphere.io/alias-name]', alias)
set(this.formData, 'metadata.annotations[kubesphere.io/alias-description]', description)
set(this.formData, 'metadata.annotations[kubesphere.io/creator]', 'admin')
set(this.formData, 'metadata.namespace', namespace)
set(this.formData, 'spec.template.metadata.annotations[logging.kubesphere.io/logsidecar-config]', '{}')
// this.formData = {
// apiVersion: 'v1',
// kind: 'Namespace',
// metadata: {
// labels: {
// app: this.editInfoForm.name
// },
// name: this.editInfoForm.name,
// annotations: {
// 'kubesphere.io/alias-name': this.editInfoForm.alias,
// 'kubesphere.io/description': this.editInfoForm.description,
// 'kubesphere.io/creator': 'admin'
// },
// namespace: this.editInfoForm.namespace
// },
// spec: {
// containers: [],
// replicas: 1, // ,
// selector: {
// matchLabels: {
// app: this.editInfoForm.name
// }
// },
// stategy: { type: 'RollingUpdate', rollingUpdate: {}},
// securityContext: {},
// template: {
// metadata: {
// labels: {
// app: this.editInfoForm.name
// }, //
// annotations: {
// 'logging.kubesphere.io/logsidecar-config': '{}'
// }
// }
// }
// }
// }
},
nameValidator(rule, value, callback) {
if (!value) {

View File

@ -2,29 +2,37 @@
<div class="createForm">
<el-form ref="editInfoForm" :rules="rules" :model="editInfoForm">
<el-form-item
prop="namespace"
prop="replicas"
label="容器组副本数量"
>
<el-input-number v-model="editInfoForm.num" :min="1" :max="10" label="描述文字" />
<el-input-number v-model="editInfoForm.spec.replicas" :min="1" :max="10" label="" />
</el-form-item>
<p>容器镜像</p>
<el-button @click="containerFormVisiable=true">
添加容器镜像
<span class="tips">Kubesphere 支持从镜像仓库拉取镜像以及通过代码构建新的镜像并部署</span>
</el-button>
<addContainerForm v-model="containerFormVisiable" :form-data="formData" @addVolumes="addContainer" />
<div v-if="editInfoForm.spec.template.spec.containers">
<div v-for="(item, index) in editInfoForm.spec.template.spec.containers" :key="index" class="dataList">
<i class="el-icon-receiving" />
<div>{{ item.name }}</div>
<div>镜像{{ item.image }}</div>
</div>
</div>
<addContainerForm v-model="containerFormVisiable" :form-data="formData" @addImage="addImage" @editImage="editImage" />
<!-- <el-form-item
prop="mirror"
label="更新策略"
> -->
<p>更新策略</p>
<el-radio v-model="editInfoForm.radio1" class="selectRadio" label="1" border>滚动更新(推荐)
<el-radio v-model="editInfoForm.spec.strategy.type" class="selectRadio" label="RollingUpdate" border>滚动更新(推荐)
<span class="tips">滚动升级将逐步用新版本的实例替换旧版本的实例升级的过程中业务流量会同时负载均衡分布到新老的实例上因此业务不会中断</span>
</el-radio>
<el-radio v-model="editInfoForm.radio1" class="selectRadio" label="2" border>替换升级
<el-radio v-model="editInfoForm.spec.strategy.type" class="selectRadio" label="Recreate" border>替换升级
<span class="tips">替换升级会先删除旧的容器组再创建新容器组升级过程中业务会中断</span>
</el-radio>
<el-collapse v-if="editInfoForm.radio1==='1'">
<el-collapse v-if="editInfoForm.spec.strategy.type==='RollingUpdate'">
<el-collapse-item>
<template slot="title">
更新时容器组数量
@ -35,7 +43,7 @@
prop="maxUnavailable"
label="容器组最大不可用数量"
>
<el-input v-model="editInfoForm.maxUnavailable" :maxlength="63" />
<el-input v-model="editInfoForm.spec.strategy.rollingUpdate.maxUnavailable" :maxlength="63" />
<span class="tips">升级过程中可能不可用的 Pod 的最大数量</span>
</el-form-item>
</el-col>
@ -44,7 +52,7 @@
prop="maxSurge"
label="容器组最大超出数量"
>
<el-input v-model="editInfoForm.maxSurge" :maxlength="63" />
<el-input v-model="editInfoForm.spec.strategy.rollingUpdate.maxSurge" :maxlength="63" />
<span class="tips">升级过程中允许超出副本数量的容器组的最大数量或百分比</span>
</el-form-item>
</el-col>
@ -58,10 +66,10 @@
>
</el-form-item> -->
<div class="selectCheck">
<el-checkbox v-model="editInfoForm.checked" size="small">容器组
<el-checkbox v-model="checked" size="small">容器组
<span class="tips">Security Context的目的是限制不可信容器的行为保护系统和其他容器不受其影响</span>
</el-checkbox>
<div v-if="editInfoForm.checked">
<div v-if="checked">
<el-alert
title="容器组 Security Context 可以为容器组内的容器提供默认的用户和用户组设置以及 seLinuxOptions 的参数设置,如果容器中已经对这些参数进行了定义,则优先以容器中的设置为准。"
type="info"
@ -70,7 +78,7 @@
<el-row style="padding: 10px;margin:0 10px;border:1px solid #DCDFE6;font-size:0.7rem" :gutter="20">
<el-col :span="24">
<el-switch
v-model="editInfoForm.runAsNonRoot"
v-model="editInfoForm.spec.template.spec.securityContext.runAsNonRoot"
/>
仅允许非 Root 用户
<span class="tips">Kubernetes 在运行容器之前将执行检查以确保容器进程不是以 root 用户UID为0运行否则将不能启动容器</span>
@ -80,7 +88,7 @@
prop="runAsUser"
label="用户"
>
<el-input v-model="editInfoForm.runAsUser" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.runAsUser" />
<span class="tips">执行容器 entrypoint 进程的 UID默认为 docker 引擎的 GID</span>
</el-form-item>
</el-col>
@ -90,7 +98,7 @@
prop="runAsGroup"
label="用户组"
>
<el-input v-model="editInfoForm.runAsGroup" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.runAsGroup" />
<span class="tips">执行容器 entrypoint 进程的 GID默认为 docker 引擎的 GID</span>
</el-form-item>
</el-col>
@ -102,7 +110,7 @@
prop="level"
label="Level"
>
<el-input v-model="editInfoForm.level" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.seLinuxOptions.level" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -110,7 +118,7 @@
prop="role"
label="Role"
>
<el-input v-model="editInfoForm.role" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.seLinuxOptions.role" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -118,7 +126,7 @@
prop="type"
label="Type"
>
<el-input v-model="editInfoForm.type" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.seLinuxOptions.type" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -126,7 +134,7 @@
prop="user"
label="User"
>
<el-input v-model="editInfoForm.user" />
<el-input v-model="editInfoForm.spec.template.spec.securityContext.seLinuxOptions.user" />
</el-form-item>
</el-col>
</el-row>
@ -204,24 +212,38 @@ import { policysOptions, policysTypeOptions } from '@/utils/map'
import addContainerForm from '@/components/Actions/addContainerForm.vue'
export default {
components: { addContainerForm },
props: {
value: {
type: Object,
default: () => {}
}
},
data() {
return {
policysOptions,
policysTypeOptions,
namespaceOptions: [],
editInfoForm: {
num: 1,
maxUnavailable: '25%',
maxSurge: '25%'
},
// editInfoForm: {
// num: 1,
// maxUnavailable: '25%',
// maxSurge: '25%'
// },
checked: false,
rules: {},
editTagForm: [],
containerFormVisiable: false,
createContainerForm: {},
formData: {}
}
},
computed: {
editInfoForm: {
get() {
return this.value
},
set(value) {
this.$emit('input', value)
}
},
addTagNumCheck() {
let flag = false
this.editTagForm.forEach(e => {
@ -231,6 +253,7 @@ export default {
})
return flag
}
},
watch() {
// const customMode = this.editTagForm
@ -239,7 +262,13 @@ export default {
this.setFilterMapNamespaceList()
},
methods: {
addContainer() {},
addImage(data) {
this.editInfoForm.spec.template.spec.containers.push(data)
console.log(data)
},
editImage(data) {
console.log(data)
},
setFilterMapNamespaceList() {
this.$Api.getNamespaceList().then(res => {
const arr = res.items.map(e => { return { label: e.metadata.name, value: e.metadata.name } })

View File

@ -8,9 +8,9 @@
</el-steps>
{{ metaData }}
<basicInfoForm v-show="stepNum===0" v-model="metaData" />
<containerImage v-show="stepNum===1" :meta-data="metaData" />
<mountVolumes v-show="stepNum===2" :meta-data="metaData" />
<advancedSettings v-show="stepNum===3" :meta-data="metaData" />
<containerImage v-if="stepNum===1" v-model="metaData" />
<mountVolumes v-if="stepNum===2" v-model="metaData" />
<advancedSettings v-if="stepNum===3" v-model="metaData" />
<div slot="footer" class="dialog-footer">
<el-button @click="createFormVisible = false"> </el-button>
<el-button v-if="stepNum!==0" type="primary" @click="prev">上一步</el-button>

View File

@ -5,6 +5,9 @@
<!-- <h2 class="headTitle">国家重点研发计划</h2> -->
<div class="right-menu">
<router-link class="selectBtn" to="/clusterSelect">多集群管理</router-link>
<router-link class="selectBtn" to="/monitorSelect">计量计费</router-link>
<router-link class="selectBtn" to="/monitorSelect">资源管理</router-link>
<template v-if="device!=='mobile'">
<!-- <search id="header-search" class="right-menu-item" /> -->
@ -34,11 +37,11 @@
<router-link to="/prometheusMonitorNew">
<el-dropdown-item>数据监控总览</el-dropdown-item>
</router-link>
<div v-if="clusterName !== 'default'">
<!-- <div v-if="clusterName !== 'default'">
<router-link to="/">
<el-dropdown-item>多集群管理</el-dropdown-item>
</router-link>
</div>
</div> -->
<el-dropdown-item v-if="this.$route.path !== '/cluster'" @click.native="toMoniter">
用户资源监控
</el-dropdown-item>
@ -114,7 +117,17 @@ export default {
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
.selectBtn{
line-height: 67px;
height: 60px;
float: left;
border-right: 1px solid #eeeeee;
border-left: 1px solid #eeeeee;
padding: 0 20px;
}
.navbar .right-menu .right-menu-item.hover-effect{
margin-left: 10px;
}
.headTitle{
display: inline-block;
line-height: 2rem;

View File

@ -7,8 +7,7 @@
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<el-submenu v-if="(item.path.indexOf('/'+routesType)===0)" ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template>
@ -30,6 +29,7 @@ import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
import { mapGetters } from 'vuex'
export default {
name: 'SidebarItem',
@ -56,6 +56,11 @@ export default {
this.onlyOneChild = null
return {}
},
computed: {
...mapGetters([
'routesType'
])
},
methods: {
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {

View File

@ -1,11 +1,10 @@
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
import emptyLayout from '@/layout/emptyLayout'
// import emptyLayout from '@/layout/emptyLayout'
import podRouter from './modules/pod'
import virtualMachineRouter from './modules/virtualMachine'
import blockChainRouter from './modules/blockChain'
@ -42,6 +41,7 @@ import functionsRouter from './modules/functions'
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [
{
path: '/redirect',
@ -75,31 +75,30 @@ export const constantRoutes = [
hidden: true
},
{
path: '/',
component: emptyLayout,
redirect: 'cluster',
hidden: true,
children: [
{
path: 'cluster',
component: () => import('@/views/cluster/index'),
hidden: true
}
]
path: '/monitorSelect',
component: () => import('@/views/monitorSelect/index'),
hidden: true
},
{
path: '/cluster/overview',
component: Layout,
redirect: 'overview',
children: [
{
path: '',
component: () => import('@/views/overview/index'),
name: 'Overview',
meta: { title: '概览', icon: 'dashboard', affix: true }
}
]
path: '/clusterSelect',
component: () => import('@/views/cluster/index'),
hidden: true
// children: [
// {
// path: 'clusterSelect',
// hidden: true
// }
// ]
},
// {
// path: '/cluster/',
// component: Layout,
// redirect: 'overview',
// children: [
// ]
// },
{
path: '/prometheusMonitor',
component: () => import('@/views/prometheusMonitor/index'),

View File

@ -11,49 +11,24 @@ const blockChainRouter = {
children: [
{
path: 'blockChainBrowser',
component: emptyLayout,
redirect: 'blockChainBrowser',
children: [
{
path: '',
component: () => import('@/views/blockChain/blockChainBrowser'),
name: 'blockChainBrowser',
meta: { title: '块链浏览器', icon: 'el-icon-discover', affix: true },
hidden: false
}
// {
// path: 'detail',
// component: () => import('@/views/virtualMachine/hostDetailPanel'),
// name: 'detail',
// meta: { activeMenu: '/virtual/host' },
// hidden: true,
// children: [
// {
// path: '',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'overview',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'config',
// component: () => import('@/views/virtualMachine/hostConfig'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'yaml',
// component: () => import('@/views/virtualMachine/hostYAML'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// }
// ]
// }
]
component: () => import('@/views/blockChain/blockChainBrowser'),
name: 'blockChainBrowser',
meta: { title: '块链浏览器', icon: 'el-icon-discover', affix: true }
},
// {
// path: '',
// component: emptyLayout,
// redirect: 'blockChainBrowser',
// children: [
// {
// path: '',
// component: () => import('@/views/blockChain/blockChainBrowser'),
// name: 'blockChainBrowser',
// meta: { title: '块链浏览器', icon: 'el-icon-discover', affix: true },
// hidden: false
// }
// ]
// },
{
path: 'blockList',
component: emptyLayout,

View File

@ -0,0 +1,29 @@
import Layout from '@/layout'
import emptyLayout from '@/layout/emptyLayout'
const blockChainRouter = {
path: '/costStatistics',
component: Layout,
name: '费用统计',
meta: {
title: '费用统计',
icon: 'el-icon-share'
},
children: [
{
path: 'containerCost',
component: emptyLayout,
redirect: 'containerCost',
children: [
{
path: '',
component: () => import('@/views/costStatistics/containerCost'),
name: 'containerCost',
meta: { title: '容器费用统计', icon: 'el-icon-discover', affix: true },
hidden: false
}
]
}
]
}
export default blockChainRouter

View File

@ -8,40 +8,47 @@ const functionsRouter = {
title: '函数管理',
icon: 'el-icon-s-operation'
},
children: [{
path: 'functionList',
component: emptyLayout,
redirect: 'functionList',
children: [
{
path: '',
component: () => import('@/views/functionManagement/functionList'),
name: 'functionList',
meta: { title: '函数列表', icon: 'el-icon-s-opportunity', affix: true },
hidden: false
}
// {
// path: 'detail',
// component: () => import('@/views/virtualMachine/hostDetailPanel'),
// name: 'detail',
// meta: { activeMenu: '/virtual/host' },
// hidden: true,
// children: [
// {
// path: '',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'overview',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'config',
// component: () => import('@/views/virtualMachine/hostConfig'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
children: [
{
path: 'overview',
component: () => import('@/views/overview/function'),
name: 'functionsOverview',
meta: { title: '概览', icon: 'dashboard', affix: true }
},
{
path: 'functionList',
component: emptyLayout,
redirect: 'functionList',
children: [
{
path: 'functionList',
component: () => import('@/views/functionManagement/functionList'),
name: 'functionList',
meta: { title: '函数列表', icon: 'el-icon-s-opportunity', affix: true },
hidden: false
}
// {
// path: 'detail',
// component: () => import('@/views/virtualMachine/hostDetailPanel'),
// name: 'detail',
// meta: { activeMenu: '/virtual/host' },
// hidden: true,
// children: [
// {
// path: '',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'overview',
// component: () => import('@/views/virtualMachine/hostDetail'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'config',
// component: () => import('@/views/virtualMachine/hostConfig'),
// meta: { activeMenu: '/virtual/host', keepAlive: true }
// },
// {
// path: 'yaml',
@ -50,7 +57,7 @@ const functionsRouter = {
// }
// ]
// }
]
}]
]
}]
}
export default functionsRouter

View File

@ -10,6 +10,12 @@ const podRouter = {
icon: 'el-icon-s-claim'
},
children: [
{
path: 'overview',
component: () => import('@/views/overview/index'),
name: 'clusterOverview',
meta: { title: '概览', icon: 'dashboard', affix: true }
},
{
path: 'nodeManagement',
component: emptyLayout,

View File

@ -8,175 +8,182 @@ const virtualMachineRouter = {
title: '虚拟机管理',
icon: 'el-icon-s-finance'
},
children: [{
path: 'host',
component: emptyLayout,
redirect: 'host',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/virtualHost'),
name: 'host',
meta: { title: '主机', icon: 'el-icon-s-platform', affix: true },
hidden: false
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/hostDetailPanel'),
meta: { activeMenu: '/virtual/host' },
hidden: true,
children: [
{
path: '',
name: 'hostDetail',
component: () => import('@/views/virtualMachine/hostDetail'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/hostDetail'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/hostConfig'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
children: [
{
path: 'overview',
component: () => import('@/views/overview/virtualMachine'),
name: 'virtualOverview',
meta: { title: '概览', icon: 'dashboard', affix: true }
},
{
path: 'host',
component: emptyLayout,
redirect: 'host',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/virtualHost'),
name: 'host',
meta: { title: '主机', icon: 'el-icon-s-platform', affix: true },
hidden: false
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/hostDetailPanel'),
meta: { activeMenu: '/virtual/host' },
hidden: true,
children: [
{
path: '',
name: 'hostDetail',
component: () => import('@/views/virtualMachine/hostDetail'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/hostDetail'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/hostConfig'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
},
{
path: 'yaml',
component: () => import('@/views/virtualMachine/hostYAML'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
}
]
}
]
},
{
path: 'virtual-machine',
component: emptyLayout,
redirect: 'virtual-machine',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/virtualMachine'),
name: 'virtual-machine',
meta: { title: '虚拟机', icon: 'el-icon-monitor', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/virtualMachineCreate.vue'),
name: 'virtualMachineCreate',
meta: { activeMenu: '/virtual/virtual-machine' },
hidden: true
},
{
path: 'info',
component: () => import('@/views/virtualMachine/virtualMachineDetailPanel'),
name: 'info',
meta: { activeMenu: '/virtual/virtual-machine' },
hidden: true
}
]
},
{
path: 'dataVolume',
component: emptyLayout,
redirect: 'dataVolume',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/datavolumes.vue'),
name: 'dataVolume',
meta: { title: '卷', icon: 'el-icon-box', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/datavolumeCreate.vue'),
name: 'dataVolumeCreate',
meta: { activeMenu: '/virtual/dataVolume' },
hidden: true
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/datavolumeDetailPanel'),
meta: { activeMenu: '/virtual/dataVolume' },
hidden: true,
children: [
{
path: '',
name: 'datavolumeDetail',
component: () => import('@/views/virtualMachine/datavolumeDetail'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/datavolumeDetail'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/datavolumeConfig'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'yaml',
component: () => import('@/views/virtualMachine/datavolumeYAML'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
}]
}
]
},
{
path: 'images',
component: emptyLayout,
redirect: 'images',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/images.vue'),
name: 'images',
meta: { title: '镜像', icon: 'el-icon-picture-outline', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/imagesCreate.vue'),
name: 'imagesCreate',
meta: { activeMenu: '/virtual/images' },
hidden: true
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/imagesDetailPanel.vue'),
meta: { activeMenu: '/virtual/images' },
hidden: true,
children: [
{
path: '',
name: 'imagesDetail',
component: () => import('@/views/virtualMachine/imagesDetail'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/imagesDetail'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/imagesConfig'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'yaml',
component: () => import('@/views/virtualMachine/imagesYAML'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
}]
}
]
}]
{
path: 'yaml',
component: () => import('@/views/virtualMachine/hostYAML'),
meta: { activeMenu: '/virtual/host', keepAlive: true }
}
]
}
]
},
{
path: 'virtual-machine',
component: emptyLayout,
redirect: 'virtual-machine',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/virtualMachine'),
name: 'virtual-machine',
meta: { title: '虚拟机', icon: 'el-icon-monitor', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/virtualMachineCreate.vue'),
name: 'virtualMachineCreate',
meta: { activeMenu: '/virtual/virtual-machine' },
hidden: true
},
{
path: 'info',
component: () => import('@/views/virtualMachine/virtualMachineDetailPanel'),
name: 'info',
meta: { activeMenu: '/virtual/virtual-machine' },
hidden: true
}
]
},
{
path: 'dataVolume',
component: emptyLayout,
redirect: 'dataVolume',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/datavolumes.vue'),
name: 'dataVolume',
meta: { title: '卷', icon: 'el-icon-box', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/datavolumeCreate.vue'),
name: 'dataVolumeCreate',
meta: { activeMenu: '/virtual/dataVolume' },
hidden: true
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/datavolumeDetailPanel'),
meta: { activeMenu: '/virtual/dataVolume' },
hidden: true,
children: [
{
path: '',
name: 'datavolumeDetail',
component: () => import('@/views/virtualMachine/datavolumeDetail'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/datavolumeDetail'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/datavolumeConfig'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
},
{
path: 'yaml',
component: () => import('@/views/virtualMachine/datavolumeYAML'),
meta: { activeMenu: '/virtual/dataVolume', keepAlive: true }
}]
}
]
},
{
path: 'images',
component: emptyLayout,
redirect: 'images',
children: [
{
path: '',
component: () => import('@/views/virtualMachine/images.vue'),
name: 'images',
meta: { title: '镜像', icon: 'el-icon-picture-outline', affix: true },
hidden: false
},
{
path: 'create',
component: () => import('@/views/virtualMachine/imagesCreate.vue'),
name: 'imagesCreate',
meta: { activeMenu: '/virtual/images' },
hidden: true
},
{
path: 'detail',
component: () => import('@/views/virtualMachine/imagesDetailPanel.vue'),
meta: { activeMenu: '/virtual/images' },
hidden: true,
children: [
{
path: '',
name: 'imagesDetail',
component: () => import('@/views/virtualMachine/imagesDetail'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'overview',
component: () => import('@/views/virtualMachine/imagesDetail'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'config',
component: () => import('@/views/virtualMachine/imagesConfig'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
},
{
path: 'yaml',
component: () => import('@/views/virtualMachine/imagesYAML'),
meta: { activeMenu: '/virtual/images', keepAlive: true }
}]
}
]
}]
}
export default virtualMachineRouter

View File

@ -10,6 +10,7 @@ const getters = {
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permission_routes: state => state.permission.routes,
routesType: state => state.user.routesType,
errorLogs: state => state.errorLog.logs,
clusterName: state => state.cluster.clusterName
}

View File

@ -1,4 +1,4 @@
import { login, harvesterLogin, blockChainLogin } from '@/api/user'
import { login, blockChainLogin } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
@ -7,7 +7,8 @@ const state = {
name: '',
avatar: '',
introduction: '',
roles: []
roles: [],
routesType: localStorage.getItem('routesType') || 'cluster'
}
const mutations = {
@ -25,6 +26,9 @@ const mutations = {
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_ROUTESTYPE: (state, routesType) => {
state.routesType = routesType
}
}
function encrypt(salt, str) {
@ -53,14 +57,14 @@ const actions = {
const { username, password } = userInfo
return Promise.all([
login({ 'username': username.trim(), 'encrypt': encrypt('kubesphere', password) }),
harvesterLogin({ 'username': 'admin', 'password': 'Nudt@123', 'description': 'UI Session', 'responseType': 'cookie', 'ttl': 57600000 }),
// harvesterLogin({ 'username': 'admin', 'password': 'Nudt@123', 'description': 'UI Session', 'responseType': 'cookie', 'ttl': 57600000 }),
blockChainLogin({
'user': 'exploreradmin',
'password': 'exploreradminpw',
'network': 'agridepart-network'
})]).then(response => {
commit('SET_TOKEN', response[2].token)
setToken(response[2].token)
commit('SET_TOKEN', response[1].token)
setToken(response[1].token)
// Cookies.set('bToken', response[2].token)
})
},
@ -99,6 +103,14 @@ const actions = {
})
},
setRouteType({ commit }, type) {
// return new Promise((resolve, reject) => {
// logout(state.token).then(() => {
commit('SET_ROUTESTYPE', type)
localStorage.setItem('routesType', type)
// })
},
// user logout
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {

View File

@ -1,3 +1,4 @@
const statusOptions = [
{ label: '不限', value: '' },
{ label: '运行中', value: 'running' },
@ -21,9 +22,41 @@ const mountOptions = [
{ label: '不挂载', value: 'null' }
]
const imagePullPolicyOptions = [
{
label: '尝试重新下载镜像Always',
value: 'Always',
description: '在创建及更新时,每次都会尝试下载新的镜像'
},
{
label: '优先使用本地镜像IfNotPresent',
value: 'IfNotPresent',
description: '如果本地存在镜像就优先使用本地镜像'
},
{
label: '仅使用本地镜像Never',
value: 'Never',
description: '仅会使用本地镜像,如果本地不存在所需镜像,则会导致容器异常'
}
]
const protocolOptions = [
{ label: 'GRPC', value: 'GRPC' },
{ label: 'HTTP', value: 'HTTP' },
{ label: 'HTTP2', value: 'HTTP2' },
{ label: 'HTTPS', value: 'HTTPS' },
{ label: 'MONGO', value: 'MONGO' },
{ label: 'REDIS', value: 'REDIS' },
{ label: 'TCP', value: 'TCP' },
{ label: 'TLS', value: 'TLS' },
{ label: 'UDP', value: 'UDP' }
]
export {
statusOptions,
policysOptions,
policysTypeOptions,
mountOptions
mountOptions,
imagePullPolicyOptions,
protocolOptions
}

View File

View File

@ -0,0 +1,74 @@
<template>
<el-row :gutter="20">
<el-col :span="12">
<div :class="['costNumMark', 'blue']">
<div>
<div class="bigNum">4262052.339</div>
<p>CPU消费Core</p>
</div>
<div>
<div class="bigNum">1945.299</div>
<p>内存消费Gi</p>
</div>
<div>
<div class="bigNum">391659.532</div>
<p>网络流入消费M</p>
</div>
<div>
<div class="bigNum">50421.807</div>
<p>网络流出消费M</p>
</div>
</div>
</el-col>
<el-col :span="12">
<div :class="['costNumMark', 'green']">
<div>
<div class="bigNum">3409641.87</div>
<p>CPU 消费()</p>
</div>
<div>
<div class="bigNum">2528.89</div>
<p>内存 消费()</p>
</div>
<div>
<div class="bigNum">3133.28</div>
<p>网络流入 消费()</p>
</div>
<div>
<div class="bigNum">15.39</div>
<p>网络流出 消费()</p>
</div>
</div>
</el-col>
</el-row>
</template>
<script>
export default {
}
</script>
<style lang="scss">
.costNumMark{
padding: 5px 20px;
border-radius: 5px;
font-size: 12px;
line-height: 20px;
padding: 21px 40px 0 40px;
color: #000000;
>div{
width: 33.3%;
display: inline-block;
p{
margin: 0;
margin-bottom: 21px;
color: #666666;
}
}
}
.green{
background-color: #00d9a611;
border-left: 4px solid #00d9a6;
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<div id="lineChart" ref="lineChart" style="height:300px" />
</template>
<script>
import * as echarts from 'echarts'
export default {
data() {
return {
chartOption: {
xAxis: {
type: 'category',
boundaryGap: false,
axisLine: { lineStyle: { color: '#999999' }},
data: []
// data: createdTime
},
yAxis: {
type: 'value',
axisLine: { lineStyle: { color: '#999999' }}
},
series: [{
// data: createCount,
data: [],
type: 'line',
itemStyle: {
color: 'rgba(0, 55, 255, 1)'
},
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#409eff' // 0%
}, {
offset: 1, color: 'white' // 100%
}],
global: false // false
}
}
}]
},
lineChart: null
}
},
mounted() {
this.lineChart = echarts.init(this.$refs.lineChart)
this.lineChart.setOption(this.chartOption)
},
methods: {
setChart(option) {
this.lineChart.setOption(option)
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,70 @@
<template>
<div id="gaugeChart" ref="gaugeChart" style="height:300px" />
</template>
<script>
import * as echarts from 'echarts'
export default {
data() {
return {
option: {
title: {
text: `{v|k8s-node1}\n\n{t|${'34.35%'}}`,
x: 'center',
y: 'center',
textStyle: {
rich: {
v: { fontSize: 14, color: '#333333' },
t: { fontFamily: 'Impact', fontSize: 30, color: '#333333' }
}
}
},
color: ['#0097FB',
'#92E1FF',
'#FFC227',
'#30ECA6',
'#FDFA4E',
'#FF4848'],
series: [
{
name: '标签使用频率',
type: 'pie',
radius: ['55%', '75%'],
center: ['50%', '50%'],
roseType: 'radius',
label: {
show: false
},
emphasis: {
label: {
show: false
}
},
itemStyle: {
shadowBlur: 1,
shadowColor: 2,
shadowOffsetX: 5,
shadowOffsetY: 5
},
data: [21, 32, 43, 64, 55]
}
]
},
gaugeChart: null
}
},
mounted() {
this.gaugeChart = echarts.init(this.$refs.gaugeChart)
this.gaugeChart.setOption(this.option, true)
},
methods: {
setChart(option) {
this.lineChart.setOption(option)
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,324 @@
<template>
<div>
<el-row>
<el-col :span="4">
<el-card shadow="never" style="height:1000px">
<h4>集群选择</h4>
<el-tree
ref="tree"
node-key="id"
:load="loadNode"
lazy
:props="props"
show-checkbox
/>
</el-card>
</el-col>
<el-col :span="20">
<el-row>
<el-col :span="24">
<el-card shadow="never">
<h4>消费账单</h4>
<span class="tips">
集群host1自创建以来共消费
<span class="tip-num">¥3415319.43</span>
</span>
<CostDiv />
</el-card>
</el-col>
<el-col :span="16">
<el-card shadow="never">
<h4>截止到昨天的消费历史</h4>
<div class="change">
对账周期
<el-date-picker
v-model="value1"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</div>
<LineChart ref="lineChart" />
<List
ref="multipleTable"
class="multipleTable"
:columns="columns"
:table-list-data="[{
name:'111'
},{
name:'111'
},{
name:'111'
}]"
:cluster-name="clusterName"
:pagination="false"
tooltip-effect="dark"
/>
</el-card>
</el-col>
<el-col :span="8">
<el-card shadow="never">
<h4>当前包含的资源</h4>
<div class="change">
<el-select v-model="metrics_filter" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<PieChart ref="pieChart" />
<div v-for="item in nodes" :key="item.name +'nodes'" class="nodes-div">
<div>
<img :src="item.imgSrc" style="width: 52px">
<div>
<div class="name"> {{ item.name }}</div>
<div class="node">集群节点</div>
</div>
</div>
<div>{{ item.value }} Core </div>
</div>
</el-card>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script>
import List from '@/components/list'
import CostDiv from './components/CostDiv'
import LineChart from './components/LineChart'
import PieChart from './components/PieChart'
// import { numberToStr } from '@/utils/data-process'
import { getClusterList, getNodeList, getBillNum, getResource } from '@/api/one-class-page/costStatistics'
export default {
components: { List, LineChart, PieChart, CostDiv },
data() {
return {
value1: '',
metrics_filter: 'meter_node_cpu_usage',
options: [{
value: 'meter_node_cpu_usage',
label: 'CPU 消费'
}, {
value: 'meter_node_memory_usage_wo_cache',
label: '内存 消费'
}, {
value: 'meter_node_pvc_bytes_total',
label: '存储卷 消费'
}, {
value: 'meter_node_net_bytes_received',
label: '网络流入 消费'
}, {
value: 'meter_node_net_bytes_transmitted',
label: '网络流出 消费'
}],
currentCluster: '',
props: {
isLeaf: 'leaf',
children: 'zones'
},
nodes: [],
columns: [
{
prop: 'state',
label: '资源类型'
},
{ prop: 'name', label: '最大用量', formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
{ prop: 'hostIP', label: '最小用量' },
{ prop: 'cpu', label: '平均用量', formatter: (row) => { return <div>{row.cpuAll}</div> } },
{ prop: 'memory', label: '共消费', formatter: (row) => { return <div>{row.memoryAll}</div> } },
{ prop: 'storageSize', label: '价格', formatter: (row) => { return <div>{row.storageAll}</div> } }
]
}
},
computed: {
clusterName() {
if (localStorage.getItem('clusterName') === 'default') {
return ''
} else {
return '/clusters/' + localStorage.getItem('clusterName')
}
}
},
mounted() {
},
methods: {
//
async loadNode(node, resolve) {
//
if (node.level === 0) {
const array = []
// host
getClusterList({
page: 1,
limit: -1,
labelSelector: 'cluster-role.kubesphere.io/host',
sortBy: 'createTime'
}).then(res => {
if (res.items.length > 0) {
res.items.forEach(n =>
array.push({
id: n.metadata.uid,
label: n.metadata.name,
children: []
})
)
this.currentCluster = array[0].label
// this.getHistory(array[0].label)
this.getResources(array[0].label)
// this.getBill(array[0].label)
}
})
// member
await getClusterList({
page: 1,
limit: -1,
labelSelector: '!cluster-role.kubesphere.io/host',
sortBy: 'createTime'
}).then(res => {
if (res.items.length > 0) {
res.items.forEach(n =>
array.push({
id: n.metadata.uid,
label: n.metadata.name,
children: []
})
)
}
})
return resolve(array)
}
//
if (node.level === 1) {
getNodeList(node.data.label).then(res => {
let array = []
if (res.items.length > 0) {
array = res.items.map(n => ({
id: n.metadata.uid,
label: n.metadata.name,
children: [],
leaf: true
}))
}
return resolve(array)
})
}
return resolve([])
},
//
getBill(name) {
getBillNum({
start: '1641398400',
end: '1642003200',
step: '3600s',
metrics_filter: 'meter_cluster_cpu_usage|meter_cluster_memory_usage|meter_cluster_net_bytes_transmitted|meter_cluster_net_bytes_received|meter_cluster_pvc_bytes_total',
resources_filter: name
}).then(res => {
console.log(res)
})
},
getImg(num) {
return require('@/assets/img/node' + num + '.png')
},
//
getHistory(name) {
// getClusterList({
// start: '1641398400',
// end: '1642003200',
// step: '3600s',
// metrics_filter: 'meter_cluster_cpu_usage|meter_cluster_memory_usage|meter_cluster_net_bytes_transmitted|meter_cluster_net_bytes_received|meter_cluster_pvc_bytes_total',
// resources_filter: name
// }).then(res => {
// console.log(res)
const data = [{ 'createdTime': '2021-12-16', 'createCount': 0 }, { 'createdTime': '2021-12-17', 'createCount': 0 }, { 'createdTime': '2021-12-18', 'createCount': 0 }, { 'createdTime': '2021-12-19', 'createCount': 0 }, { 'createdTime': '2021-12-20', 'createCount': 0 }, { 'createdTime': '2021-12-21', 'createCount': 0 }, { 'createdTime': '2021-12-22', 'createCount': 0 }]
const createCount = data.map(i => i.createCount)
const createdTime = data.map(i => i.createdTime)
this.$refs.lineChart.setChart({
xAxis: {
data: createdTime
},
series: [{
data: createCount
}]
})
// })
},
//
getResources(name) {
getResource({
clusterName: name,
metrics_filter: this.metrics_filter,
resources_filter: 'k8s-node4|k8s-node3|k8s-node2|k8s-node1|k8s-master'
}).then(res => {
const { results } = res
const { data: { result }} = results?.[0]
console.log(result)
// const
if (result.length > 0) {
this.nodes = result.map((n, index) => ({
name: n.metric.node,
value: n.avg_value,
imgSrc: this.getImg(index < 4 ? (index + 1) : (index - 3))
}))
}
})
}
}
}
</script>
<style lang="scss">
.tips{
margin: 20px 0;
display: flex !important;
align-items: center;
.tip-num{
font-size: 32px;
color: #419EFF;
font-family: Impact;
margin-left: 20px;
letter-spacing: 1px;
}
}
.change{
padding: 17px 19px;
background: #F7F7F7;
font-size: 14px;
}
.blue{
background-color: #419eff11;
border-left: 4px solid #419eff;
}
.bigNum{
font-size: 20px;
font-weight: bold;
}
.nodes-div{
display: flex;
justify-content: space-between;
>div{
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
.name{
font-weight: bold;
font-size: 16px;
}
.node{
font-size: 14px;
color: #999999;
line-height: 18px;
}
img{
margin-right: 20px;
}
}
}
</style>

View File

@ -1,26 +1,14 @@
<template>
<div class="cloudComputation">
<el-card class="basicInfo" shadow="never">
<img src="@/assets/img/pod.png" class="sidebar-logo" alt="容器组">
<h4>函数</h4>
<span class="tips" />
</el-card>
<el-card shadow="never">
<el-button style="margin-top:30px" type="primary" @click="dialogCreateVisible=true">创建函数</el-button>
<el-row :gutter="30">
<el-col v-for="(item,index) in functionList" :key="index" :span="6">
<el-card class="functionCard">
<p class="title">{{ item.functionName }}
<el-button
type="text"
class="insideFloatRight"
@click="goDetail(item)"
>details</el-button>
</p>
<el-divider />
<p>env: {{ item.runEnv }}</p>
<p>memory: {{ item.memorySize }}</p>
<p>timeout: {{ item.timeout }}</p>
<div class="functionList">
<el-button class="opr-btn" size="middle" type="primary" @click="dialogCreateVisible=true">创建函数</el-button>
<el-row :gutter="20">
<el-col v-for="(item,index) in functionList" :key="index" :span="6">
<el-card shadow="never" class="functionCard">
<p class="title">{{ item.functionName }}</p>
<p>运行环境 {{ item.runEnv }}</p>
<p>内存大小 {{ item.memorySize }}</p>
<p>超时 {{ item.timeout }}</p>
<div class="btn-group">
<el-popconfirm
confirm-button-text="好的"
cancel-button-text="不用了"
@ -29,123 +17,132 @@
title="确认删除此函数么?"
@onConfirm="deleteFunc(item.functionId)"
>
<el-button slot="reference" type="danger" size="small">删除</el-button>
<el-button slot="reference" size="small">删除</el-button>
</el-popconfirm>
</el-card>
</el-col>
</el-row>
<el-pagination
background
:hide-on-single-page="true"
:current-page="page"
layout="prev, pager, next"
:total="total"
@current-change="currentChange"
/>
<el-dialog :visible.sync="dialogCreateVisible" title="创建函数" width="80%">
<div class="bg-gray">
<el-row :gutter="30">
<el-col :span="12">
<el-form ref="form" v-model="form" label-width="150px">
<el-form-item label="Function Name:" prop="functionName">
<el-input v-model="form.functionName" :maxlength="50" />
</el-form-item>
<el-form-item label="Env:">
<el-select v-model="form.runEnv" placeholder="请选择">
<el-option label="java8" value="java8" />
<el-option label="python3" value="python3" />
</el-select>
</el-form-item>
<el-form-item label="TimeOut(1-300s):">
<el-input v-model="form.timeout" :maxlength="3" />
</el-form-item>
<el-form-item label="Memory Size(128-1024MB):">
<el-input v-model="form.memorySize" :maxlength="4" />
</el-form-item>
</el-form>
</el-col>
<el-col :span="12">
<span class="el-form-item__label">Entrypoint:</span>
<div v-if="form.runEnv==='python3'" class="codemirror">
<codemirror v-model="code" :options="cmOption" />
</div>
<div v-if="form.runEnv === 'java8'">
<el-upload
class="upload-demo"
action="#"
:http-request="httpRequest"
:limit="1"
:file-list="fileList"
>
<el-button size="small" type="primary">上传jar包</el-button>
<div slot="tip" class="el-upload__tip">只能上传jar文件</div>
</el-upload>
</div>
</el-col>
</el-row>
<el-button @click="createFunc">下一步</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogExecuteVisible" title="提交运行">
<div class="bg-gray">
<table class="el-table funcTable">
<tr>
<td>Function Name:</td>
<td :colspan="3">{{ form.functionName }}</td>
<td>Created Time:</td>
<td>{{ form.createTime }}</td>
</tr>
<tr>
<td>Env:</td>
<td>{{ form.runEnv }}</td>
<td>Memory Size:</td>
<td>{{ form.memorySize }}</td>
<td>Timeout:</td>
<td>{{ form.timeout }}</td>
</tr>
<tr>
<td>Code Size:</td>
<td>{{ form.codeSize }}</td>
<td>Code Checksum:</td>
<td :colspan="3">{{ form.codeChecksum }}</td>
</tr>
<tr>
<td>Description</td>
<td :colspan="5">{{ form.description }}</td>
</tr>
<tr>
<td>EnviromentVariable:</td>
<td :colspan="2">{{ form.envVar }}</td>
<td :colspan="3">
<!-- Enable Native Serverless:
<el-button
type="primary"
@click="goDetail(item)"
>函数查看</el-button>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
background
:hide-on-single-page="true"
:current-page="page"
layout="prev, pager, next"
:total="total"
@current-change="currentChange"
/>
<el-dialog :visible.sync="dialogCreateVisible" title="创建函数" width="80%">
<!-- <el-steps :active="active">
<el-step title="步骤 1" />
<el-step title="步骤 2" />
<el-step title="步骤 3" />
</el-steps> -->
<div class="bg-gray">
<el-row :gutter="30">
<el-col :span="12">
<el-form ref="form" v-model="form" label-width="150px">
<el-form-item label="函数名称:" prop="functionName">
<el-input v-model="form.functionName" :maxlength="50" />
</el-form-item>
<el-form-item label="运行环境:">
<el-select v-model="form.runEnv" placeholder="请选择">
<el-option label="java8" value="java8" />
<el-option label="python3" value="python3" />
</el-select>
</el-form-item>
<el-form-item label="超时(1-300s):">
<el-input v-model="form.timeout" :maxlength="3" />
</el-form-item>
<el-form-item label="内存大小(128-1024MB):">
<el-input v-model="form.memorySize" :maxlength="4" />
</el-form-item>
</el-form>
</el-col>
<el-col :span="12">
<span class="el-form-item__label">Entrypoint:</span>
<div v-if="form.runEnv==='python3'" class="codemirror">
<codemirror v-model="code" :options="cmOption" />
</div>
<div v-if="form.runEnv === 'java8'">
<el-upload
class="upload-demo"
action="#"
:http-request="httpRequest"
:limit="1"
:file-list="fileList"
>
<el-button size="small" type="primary">上传jar包</el-button>
<div slot="tip" class="el-upload__tip">只能上传jar文件</div>
</el-upload>
</div>
</el-col>
</el-row>
<el-button @click="createFunc">下一步</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogExecuteVisible" title="函数详情">
<div class="bg-gray">
<table class="el-table funcTable">
<tr>
<td>Function Name:</td>
<td :colspan="3">{{ form.functionName }}</td>
<td>Created Time:</td>
<td>{{ form.createTime }}</td>
</tr>
<tr>
<td>Env:</td>
<td>{{ form.runEnv }}</td>
<td>Memory Size:</td>
<td>{{ form.memorySize }}</td>
<td>Timeout:</td>
<td>{{ form.timeout }}</td>
</tr>
<tr>
<td>Code Size:</td>
<td>{{ form.codeSize }}</td>
<td>Code Checksum:</td>
<td :colspan="3">{{ form.codeChecksum }}</td>
</tr>
<tr>
<td>Description</td>
<td :colspan="5">{{ form.description }}</td>
</tr>
<tr>
<td>EnviromentVariable:</td>
<td :colspan="2">{{ form.envVar }}</td>
<td :colspan="3">
<!-- Enable Native Serverless:
<el-switch
v-model="form.enableNS"
size="small">
</el-switch> -->
</td>
</tr>
</table>
<el-row style="margin-bottom:30px" :gutter="30">
<el-col :span="9">
<p>Args</p>
<el-input
v-model="jsonObject"
type="textarea"
rows="6"
/>
</el-col>
<el-col :span="2" :offset="1">
<el-button class="invokeBtn" @click="invoke">invoke</el-button>
</el-col>
<el-col :offset="1" :span="9">
<p>函数返回值</p>
<el-input v-model="result" rows="6" type="textarea" readonly />
</el-col>
</el-row>
<!-- <el-button @click="getResult">查看过程</el-button> -->
</div>
</el-dialog>
</el-card>
</td>
</tr>
</table>
<el-row style="margin-bottom:30px" :gutter="30">
<el-col :span="9">
<p>Args</p>
<el-input
v-model="jsonObject"
type="textarea"
rows="6"
/>
</el-col>
<el-col :span="2" :offset="1">
<el-button class="invokeBtn" type="primary" @click="invoke">invoke</el-button>
</el-col>
<el-col :offset="1" :span="9">
<p>函数返回值</p>
<el-input v-model="result" rows="6" type="textarea" readonly />
</el-col>
</el-row>
<!-- <el-button @click="getResult">查看过程</el-button> -->
</div>
</el-dialog>
</div>
</template>
@ -170,6 +167,7 @@ export default {
},
data() {
return {
active: 1,
dialogCreateVisible: false,
dialogExecuteVisible: false,
interval: '',
@ -197,7 +195,7 @@ export default {
functionList: [], //
fileList: [],
page: 1,
size: 10,
size: 12,
total: 0
}
},
@ -298,7 +296,57 @@ export default {
</script>
<style lang="scss">
.cloudComputation{
.functionList{
margin: 30px 20px;
.opr-btn{
font-size: 16px;
padding: 10px 36px;
margin-bottom: 30px;
}
.el-button--primary{
background-color: #468EFC;
}
.el-card{
border: 1px solid #EEEEEE;
border-radius: 5px;
margin-top:0;
.btn-group{
width: 100%;
padding: 10px 30px;
}
.el-button{
width: 45%;
margin:0
}
.el-popover__reference{
margin-right: 10%;
}
}
.el-steps{
width: 80%;
margin: auto;
.el-step__icon.is-text{
background: #BCBCBC;
color: #ffffff;
border-color:#BCBCBC;
}
.el-step__head.is-finish .is-text{
border-color:#468EFC;
background: #468EFC;
}
.el-step.is-horizontal .el-step__line {
top: 11px;
height: 1px;
background: #DFDFDF;
left: 10%;
right: 0;
width: 85%;
}
}
}
.functionList{
.el-tabs__header{
margin-bottom: 0;
}
@ -334,7 +382,7 @@ export default {
margin: 30px auto;
}
.invokeBtn{
margin: 40px auto;
margin: 60px auto;
}
}
.functionCard{
@ -345,19 +393,45 @@ export default {
padding-bottom: 20px;
text-align: center;
}
p{
margin: 10px 30px;
font-size: 14px;
text-align: left;
position: relative;
text-indent: 1em;
}
p:before{
content: '';
position: absolute;
width: 8px;
height: 8px;
background: #2FB4AA;
border-radius: 50%;
top: 5px;
left: 0em;
}
.title{
margin:20px;
margin-bottom: 10px;
margin:20px 27px;
// margin-bottom: 10px;
font-size: 18px;
text-indent: 0;
font-weight: bold;
}
.title:before{
width: 0;
height: 0;
}
.el-button--text{
line-height: 1.1rem;
}
p{
margin: 10px 20px;
// margin-bottom: 10px;
}
.el-button{
margin:10px;
border:1px solid #468EFC ;
border-radius: 0;
}
.el-button--default{
color: #468EFC;
}
.insideFloatRight {
margin: 0;

View File

@ -181,10 +181,14 @@ export default {
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
this.$message.success('登录成功')
if (localStorage.getItem('clusterName')) {
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
if (this.redirect) {
if (this.redirect.indexOf('cluster') && !localStorage.getItem('clusterName')) {
this.$router.push({ path: '/clusterSelect' })
} else {
this.$router.push({ path: this.redirect, query: this.otherQuery })
}
} else {
this.$router.push({ path: '/cluster' })
this.$router.push({ path: '/monitorSelect' })
}
this.loading = false
})

View File

@ -0,0 +1,63 @@
<template>
<div class="monitor-select">
<Navbar />
<el-row :gutter="20">
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/cluster/overview')">
<p>容器管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/virtual/overview')">
<p>虚拟机管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/functions/overview')">
<p>函数管理</p>
</a>
</el-col>
<el-col :span="6">
<a class="monitorSelectBtn" @click="selectMonitor('/blockChain/blockChainBrowser')">
<p>块链管理</p>
</a>
</el-col>
</el-row>
</div>
</template>
<script>
import Navbar from '@/layout/components/Navbar'
export default {
name: 'MonitorSelect',
components: { Navbar },
data() {
return {
}
},
created() {
},
methods: {
selectMonitor(monitor) {
this.$store.dispatch('user/setRouteType', monitor.split('/')[1])
this.$router.push({ path: monitor })
}
}
}
</script>
<style lang="scss">
.monitor-select{
.el-col a{
display: block;
width: 80%;
margin: 30px auto;
height: 80vh;
padding: 30px;
border: 1px solid #419ef4;
border-radius: 30px;
font-size: 24px;
}
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div class="functionOverview">
<el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/hanshu-.png">
<h4>函数概览</h4>
</el-card>
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>函数调用概览</span>
</div>
<div v-for="(value,key) in dataMap" :key="key" class="overviewInfo">
<span>
{{ value }}
</span>
<p>{{ data[key] }}</p>
</div>
<!-- <FormData :column="3" :data="data" :data-map="dataMap" /> -->
</el-card>
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>函数监控(日创建次数)</span>
</div>
<div id="lineChart" ref="lineChart" />
</el-card>
</div>
</template>
<script>
// import { FormData } from '@/components/FormData'
import * as echarts from 'echarts'
export default {
// components: { FormData },
data() {
return {
data: {
allInstanceConcurrency: 0,
allCodeSize: '200Mb',
allTimeout: '2000s'
},
dataMap: {
allInstanceConcurrency: '总单实例并发度',
allCodeSize: '函数总代码大小',
allTimeout: '函数执行总超时时长'
}
}
},
mounted() {
this.getOverview()
this.initChart()
},
methods: {
getOverview() {
this.$Api.getFunctionOverview().then(res => {
this.data = res.data
this.data.allCodeSize = this.data.allCodeSize + 'Mb'
this.data.allTimeout = this.data.allTimeout + 's'
})
},
initChart() {
this.$Api.getFunctionMap().then(res => {
const createCount = res.data.map(i => i.createCount)
const createdTime = res.data.map(i => i.createdTime)
const chartOption = {
xAxis: {
type: 'category',
boundaryGap: false,
axisLine: { lineStyle: { color: '#999999' }},
data: createdTime
},
yAxis: {
type: 'value',
axisLine: { lineStyle: { color: '#999999' }}
},
series: [{
data: createCount,
type: 'line',
itemStyle: {
color: 'rgba(0, 55, 255, 1)'
},
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#409eff' // 0%
}, {
offset: 1, color: 'white' // 100%
}],
global: false // false
}
}
}]
}
const lineChart = echarts.init(this.$refs.lineChart)
lineChart.setOption(chartOption)
})
}
}
}
</script>
<style lang="scss" >
.functionOverview{
.el-card{
margin-bottom: 20px;
}
.el-card .el-card__header{
font-size: 16px;
padding-top: 30px;
}
.overviewInfo{
width: 219px;
height: 131px;
display: inline-block;
margin-right: 30px;
margin-bottom: 10px;
background: #F7F7F7;
border-radius: 10px;
padding:42px 20px;
position: relative;
span{color: #505879;}
p{
font-size: 20px;
font-weight: bold;
margin-top: 15px;
}
}
.overviewInfo:before{
content: '';
width: 42px;
height: 4px;
background: #468EFC;
position: absolute;
top: 22px;
left: 20px;
}
#lineChart{
width: 100%;
height: 35vh;
}
}
</style>

View File

@ -1,41 +1,19 @@
<template>
<div>
<el-tabs v-model="activeName" class="overviewTabs">
<el-tab-pane name="first">
<el-card slot="label" class="overviewTab" shadow="never">
<img v-if="activeName==='first'" src="@/assets/img/xnj-.png">
<img v-else src="@/assets/img/xnj.png">
<h4>虚拟机概览</h4>
</el-card>
<VirtualMachine />
</el-tab-pane>
<el-tab-pane name="second">
<el-card slot="label" class="overviewTab" shadow="never">
<img v-if="activeName==='second'" src="@/assets/img/rq.png">
<img v-else src="@/assets/img/rq-.png">
<h4>容器概览</h4>
</el-card>
<Pod v-if="activeName==='second'" />
</el-tab-pane>
<el-tab-pane name="third">
<el-card slot="label" class="overviewTab" shadow="never">
<img v-if="activeName==='third'" src="@/assets/img/hanshu-.png">
<img v-else src="@/assets/img/hanshu.png">
<h4>函数概览</h4>
</el-card>
<Function v-if="activeName==='third'" />
</el-tab-pane>
</el-tabs>
<el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/rq.png">
<h4>容器概览</h4>
</el-card>
<Pod />
</div>
</template>
<script>
import Pod from './components/pod'
import VirtualMachine from './components/virtualMachine'
import Function from './components/function'
import Pod from './pod'
// import VirtualMachine from './virtualMachine'
// import Function from './function'
export default {
components: { Pod, VirtualMachine, Function },
components: { Pod },
data() {
return {
activeName: 'first'
@ -51,31 +29,10 @@ export default {
</script>
<style lang="scss">
.overviewTabs{
.el-tabs__nav-wrap::after{
display: none;
}
.el-tabs__active-bar{
display: none;
}
.el-tabs__item.is-active .overviewTab{
background-color: #419ef4;
color:#fff;
}
.el-tabs__nav{
width: 100%;
}
.el-tabs__item{
width: 33.33%;
padding: 0;
}
.el-tabs__header{
margin:0;
}
}
.overviewTab{
width: 30%;
background-color: #419ef4;
color:#fff;
// cursor: pointer;
border-radius: 10px;
.el-card__body{

View File

@ -0,0 +1,53 @@
<template>
<el-row :gutter="5">
<el-col :span="12">
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>集群信息</span>
</div>
<ClusterMessage />
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>JCCE组件状态</span>
</div>
<ComponentStatus />
</el-card>
</el-col>
<el-col :span="16">
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>集群资源使用情况</span>
</div>
<ResourceUsage />
</el-card>
</el-col>
<el-col :span="8">
<el-card shadow="never">
<div slot="header" class="clearfix">
<span>节点用量 Top5</span>
</div>
<NodeMessage />
</el-card>
</el-col>
</el-row>
</template>
<script>
import ClusterMessage from '@/components/ClusterManagement/clusterMessage'
import ComponentStatus from '@/components/ClusterManagement/componentStatus'
import NodeMessage from '@/components/ClusterManagement/nodeMessage'
import ResourceUsage from '@/components/ClusterManagement/resourceUsage'
export default {
components: {
ClusterMessage, ComponentStatus, ResourceUsage, NodeMessage
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,174 @@
<template>
<div>
<el-card slot="label" class="overviewTab" shadow="never">
<img src="@/assets/img/xnj-.png">
<h4>虚拟机概览</h4>
</el-card>
<el-card shadow="never" class="virtualMachineChart">
<el-row :gutter="5">
<el-col :span="8">
<h4>cpu</h4>
<div id="cpuGauge" ref="cpuGauge" />
<p>cpu4中的0.39</p>
</el-col>
<el-col :span="8">
<h4>内存</h4>
<div id="memoryGauge" ref="memoryGauge" />
<p>内存7.75GiB中的4.27</p>
</el-col>
<el-col :span="8">
<h4>存储</h4>
<div id="storageGauge" ref="storageGauge" />
<p>存储197GiB中的9.84</p>
</el-col>
</el-row>
<table class="table" border="0">
<tr>
<th>主机</th>
<th>虚拟机</th>
<th>网络</th>
<th>镜像</th>
<th>存储卷</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
<td>2</td>
</tr>
</table>
<h4>事件</h4>
<List
ref="multipleTable"
:table-list-data="listData"
:columns="columns"
/>
</el-card>
</div>
</template>
<script>
import List from '@/components/list'
import * as echarts from 'echarts'
export default {
components: { List },
data() {
return {
columns: [
{ prop: 'reason', label: '原因', width: '150' },
{ prop: 'info', label: '资源信息' },
{ prop: 'time', label: '发生时间', width: '150' }
],
listData: [
{
reason: 'Created',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
},
{
reason: 'Started',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
},
{
reason: 'Stopped',
info: 'VirtualMachineInstance educoder-main VirtualMachineInstance defined. ',
time: '2021/4/23 9:40'
}
]
}
},
created() {
this.$nextTick(() => {
this.drawChart()
})
},
methods: {
drawChart() {
const cpuGauge = echarts.init(this.$refs.cpuGauge)
cpuGauge.setOption(this.returnGaugeOption(5))
const memoryGauge = echarts.init(this.$refs.memoryGauge)
memoryGauge.setOption(this.returnGaugeOption(16))
const storageGauge = echarts.init(this.$refs.storageGauge)
storageGauge.setOption(this.returnGaugeOption(3))
},
returnGaugeOption(data) {
return {
series: [
{
type: 'gauge',
detail: {
formatter: '{value}%',
color: '#000000',
fontSize: 20,
offsetCenter: [0, '0']
},
center: ['50%', '78%'],
radius: '100%',
data: [{ value: data }],
itemStyle: {
color: 'transparent'
// show: false,
},
// splitLine: { show: false },
// axisTick: { show: false },
axisLabel: { show: false },
startAngle: 200,
endAngle: -20,
// progress: {
// show: false,
// // width: 1,
// // itemStyle: { color: '#419ef4' }
// },
axisTick: {
length: 16,
lineStyle: {
color: 'auto',
width: 1
}
},
splitLine: {
length: 20,
lineStyle: {
color: 'auto',
width: 2
}
},
axisLine: {
lineStyle: {
width: 6,
color: [
[data / 100, '#419ef4'],
[1, '#dddddd']
]
}
}
// axisLine: { lineStyle: { color: [[1, '#409eff']], width: 10 }}
}
]
}
}
}
}
</script>
<style lang="scss">
#cpuGauge,#memoryGauge,#storageGauge{
width: 100%;
height: 210px;
}
.virtualMachineChart{
p{
text-align: center;
}
}
</style>

View File

@ -4,33 +4,23 @@
<script>
import * as Three from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { getEarthRegion } from '@/api/screen -one-class-page/TotalNum'
import { getEarthDetails } from '@/api/screen -one-class-page/TotalNum'
export default {
data() {
return {
mshs: 1.0,
satellitesArr: [],
mapMarks: [
{
value: [116.423784, 39.876303],
name: '北京',
count: 1637
},
{
value: [120.161360422694918, 30.25886728953814],
name: '杭州',
count: 1328
},
{ name: '东京', value: [139.766037, 35.724993], count: 615 },
{ name: '新加坡', value: [103.865254, 1.35353], count: 5 },
{ name: '孟买', value: [72.841576, 19.017378], count: 5 },
{ name: '伦敦', value: [-0.138681, 51.529409], count: 11 },
{ name: '迪拜', value: [55.331252, 25.290169], count: 2 }
]
mapMarks: [],
area: []
}
},
mounted() {
this.getEarth()
// this.date_trans()
this.$nextTick(() => {
setTimeout(() => {
this.$nextTick(() => {
// this.drawBarchart()
// this.chinaConfigure()
// this.load_average()
@ -38,11 +28,40 @@ export default {
// this.memory_total()
// this.memory_average()
// this.resource_used()
this.init()
this.init()
// this.animate()
})
})
}, 1000)
},
methods: {
getEarth() {
getEarthRegion().then(res => {
const demo = res.data
const that = this
// console.log(demo)
for (let i = 0; i < demo.length; i++) {
const modelItem = []
const value = []
modelItem['name'] = demo[i].area
modelItem['count'] = demo[i].areaCount
value[0] = demo[i].value[0]
value[1] = demo[i].value[1]
modelItem['value'] = value
that.mapMarks[i] = modelItem
}
// console.log(that.mapMarks)
})
getEarthDetails('杭州').then(res => {
const demo = res.data
const that = this
that.area['resourceArea'] = demo.resourceArea
that.area['userNum'] = demo.userNum
that.area['areaCount'] = demo.areaCount
that.area['clusterNum'] = demo.clusterNum
that.area['usagedRate'] = demo.usagedRate
// console.log(that.area)
})
},
init() {
const earth = document.getElementById('earth')
@ -134,7 +153,7 @@ export default {
// this.scene.add(this.mesh4)
// this.scene.add(this.mesh5)
this.setMark(this.mapMarks)
this.setAreaMark()
this.setAreaMark(this.area)
this.renderer.setSize(width, height)//
// this.renderer.setClearColor(0x03060f, 1) //
earth.appendChild(this.renderer.domElement)
@ -213,7 +232,7 @@ export default {
context.stroke()
return canvas
},
setAreaMark() {
setAreaMark(_area) {
const borderSize = 2
const ctx = document.createElement('canvas').getContext('2d')
// measure how long the name will be
@ -230,11 +249,11 @@ export default {
ctx.strokeStyle = '#008aff'
ctx.strokeRect(0, 0, width, 580)
ctx.fillStyle = 'white'
ctx.fillText('资源区域亚太1区', borderSize * 30, borderSize * 20)
ctx.fillText('活跃用户1574', borderSize * 30, borderSize * 20 + 100)
ctx.fillText('服务器数量3580', borderSize * 30, borderSize * 20 + 200)
ctx.fillText('集群数量284', borderSize * 30, borderSize * 20 + 300)
ctx.fillText('资源使用率50%', borderSize * 30, borderSize * 20 + 400)
ctx.fillText('资源区域: ' + _area.resourceArea, borderSize * 30, borderSize * 20)
ctx.fillText('活跃用户: ' + _area.userNum, borderSize * 30, borderSize * 20 + 100)
ctx.fillText('服务器数量: ' + _area.areaCount, borderSize * 30, borderSize * 20 + 200)
ctx.fillText('集群数量: ' + _area.clusterNum, borderSize * 30, borderSize * 20 + 300)
ctx.fillText('资源使用率: ' + _area.usagedRate, borderSize * 30, borderSize * 20 + 400)
const markPos = this.getPosition(130.21029 + 90, 23.527138, 100)
var texture = new Three.CanvasTexture(ctx.canvas)
@ -284,14 +303,17 @@ export default {
this.marking.add(mesh)
// text
// console.log(typeof (_markData[i].name + '' + _markData[i].count + ''))
var texture = new Three.CanvasTexture(this.getCanvasFont(_markData[i].name + '' + _markData[i].count + '个'))
// console.log(_markData[i].count.toString().length)
const fontNumber = _markData[i].count.toString().length * 5.8642578125 + _markData[i].name.length * 10 + 10 + 2.4072265625 + 5
texture.needsUpdate = true
var fontMesh = new Three.Sprite(
new Three.SpriteMaterial({
map: texture
})
)
fontMesh.scale.x = 40
fontMesh.scale.x = fontNumber
fontMesh.scale.y = 10
fontMesh.position.set(markPos.x + 10, markPos.y + 10, markPos.z - 20)
this.textMarking.add(fontMesh)
@ -304,19 +326,25 @@ export default {
const ctx = document.createElement('canvas').getContext('2d')
// measure how long the name will be
const doubleBorderSize = borderSize * 2
const width = (ctx.measureText(name).width + doubleBorderSize) * 10
const width = (ctx.measureText(name).width + doubleBorderSize * 2) * 11
ctx.canvas.width = width
// ctx.canvas.height = height
// ctx.canvas.height = hei ght
// need to set font again after resizing canvas
ctx.textBaseline = 'top'
ctx.font = '80px Arial'
ctx.font = '85px Arial'
ctx.lineWidth = 15
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'
ctx.fillRect(0, 0, width, 150)
ctx.strokeStyle = '#00ffd2'
ctx.strokeRect(0, 0, width, 150)
ctx.fillStyle = 'white'
ctx.fillText(name, borderSize * 30, borderSize * 20)
// console.log(ctx.measureText(name).width)
if (ctx.measureText(name).width > 540) {
ctx.fillText(name, borderSize * 80, borderSize * 20)
} else {
ctx.fillText(name, borderSize * 60, borderSize * 20)
}
return ctx.canvas
},
getPosition(_longitude, _latitude, _radius) {

208
yarn.lock
View File

@ -14,7 +14,7 @@
"resolved" "https://registry.nlark.com/@babel/compat-data/download/@babel/compat-data-7.14.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.14.0.tgz"
"version" "7.14.0"
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.1.0", "@babel/core@^7.11.0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.4.0-0", "@babel/core@^7.9.6":
"@babel/core@^7.1.0", "@babel/core@^7.11.0", "@babel/core@^7.9.6":
"integrity" "sha1-U5XjBAXwd2Bn+9nPCITxW/t3Cjg="
"resolved" "https://registry.nlark.com/@babel/core/download/@babel/core-7.14.3.tgz"
"version" "7.14.3"
@ -1505,7 +1505,7 @@
"resolved" "https://registry.nlark.com/@vue/cli-plugin-vuex/download/@vue/cli-plugin-vuex-4.5.13.tgz"
"version" "4.5.13"
"@vue/cli-service@^3.0.0 || ^4.0.0-0", "@vue/cli-service@4.4.4":
"@vue/cli-service@4.4.4":
"integrity" "sha1-JWyZDkmi/43FM7dzxQSmVDXHXEw="
"resolved" "https://registry.nlark.com/@vue/cli-service/download/@vue/cli-service-4.4.4.tgz?cache=0&sync_timestamp=1620981774837&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40vue%2Fcli-service%2Fdownload%2F%40vue%2Fcli-service-4.4.4.tgz"
"version" "4.4.4"
@ -1816,7 +1816,7 @@
"resolved" "https://registry.nlark.com/acorn/download/acorn-5.7.4.tgz?cache=0&sync_timestamp=1620134123724&other_urls=https%3A%2F%2Fregistry.nlark.com%2Facorn%2Fdownload%2Facorn-5.7.4.tgz"
"version" "5.7.4"
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.0.1", "acorn@^6.4.1":
"acorn@^6.0.1", "acorn@^6.4.1":
"integrity" "sha1-NYZv1xBSjpLeEM8GAWSY5H454eY="
"resolved" "https://registry.nlark.com/acorn/download/acorn-6.4.2.tgz?cache=0&sync_timestamp=1620134123724&other_urls=https%3A%2F%2Fregistry.nlark.com%2Facorn%2Fdownload%2Facorn-6.4.2.tgz"
"version" "6.4.2"
@ -1867,7 +1867,7 @@
"resolved" "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1616882441894&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz"
"version" "3.5.2"
"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.12.4", "ajv@^6.9.1", "ajv@>=5.0.0":
"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.12.4":
"integrity" "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ="
"resolved" "https://registry.nlark.com/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1621517743418&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fajv%2Fdownload%2Fajv-6.12.6.tgz"
"version" "6.12.6"
@ -2076,11 +2076,6 @@
"resolved" "https://registry.nlark.com/array-uniq/download/array-uniq-1.0.3.tgz?cache=0&sync_timestamp=1620042045402&other_urls=https%3A%2F%2Fregistry.nlark.com%2Farray-uniq%2Fdownload%2Farray-uniq-1.0.3.tgz"
"version" "1.0.3"
"array-uniq@1.0.2":
"integrity" "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0="
"resolved" "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz"
"version" "1.0.2"
"array-unique@^0.2.1":
"integrity" "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
"resolved" "https://registry.npm.taobao.org/array-unique/download/array-unique-0.2.1.tgz"
@ -2222,7 +2217,7 @@
"esutils" "^2.0.2"
"js-tokens" "^3.0.2"
"babel-core@^6.0.0 || ^7.0.0-0", "babel-core@^6.25.0 || ^7.0.0-0", "babel-core@^7.0.0-bridge.0":
"babel-core@^7.0.0-bridge.0":
"integrity" "sha1-laSS3dkPm06aSh2hTrM1uHtjTs4="
"resolved" "https://registry.npm.taobao.org/babel-core/download/babel-core-7.0.0-bridge.0.tgz"
"version" "7.0.0-bridge.0"
@ -3074,13 +3069,12 @@
dependencies:
"anymatch" "~3.1.1"
"braces" "~3.0.2"
"fsevents" "~2.3.1"
"glob-parent" "~5.1.0"
"is-binary-path" "~2.1.0"
"is-glob" "~4.0.1"
"normalize-path" "~3.0.0"
"readdirp" "~3.5.0"
optionalDependencies:
"fsevents" "~2.3.1"
"chokidar@>=2.0.0 <4.0.0", "chokidar@2.1.5":
"integrity" "sha1-CuhDTZYigaX1bHKGnnnLbZ2GrU0="
@ -3264,11 +3258,6 @@
"resolved" "https://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz"
"version" "2.1.2"
"clone@^2.1.2":
"integrity" "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
"resolved" "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz"
"version" "2.1.2"
"clone@2.x":
"integrity" "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
"resolved" "https://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz"
@ -3527,13 +3516,6 @@
"resolved" "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz"
"version" "0.4.0"
"copy-anything@^2.0.1":
"integrity" "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ=="
"resolved" "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz"
"version" "2.0.3"
dependencies:
"is-what" "^3.12.0"
"copy-concurrently@^1.0.0":
"integrity" "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA="
"resolved" "https://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz"
@ -3705,7 +3687,7 @@
"postcss" "^7.0.1"
"timsort" "^0.3.0"
"css-loader@*", "css-loader@^3.5.3":
"css-loader@^3.5.3":
"integrity" "sha1-Lkssfm4tJ/jI8o9hv/zS5ske9kU="
"resolved" "https://registry.nlark.com/css-loader/download/css-loader-3.6.0.tgz"
"version" "3.6.0"
@ -3959,8 +3941,8 @@
"ms" "^2.1.1"
"debug@^3.2.6":
"integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="
"resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
"integrity" "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o="
"resolved" "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566571506&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz"
"version" "3.2.7"
dependencies:
"ms" "^2.1.1"
@ -4465,7 +4447,7 @@
"resolved" "https://registry.nlark.com/entities/download/entities-2.2.0.tgz"
"version" "2.2.0"
"errno@^0.1.1", "errno@^0.1.3", "errno@~0.1.7":
"errno@^0.1.3", "errno@~0.1.7":
"integrity" "sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8="
"resolved" "https://registry.nlark.com/errno/download/errno-0.1.8.tgz"
"version" "0.1.8"
@ -4597,7 +4579,7 @@
"resolved" "https://registry.nlark.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz?cache=0&sync_timestamp=1620088667316&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint-visitor-keys%2Fdownload%2Feslint-visitor-keys-1.3.0.tgz"
"version" "1.3.0"
"eslint@^5.0.0 || ^6.0.0", "eslint@>= 1.6.0", "eslint@>= 4.12.1", "eslint@>=1.6.0 <7.0.0", "eslint@>=5.0.0", "eslint@6.7.2":
"eslint@6.7.2":
"integrity" "sha1-wXcHykrXstivmGoz/rpx4Yqf7NE="
"resolved" "https://registry.nlark.com/eslint/download/eslint-6.7.2.tgz?cache=0&sync_timestamp=1621646990959&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint%2Fdownload%2Feslint-6.7.2.tgz"
"version" "6.7.2"
@ -4694,9 +4676,7 @@
"version" "1.8.1"
"eve@git://github.com/adobe-webplatform/eve.git#eef80ed":
"integrity" "sha512-VrMCMjRWGSuyiV/1SP58K4lIui3jlfD3uBapV8jahx9/RsqZad/FL7Tq5NRTHWFI8yd1dVLgUrEDPrA70gnOTw=="
"resolved" "git+ssh://git@github.com/adobe-webplatform/eve.git#eef80ed8d188423c2272746fb8ae5cc8dad84cb1"
"version" "0.4.1"
"event-pubsub@4.3.0":
"integrity" "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24="
@ -5009,7 +4989,7 @@
dependencies:
"flat-cache" "^2.0.1"
"file-loader@*", "file-loader@^4.2.0":
"file-loader@^4.2.0":
"integrity" "sha1-eA8ED3KbPRgBnyBgX3I+hEuKWK8="
"resolved" "https://registry.nlark.com/file-loader/download/file-loader-4.3.0.tgz"
"version" "4.3.0"
@ -5322,6 +5302,19 @@
"resolved" "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz"
"version" "1.0.0"
"fsevents@^1.2.7":
"integrity" "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg="
"resolved" "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz"
"version" "1.2.13"
dependencies:
"bindings" "^1.5.0"
"nan" "^2.12.1"
"fsevents@~2.3.1":
"integrity" "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro="
"resolved" "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz"
"version" "2.3.2"
"function-bind@^1.1.1":
"integrity" "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
"resolved" "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz"
@ -5578,9 +5571,8 @@
"minimist" "^1.2.5"
"neo-async" "^2.6.0"
"source-map" "^0.6.1"
"wordwrap" "^1.0.0"
optionalDependencies:
"uglify-js" "^3.1.4"
"wordwrap" "^1.0.0"
"har-schema@^2.0.0":
"integrity" "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
@ -5816,7 +5808,7 @@
"resolved" "https://registry.npm.taobao.org/html-tags/download/html-tags-3.1.0.tgz"
"version" "3.1.0"
"html-webpack-plugin@^3.0.0 || ^4.0.0", "html-webpack-plugin@^3.2.0", "html-webpack-plugin@>=2.26.0", "html-webpack-plugin@3.2.0":
"html-webpack-plugin@^3.2.0", "html-webpack-plugin@3.2.0":
"integrity" "sha1-sBq71yOsqqeze2r0SS69oD2d03s="
"resolved" "https://registry.nlark.com/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz"
"version" "3.2.0"
@ -5910,7 +5902,7 @@
"resolved" "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz?cache=0&sync_timestamp=1584198662293&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhuman-signals%2Fdownload%2Fhuman-signals-1.1.1.tgz"
"version" "1.1.1"
"husky@^1.3.1":
"husky@1.3.1":
"integrity" "sha1-JoI+OZMAOIyir/8Rz6ioawAz+uA="
"resolved" "https://registry.npm.taobao.org/husky/download/husky-1.3.1.tgz?cache=0&sync_timestamp=1617004245593&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhusky%2Fdownload%2Fhusky-1.3.1.tgz"
"version" "1.3.1"
@ -5926,7 +5918,7 @@
"run-node" "^1.0.0"
"slash" "^2.0.0"
"iconv-lite@^0.4.24", "iconv-lite@^0.4.4", "iconv-lite@0.4.24":
"iconv-lite@^0.4.24", "iconv-lite@0.4.24":
"integrity" "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs="
"resolved" "https://registry.nlark.com/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1621826342262&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz"
"version" "0.4.24"
@ -5960,7 +5952,7 @@
"resolved" "https://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fignore%2Fdownload%2Fignore-4.0.6.tgz"
"version" "4.0.6"
"image-size@^0.5.1", "image-size@~0.5.0":
"image-size@^0.5.1":
"integrity" "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w="
"resolved" "https://registry.npm.taobao.org/image-size/download/image-size-0.5.5.tgz?cache=0&sync_timestamp=1618424661730&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimage-size%2Fdownload%2Fimage-size-0.5.5.tgz"
"version" "0.5.5"
@ -6603,11 +6595,6 @@
"resolved" "https://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz"
"version" "0.2.1"
"is-what@^3.12.0":
"integrity" "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
"resolved" "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz"
"version" "3.14.1"
"is-whitespace@^0.3.0":
"integrity" "sha1-Fjnssb4DauxppUy7QBz77XEUq38="
"resolved" "https://registry.npm.taobao.org/is-whitespace/download/is-whitespace-0.3.0.tgz"
@ -6957,7 +6944,7 @@
"jest-regex-util" "^24.3.0"
"jest-snapshot" "^24.9.0"
"jest-resolve@*", "jest-resolve@^24.9.0":
"jest-resolve@^24.9.0":
"integrity" "sha1-3/BMdoevNMTdflJIktnPd+XRcyE="
"resolved" "https://registry.nlark.com/jest-resolve/download/jest-resolve-24.9.0.tgz"
"version" "24.9.0"
@ -7130,7 +7117,7 @@
"merge-stream" "^2.0.0"
"supports-color" "^7.0.0"
"jest@^24.9.0", "jest@>=24 <25":
"jest@^24.9.0":
"integrity" "sha1-mH0pDAWgi1LFYYjBAC42jtsAcXE="
"resolved" "https://registry.nlark.com/jest/download/jest-24.9.0.tgz?cache=0&sync_timestamp=1621937261609&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjest%2Fdownload%2Fjest-24.9.0.tgz"
"version" "24.9.0"
@ -7341,7 +7328,7 @@
"integrity" "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss="
"resolved" "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161876665&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz"
"version" "4.0.0"
optionalDependencies:
dependencies:
"graceful-fs" "^4.1.6"
"jsonlint@1.6.3":
@ -7450,49 +7437,6 @@
"resolved" "https://registry.npm.taobao.org/left-pad/download/left-pad-1.3.0.tgz"
"version" "1.3.0"
"less-loader@^6.0.0":
"integrity" "sha512-k9KrSkjkdGCQwbKPHfbJT9AfRCmOCHCCjiQCc0v2fdVCRTlJvr1Si68Zk6Z4d4UyVkp0U/nEEdQeH4wV/jW8/g=="
"resolved" "https://registry.npmjs.org/less-loader/-/less-loader-6.0.0.tgz"
"version" "6.0.0"
dependencies:
"clone" "^2.1.2"
"less" "^3.11.1"
"loader-utils" "^2.0.0"
"schema-utils" "^2.6.6"
"less@^3.11.1":
"integrity" "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw=="
"resolved" "https://registry.npmjs.org/less/-/less-3.13.1.tgz"
"version" "3.13.1"
dependencies:
"copy-anything" "^2.0.1"
"tslib" "^1.10.0"
optionalDependencies:
"errno" "^0.1.1"
"graceful-fs" "^4.1.2"
"image-size" "~0.5.0"
"make-dir" "^2.1.0"
"mime" "^1.4.1"
"native-request" "^1.0.5"
"source-map" "~0.6.0"
"less@^4.1.1":
"integrity" "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw=="
"resolved" "https://registry.npmjs.org/less/-/less-4.1.1.tgz"
"version" "4.1.1"
dependencies:
"copy-anything" "^2.0.1"
"parse-node-version" "^1.0.1"
"tslib" "^1.10.0"
optionalDependencies:
"errno" "^0.1.1"
"graceful-fs" "^4.1.2"
"image-size" "~0.5.0"
"make-dir" "^2.1.0"
"mime" "^1.4.1"
"needle" "^2.5.2"
"source-map" "~0.6.0"
"leven@^3.1.0":
"integrity" "sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I="
"resolved" "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz"
@ -7674,15 +7618,6 @@
"emojis-list" "^3.0.0"
"json5" "^1.0.1"
"loader-utils@^2.0.0":
"integrity" "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ=="
"resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz"
"version" "2.0.0"
dependencies:
"big.js" "^5.2.2"
"emojis-list" "^3.0.0"
"json5" "^2.1.2"
"locate-path@^2.0.0":
"integrity" "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4="
"resolved" "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz?cache=0&sync_timestamp=1597081764621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flocate-path%2Fdownload%2Flocate-path-2.0.0.tgz"
@ -8085,11 +8020,6 @@
dependencies:
"mime-db" "1.47.0"
"mime@^1.4.1":
"integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
"resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz"
"version" "1.6.0"
"mime@^2.4.4":
"integrity" "sha1-bj3GzCuVEGQ4MOXxnVy3U9pe6r4="
"resolved" "https://registry.npm.taobao.org/mime/download/mime-2.5.2.tgz"
@ -8223,11 +8153,6 @@
dependencies:
"commander" "*"
"moment@^2.29.1":
"integrity" "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
"resolved" "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz"
"version" "2.29.1"
"move-concurrently@^1.0.1":
"integrity" "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I="
"resolved" "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz"
@ -8241,8 +8166,8 @@
"run-queue" "^1.0.3"
"ms@^2.1.1":
"integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
"resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
"integrity" "sha1-V0yBOM4dK1hh8LRFedut1gxmFbI="
"resolved" "https://registry.npm.taobao.org/ms/download/ms-2.1.3.tgz?cache=0&sync_timestamp=1607433926553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.3.tgz"
"version" "2.1.3"
"ms@2.0.0":
@ -8292,6 +8217,11 @@
"object-assign" "^4.0.1"
"thenify-all" "^1.0.0"
"nan@^2.12.1":
"integrity" "sha1-9TdkAGlRaPTMaUrJOT0MlYXu6hk="
"resolved" "https://registry.npm.taobao.org/nan/download/nan-2.14.2.tgz?cache=0&sync_timestamp=1602591709094&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnan%2Fdownload%2Fnan-2.14.2.tgz"
"version" "2.14.2"
"nanomatch@^1.2.1", "nanomatch@^1.2.9":
"integrity" "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk="
"resolved" "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz"
@ -8309,25 +8239,11 @@
"snapdragon" "^0.8.1"
"to-regex" "^3.0.1"
"native-request@^1.0.5":
"integrity" "sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw=="
"resolved" "https://registry.npmjs.org/native-request/-/native-request-1.1.0.tgz"
"version" "1.1.0"
"natural-compare@^1.4.0":
"integrity" "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
"resolved" "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz"
"version" "1.4.0"
"needle@^2.5.2":
"integrity" "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ=="
"resolved" "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz"
"version" "2.9.1"
dependencies:
"debug" "^3.2.6"
"iconv-lite" "^0.4.4"
"sax" "^1.2.4"
"negotiator@0.6.2":
"integrity" "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs="
"resolved" "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz"
@ -8973,11 +8889,6 @@
"json-parse-even-better-errors" "^2.3.0"
"lines-and-columns" "^1.1.6"
"parse-node-version@^1.0.1":
"integrity" "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA=="
"resolved" "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz"
"version" "1.0.1"
"parse-passwd@^1.0.0":
"integrity" "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="
"resolved" "https://registry.npm.taobao.org/parse-passwd/download/parse-passwd-1.0.0.tgz"
@ -9864,11 +9775,6 @@
dependencies:
"safe-buffer" "^5.1.0"
"randombytes@2.0.3":
"integrity" "sha1-Z0yZdgkBw8QRJ3GjHlIdw0nMCew="
"resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.0.3.tgz"
"version" "2.0.3"
"randomfill@^1.0.3":
"integrity" "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg="
"resolved" "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz"
@ -9877,23 +9783,13 @@
"randombytes" "^2.0.5"
"safe-buffer" "^5.1.0"
"randomstring@^1.2.1":
"integrity" "sha512-eMnfell9XuU3jfCx3f4xCaFAt0YMFPZhx9R3PSStmLarDKg5j5vivqKhf/8pvG+VX/YkxsckHK/VPUrKa5V07A=="
"resolved" "https://registry.npmjs.org/randomstring/-/randomstring-1.2.1.tgz"
"version" "1.2.1"
dependencies:
"array-uniq" "1.0.2"
"randombytes" "2.0.3"
"range-parser@^1.2.1", "range-parser@~1.2.0", "range-parser@~1.2.1":
"integrity" "sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE="
"resolved" "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz"
"version" "1.2.1"
"raphael@git+https://github.com/nhn/raphael.git#2.2.0-c":
"integrity" "sha512-glTY/CkZjpevnNwgI0d8I+y6nqezB8INg3YHzQZdqWyTKJc+rIvr0qSkI8m+4XXLXmR2AfHu2wPOB9/AAG1agA=="
"resolved" "git+ssh://git@github.com/nhn/raphael.git#78a6ed3ec269f33b6457b0ec66f8c3d1f2ed70e0"
"version" "2.2.0-c"
dependencies:
"eve" "git://github.com/adobe-webplatform/eve.git#eef80ed"
@ -10180,7 +10076,7 @@
"stealthy-require" "^1.1.1"
"tough-cookie" "^2.3.3"
"request@^2.34", "request@^2.87.0", "request@^2.88.0", "request@^2.88.2":
"request@^2.87.0", "request@^2.88.0", "request@^2.88.2":
"integrity" "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM="
"resolved" "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz"
"version" "2.88.2"
@ -10419,7 +10315,7 @@
"schema-utils" "^2.6.1"
"semver" "^6.3.0"
"sass@^1.3.0", "sass@1.26.2":
"sass@1.26.2":
"integrity" "sha1-ThfFwjlOLuf/1lOsHYYjFKaldns="
"resolved" "https://registry.nlark.com/sass/download/sass-1.26.2.tgz?cache=0&sync_timestamp=1621664429943&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsass%2Fdownload%2Fsass-1.26.2.tgz"
"version" "1.26.2"
@ -10946,9 +10842,7 @@
"version" "1.0.3"
"squire-rte@github:sohee-lee7/Squire#b1e0e1031fa18912d233c204cbe7c7fae4a42621":
"integrity" "sha512-/1Wi323QPO3AmcGOXjliEp2Kqzse6/BbCyCj/lw0R0M/zS+7IFm1LnBlgMlfa1yLXRjNcc5PcmE2vnwA4Zlhkg=="
"resolved" "git+ssh://git@github.com/sohee-lee7/Squire.git#b1e0e1031fa18912d233c204cbe7c7fae4a42621"
"version" "1.9.0"
"ssf@~0.10.2":
"integrity" "sha1-jq4fwpyQpVLnkhII+BiS1vd6yys="
@ -11728,11 +11622,6 @@
"strip-bom" "^3.0.0"
"strip-json-comments" "^2.0.0"
"tslib@^1.10.0":
"integrity" "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
"resolved" "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
"version" "1.14.1"
"tslib@^1.9.0":
"integrity" "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA="
"resolved" "https://registry.npm.taobao.org/tslib/download/tslib-1.14.1.tgz?cache=0&sync_timestamp=1617647074515&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.14.1.tgz"
@ -12189,13 +12078,6 @@
"tsconfig" "^7.0.0"
"vue-template-es2015-compiler" "^1.6.0"
"vue-json-editor@^1.4.3":
"integrity" "sha512-st9HdXBgCnyEmmfWrZQiKzp4KuYXzmYVUNDn5h6Fa18MrrGS1amnyUFyv7hQFsNBDW27B7BKkdGOqszYT1srAg=="
"resolved" "https://registry.npmjs.org/vue-json-editor/-/vue-json-editor-1.4.3.tgz"
"version" "1.4.3"
dependencies:
"vue" "^2.2.6"
"vue-loader@^15.9.2":
"integrity" "sha1-FbBXdcPgw4QHZ5OTws5t9nOwEEQ="
"resolved" "https://registry.nlark.com/vue-loader/download/vue-loader-15.9.7.tgz"
@ -12225,7 +12107,7 @@
"hash-sum" "^1.0.2"
"loader-utils" "^1.0.2"
"vue-template-compiler@^2.0.0", "vue-template-compiler@^2.x", "vue-template-compiler@2.6.10":
"vue-template-compiler@2.6.10":
"integrity" "sha1-MjtPNJXwT6o1AzN6gvXWUHeZycw="
"resolved" "https://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.10.tgz?cache=0&sync_timestamp=1597927391993&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-template-compiler%2Fdownload%2Fvue-template-compiler-2.6.10.tgz"
"version" "2.6.10"
@ -12238,7 +12120,7 @@
"resolved" "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz"
"version" "1.9.1"
"vue@^2 || ^3.0.0-0", "vue@^2.2.6", "vue@^2.5.17", "vue@^2.x", "vue@2.6.10", "vue@2.x":
"vue@2.6.10":
"integrity" "sha1-pysaQqTYKnIepDjRtr9V5mGVxjc="
"resolved" "https://registry.nlark.com/vue/download/vue-2.6.10.tgz"
"version" "2.6.10"
@ -12415,7 +12297,7 @@
"source-list-map" "^2.0.0"
"source-map" "~0.6.1"
"webpack@^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0", "webpack@^2.0.0 || ^3.0.0 || ^4.0.0", "webpack@^3.0.0 || ^4.1.0 || ^5.0.0-0", "webpack@^4.0.0", "webpack@^4.0.0 || ^5.0.0", "webpack@^4.36.0 || ^5.0.0", "webpack@^4.4.0", "webpack@>=2", "webpack@>=2.0.0 <5.0.0", "webpack@>=4.0.0":
"webpack@^4.0.0":
"integrity" "sha1-v5tEBOogoHNgXgoBHRiNd8tq1UI="
"resolved" "https://registry.nlark.com/webpack/download/webpack-4.46.0.tgz"
"version" "4.46.0"