Skip to content

Commit

Permalink
Merge pull request #172 from veops/dev_ui
Browse files Browse the repository at this point in the history
新建ci及批量导入时,新建关系
  • Loading branch information
pycook authored Sep 7, 2023
2 parents 8ba658e + be9b308 commit bed2323
Show file tree
Hide file tree
Showing 10 changed files with 292 additions and 58 deletions.
26 changes: 25 additions & 1 deletion cmdb-ui/src/modules/cmdb/utils/helper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable */
import _ from 'lodash'
import XLSX from 'xlsx'
import XLSXS from 'xlsx-js-style'
export function sum(arr) {
if (!arr.length) {
return 0
Expand Down Expand Up @@ -149,4 +151,26 @@ export const toThousands = (num = 0) => {
return num.toString().replace(/\d+/, function (n) {
return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
})
}
}

export const downloadExcel = (data, fileName = `${moment().format('YYYY-MM-DD HH:mm:ss')}.xls`) => {
// STEP 1: Create a new workbook
const wb = XLSXS.utils.book_new()
// STEP 2: Create data rows and styles
const rowArray = data
// STEP 3: Create worksheet with rows; Add worksheet to workbook
const ws = XLSXS.utils.aoa_to_sheet(rowArray)
XLSXS.utils.book_append_sheet(wb, ws, fileName)

let maxColumnNumber = 1 // 默认最大列数
rowArray.forEach(item => { if (item.length > maxColumnNumber) { maxColumnNumber = item.length } })

// 添加列宽
ws['!cols'] = (rowArray[0].map(item => {
return { width: 22 }
}))
// // 添加行高
// ws['!rows'] = [{ 'hpt': 80 }]
// STEP 4: Write Excel file to browser #导出
XLSXS.writeFile(wb, fileName + '.xlsx')
}
170 changes: 155 additions & 15 deletions cmdb-ui/src/modules/cmdb/views/batch/modules/CiTypeChoice.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,83 @@
}}</a-select-option>
</a-select>
<a-button
@click="downLoadExcel"
@click="openModal"
:disabled="!selectNum"
type="primary"
class="ops-button-primary"
icon="download"
>下载模板</a-button
>
<a-modal
:bodyStyle="{ paddingTop: 0 }"
width="800px"
:title="`${ciTypeName}`"
:visible="visible"
@cancel="handleCancel"
@ok="handleOk"
wrapClassName="ci-type-choice-modal"
>
<a-divider orientation="left">模型属性</a-divider>
<a-checkbox
@change="changeCheckAll"
:style="{ marginBottom: '20px' }"
:indeterminate="indeterminate"
:checked="checkAll"
>
全选
</a-checkbox>
<br />
<a-checkbox-group v-model="checkedAttrs">
<a-row>
<a-col :span="6" v-for="item in selectCiTypeAttrList.attributes" :key="item.alias || item.name">
<a-checkbox :disabled="item.name === selectCiTypeAttrList.unique" :value="item.alias || item.name">
{{ item.alias || item.name }}
<span style="color: red" v-if="item.name === selectCiTypeAttrList.unique">*</span>
</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
<template v-if="parentsType && parentsType.length">
<a-divider orientation="left">模型关联</a-divider>
<a-row :gutter="[24, 24]" align="top" type="flex">
<a-col :style="{ display: 'inline-flex' }" :span="12" v-for="item in parentsType" :key="item.id">
<a-checkbox @click="clickParent(item)" :checked="checkedParents.includes(item.alias || item.name)">
</a-checkbox>
<span
:style="{
display: 'inline-block',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
width: '80px',
margin: '0 5px',
textAlign: 'right',
}"
:title="item.alias || item.name"
>{{ item.alias || item.name }}</span
>
<a-select :style="{ flex: 1 }" size="small" v-model="parentsForm[item.alias || item.name].attr">
<a-select-option
:title="attr.alias || attr.name"
v-for="attr in item.attributes"
:key="attr.alias || attr.name"
:value="attr.alias || attr.name"
>
{{ attr.alias || attr.name }}
</a-select-option>
</a-select>
</a-col>
</a-row>
</template>
</a-modal>
</a-space>
</template>

<script>
import { downloadExcel } from '../../../utils/helper'
import { getCITypes } from '@/modules/cmdb/api/CIType'
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
import { writeExcel } from '@/modules/cmdb/api/batch'
import { getCITypeParent } from '@/modules/cmdb/api/CITypeRelation'

export default {
name: 'CiTypeChoice',
Expand All @@ -37,13 +100,32 @@ export default {
ciTypeName: '',
selectNum: 0,
selectCiTypeAttrList: [],
visible: false,
checkedAttrs: [],
indeterminate: false,
checkAll: true,
parentsType: [],
parentsForm: {},
checkedParents: [],
}
},
created: function() {
getCITypes().then((res) => {
this.ciTypeList = res.ci_types
})
},
watch: {
checkedAttrs() {
if (this.checkedAttrs.length < this.selectCiTypeAttrList.attributes.length) {
this.indeterminate = true
this.checkAll = false
}
if (this.checkedAttrs.length === this.selectCiTypeAttrList.attributes.length) {
this.indeterminate = false
this.checkAll = true
}
},
},
methods: {
selectCiType(el) {
// 当选择好模板类型时的回调函数
Expand All @@ -60,24 +142,70 @@ export default {
})
},

downLoadExcel() {
const columns = []
this.selectCiTypeAttrList.attributes.forEach((item) => {
columns.push(item.alias)
openModal() {
getCITypeParent(this.selectNum).then((res) => {
this.parentsType = res.parents
const _parentsForm = {}
res.parents.forEach((item) => {
const _find = item.attributes.find((attr) => attr.id === item.unique_id)
_parentsForm[item.alias || item.name] = { attr: _find?.alias || _find?.name, value: '' }
})
this.parentsForm = _parentsForm
this.checkedParents = []
this.visible = true
this.checkedAttrs = this.selectCiTypeAttrList.attributes.map((item) => item.alias || item.name)
})
const excel = writeExcel(columns, this.ciTypeName)
const tempLink = document.createElement('a')
tempLink.download = this.ciTypeName + '.xls'
tempLink.style.display = 'none'
const blob = new Blob([excel])
tempLink.href = URL.createObjectURL(blob)
document.body.appendChild(tempLink)
tempLink.click()
document.body.removeChild(tempLink)
},
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
handleCancel() {
this.visible = false
},
handleOk() {
const columns1 = this.checkedAttrs.map((item) => {
return {
v: item,
t: 's',
s: {
numFmt: 'string',
},
}
})
const columns2 = this.checkedParents.map((p) => {
return {
v: `$${p}.${this.parentsForm[p].attr}`,
t: 's',
s: {
font: {
color: {
rgb: 'FF0000',
},
},
},
}
})
downloadExcel([[...columns1, ...columns2]], this.ciTypeName)
this.handleCancel()
},
changeCheckAll(e) {
if (e.target.checked) {
this.checkedAttrs = this.selectCiTypeAttrList.attributes.map((item) => item.alias || item.name)
} else {
const _find = this.selectCiTypeAttrList.attributes.find(
(item) => item.name === this.selectCiTypeAttrList.unique
)
this.checkedAttrs = [_find?.alias || _find?.name]
}
},
clickParent(item) {
const _idx = this.checkedParents.findIndex((p) => p === (item.alias || item.name))
if (_idx > -1) {
this.checkedParents.splice(_idx, 1)
} else {
this.checkedParents.push(item.alias || item.name)
}
},
},
}
</script>
Expand Down Expand Up @@ -105,3 +233,15 @@ export default {
}
}
</style>

<style lang="less">
.ci-type-choice-modal {
.ant-checkbox-disabled .ant-checkbox-inner {
border-color: #2f54eb !important;
background-color: #2f54eb;
}
.ant-checkbox-disabled.ant-checkbox-checked .ant-checkbox-inner::after {
border-color: #fff;
}
}
</style>
20 changes: 15 additions & 5 deletions cmdb-ui/src/modules/cmdb/views/batch/modules/CiUploadTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,25 @@ export default {
},
computed: {
columns() {
const _columns = []
if (this.ciTypeAttrs.attributes) {
return this.ciTypeAttrs.attributes.map((item) => {
return {
title: item.alias || item.name,
field: item.alias || item.name,
_columns.push(
...this.ciTypeAttrs.attributes.map((item) => {
return {
title: item.alias || item.name,
field: item.alias || item.name,
}
})
)
}
if (this.uploadData && this.uploadData.length) {
Object.keys(this.uploadData[0]).forEach((key) => {
if (key.startsWith('$')) {
_columns.push({ title: key, field: key })
}
})
}
return []
return _columns
},
dataSource() {
return _.cloneDeep(this.uploadData)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
ref="upload"
:multiple="false"
:customRequest="customRequest"
accept=".xls"
accept=".xls,.xlsx"
:showUploadList="false"
:fileList="fileList"
>
<img :style="{ width: '80px', height: '80px' }" src="@/assets/file_upload.png" />
<p class="ant-upload-text">点击或拖拽文件至此上传</p>
<p class="ant-upload-hint">支持文件类型xls</p>
<p class="ant-upload-hint">支持文件类型xlsxlsx</p>
</a-upload-dragger>
<div v-for="item in fileList" :key="item.name" class="cmdb-batch-upload-dragger-file">
<span><a-icon type="file" :style="{ color: '#2F54EB', marginRight: '5px' }" />{{ item.name }}</span>
Expand Down
20 changes: 13 additions & 7 deletions cmdb-ui/src/modules/cmdb/views/ci/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,19 @@
<EditAttrsPopover :typeId="typeId" class="operation-icon" @refresh="refreshAfterEditAttrs" />
</template>
<template #default="{ row }">
<a @click="$refs.detail.create(row.ci_id || row._id)">
<a-icon type="unordered-list" />
</a>
<a-divider type="vertical" />
<a @click="deleteCI(row)" :style="{ color: 'red' }">
<a-icon type="delete" />
</a>
<a-space>
<a @click="$refs.detail.create(row.ci_id || row._id)">
<a-icon type="unordered-list" />
</a>
<a-tooltip title="添加关系">
<a @click="$refs.detail.create(row.ci_id || row._id, 'tab_2', '2')">
<a-icon type="retweet" />
</a>
</a-tooltip>
<a @click="deleteCI(row)" :style="{ color: 'red' }">
<a-icon type="delete" />
</a>
</a-space>
</template>
</vxe-column>
<template #empty>
Expand Down
10 changes: 8 additions & 2 deletions cmdb-ui/src/modules/cmdb/views/ci/modules/CiDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<a-tab-pane key="tab_2">
<span slot="tab"><a-icon type="branches" />关系</span>
<div :style="{ padding: '24px' }">
<CiDetailRelation :ciId="ciId" :typeId="typeId" :ci="ci" />
<CiDetailRelation ref="ciDetailRelation" :ciId="ciId" :typeId="typeId" :ci="ci" />
</div>
</a-tab-pane>
<a-tab-pane key="tab_3">
Expand Down Expand Up @@ -147,8 +147,14 @@ export default {
},
inject: ['reload', 'handleSearch', 'attrList'],
methods: {
create(ciId) {
create(ciId, activeTabKey = 'tab_1', ciDetailRelationKey = '1') {
this.visible = true
this.activeTabKey = activeTabKey
if (activeTabKey === 'tab_2') {
this.$nextTick(() => {
this.$refs.ciDetailRelation.activeKey = ciDetailRelationKey
})
}
this.ciId = ciId
this.getAttributes()
this.getCI()
Expand Down
Loading

0 comments on commit bed2323

Please sign in to comment.