mirror of
https://github.com/veops/cmdb.git
synced 2025-08-09 01:02:19 +08:00
前后端全面升级
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const VueAxios = {
|
||||
vm: {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
install (Vue, instance) {
|
||||
install(Vue, instance) {
|
||||
if (this.installed) {
|
||||
return
|
||||
}
|
||||
@@ -14,15 +14,14 @@ const VueAxios = {
|
||||
}
|
||||
|
||||
Vue.axios = instance
|
||||
|
||||
Object.defineProperties(Vue.prototype, {
|
||||
axios: {
|
||||
get: function get () {
|
||||
get: function get() {
|
||||
return instance
|
||||
}
|
||||
},
|
||||
$http: {
|
||||
get: function get () {
|
||||
get: function get() {
|
||||
return instance
|
||||
}
|
||||
}
|
||||
|
@@ -16,4 +16,4 @@ export const setDocumentTitle = function (title) {
|
||||
}
|
||||
}
|
||||
|
||||
export const domTitle = 'CMDB'
|
||||
export const domTitle = 'OneOps'
|
||||
|
75
cmdb-ui/src/utils/download.js
Normal file
75
cmdb-ui/src/utils/download.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import moment from 'moment'
|
||||
import XLSX from 'xlsx'
|
||||
import XLSXS from 'xlsx-js-style'
|
||||
|
||||
export const downloadTxt = ({ text, title }) => {
|
||||
const dom = document.createElement('a')
|
||||
dom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text))
|
||||
dom.setAttribute('download', `${title}.txt`)
|
||||
if (document.createEvent) {
|
||||
var event = document.createEvent('MouseEvents')
|
||||
event.initEvent('click', true, true)
|
||||
dom.dispatchEvent(event)
|
||||
} else {
|
||||
dom.click()
|
||||
}
|
||||
}
|
||||
|
||||
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 } })
|
||||
// 合并 #将第一行标题列合并
|
||||
// const merges = ['A1:' + String.fromCharCode(64 + parseInt(maxColumnNumber)) + '1']
|
||||
const merges = ['A1:' + createCellPos(maxColumnNumber - 1) + '1']
|
||||
const wsMerge = []
|
||||
merges.map((item) => {
|
||||
wsMerge.push(
|
||||
XLSXS.utils.decode_range(item)
|
||||
)
|
||||
})
|
||||
|
||||
ws['!merges'] = wsMerge
|
||||
|
||||
// 添加列宽
|
||||
ws['!cols'] = (rowArray[1].map(item => {
|
||||
return { width: 22 }
|
||||
}))
|
||||
// 添加行高
|
||||
ws['!rows'] = [{ 'hpt': 80 }]
|
||||
// STEP 4: Write Excel file to browser #导出
|
||||
XLSXS.writeFile(wb, fileName + '.xlsx')
|
||||
}
|
||||
|
||||
export const excel2Array = (fileObj) => {
|
||||
return new Promise(function (resolve) {
|
||||
const reader = new FileReader()
|
||||
reader.readAsBinaryString(fileObj)
|
||||
reader.onload = function (e) {
|
||||
const data = e.target.result
|
||||
const workbook = XLSX.read(data, { type: 'binary' })
|
||||
const sheet = workbook.Sheets[workbook.SheetNames[0]]
|
||||
const lt = XLSX.utils.sheet_to_json(sheet, { header: 1 })
|
||||
resolve(lt)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const createCellPos = (n) => {
|
||||
const ordA = 'A'.charCodeAt(0)
|
||||
const ordZ = 'Z'.charCodeAt(0)
|
||||
const len = ordZ - ordA + 1
|
||||
let s = ''
|
||||
while (n >= 0) {
|
||||
s = String.fromCharCode(n % len + ordA) + s
|
||||
n = Math.floor(n / len) - 1
|
||||
}
|
||||
return s
|
||||
}
|
@@ -4,11 +4,7 @@ import 'moment/locale/zh-cn'
|
||||
moment.locale('zh-cn')
|
||||
|
||||
Vue.filter('NumberFormat', function (value) {
|
||||
if (!value) {
|
||||
return '0'
|
||||
}
|
||||
const intPartFormat = value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断
|
||||
return intPartFormat
|
||||
return value.toLocaleString()
|
||||
})
|
||||
|
||||
Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
|
||||
|
41
cmdb-ui/src/utils/functions/set.js
Normal file
41
cmdb-ui/src/utils/functions/set.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/* eslint-disable */
|
||||
export function intersection(thisSet, otherSet) {
|
||||
//初始化一个新集合,用于表示交集。
|
||||
var interSectionSet = new Set()
|
||||
var values = Array.from(thisSet)
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
|
||||
if (otherSet.has(values[i])) {
|
||||
interSectionSet.add(values[i])
|
||||
}
|
||||
}
|
||||
|
||||
return interSectionSet
|
||||
}
|
||||
|
||||
export function union(thisSet, otherSet) {
|
||||
var unionSet = new Set()
|
||||
var values = Array.from(thisSet)
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
unionSet.add(values[i])
|
||||
}
|
||||
values = Array.from(otherSet)
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
unionSet.add(values[i])
|
||||
}
|
||||
|
||||
return unionSet
|
||||
}
|
||||
|
||||
export function difference(thisSet, otherSet) {
|
||||
var differenceSet = new Set()
|
||||
var values = Array.from(thisSet)
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
|
||||
if (!otherSet.has(values[i])) {
|
||||
differenceSet.add(values[i])
|
||||
}
|
||||
}
|
||||
|
||||
return differenceSet
|
||||
}
|
@@ -22,10 +22,10 @@ const mixin = {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isTopMenu () {
|
||||
isTopMenu() {
|
||||
return this.layoutMode === 'topmenu'
|
||||
},
|
||||
isSideMenu () {
|
||||
isSideMenu() {
|
||||
return !this.isTopMenu()
|
||||
}
|
||||
}
|
||||
@@ -38,20 +38,20 @@ const mixinDevice = {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
isMobile () {
|
||||
isMobile() {
|
||||
return this.device === DEVICE_TYPE.MOBILE
|
||||
},
|
||||
isDesktop () {
|
||||
isDesktop() {
|
||||
return this.device === DEVICE_TYPE.DESKTOP
|
||||
},
|
||||
isTablet () {
|
||||
isTablet() {
|
||||
return this.device === DEVICE_TYPE.TABLET
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AppDeviceEnquire = {
|
||||
mounted () {
|
||||
mounted() {
|
||||
const { $store } = this
|
||||
deviceEnquire(deviceType => {
|
||||
switch (deviceType) {
|
||||
@@ -73,4 +73,21 @@ const AppDeviceEnquire = {
|
||||
}
|
||||
}
|
||||
|
||||
export { mixin, AppDeviceEnquire, mixinDevice }
|
||||
const mixinPermissions = {
|
||||
computed: {
|
||||
...mapState({
|
||||
detailPermissions: state => state.user.detailPermissions
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 根据appName 资源名 perms名 返回true/false
|
||||
// 判断该登录用户是否有传入的perms权限
|
||||
hasDetailPermission(appName, resourceName, perms = []) {
|
||||
const appNamePer = this.detailPermissions[`${appName}`]
|
||||
const _findResourcePermissions = appNamePer.find(item => item.name === resourceName)
|
||||
return _findResourcePermissions.permissions.some(item => perms.includes(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { mixin, AppDeviceEnquire, mixinDevice, mixinPermissions }
|
||||
|
@@ -1,8 +0,0 @@
|
||||
export function actionToObject (json) {
|
||||
try {
|
||||
return JSON.parse(json)
|
||||
} catch (e) {
|
||||
console.log('err', e.message)
|
||||
}
|
||||
return []
|
||||
}
|
@@ -1,8 +1,12 @@
|
||||
/* eslint-dsiable */
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import store from '@/store'
|
||||
import { VueAxios } from './axios'
|
||||
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||
import config from '@/config/setting'
|
||||
import message from 'ant-design-vue/es/message'
|
||||
import notification from 'ant-design-vue/es/notification'
|
||||
import { ACCESS_TOKEN } from '@/store/global/mutation-types'
|
||||
|
||||
// 创建 axios 实例
|
||||
const service = axios.create({
|
||||
@@ -13,9 +17,43 @@ const service = axios.create({
|
||||
})
|
||||
|
||||
const err = (error) => {
|
||||
console.log(error)
|
||||
const reg = /5\d{2}/g
|
||||
if (error.response && reg.test(error.response.status)) {
|
||||
message.error('服务端未知错误, 请联系管理员!')
|
||||
} else if (error.response.status === 412) {
|
||||
let seconds = 5
|
||||
notification.warning({
|
||||
key: 'notification',
|
||||
message: 'WARNING',
|
||||
description:
|
||||
'修改已提交,请等待审核(5s)',
|
||||
duration: 5,
|
||||
})
|
||||
let interval = setInterval(() => {
|
||||
seconds -= 1
|
||||
if (seconds === 0) {
|
||||
clearInterval(interval)
|
||||
interval = null
|
||||
return
|
||||
}
|
||||
notification.warning({
|
||||
key: 'notification',
|
||||
message: 'WARNING',
|
||||
description:
|
||||
`修改已提交,请等待审核(${seconds}s)`,
|
||||
duration: seconds
|
||||
})
|
||||
}, 1000)
|
||||
} else if (error.config.url === '/api/v0.1/ci_types/can_define_computed' || error.config.isShowMessage === false) {
|
||||
} else {
|
||||
const errorMsg = ((error.response || {}).data || {}).message || '出现错误,请稍后再试'
|
||||
message.error(`${errorMsg}`)
|
||||
}
|
||||
if (error.response) {
|
||||
if (error.response.status === 401) {
|
||||
store.dispatch('Logout')
|
||||
console.log(error.config.url)
|
||||
if (error.response.status === 401 && config.useSSO) {
|
||||
store.dispatch('Login')
|
||||
}
|
||||
}
|
||||
return Promise.reject(error)
|
||||
@@ -37,7 +75,7 @@ service.interceptors.response.use((response) => {
|
||||
|
||||
const installer = {
|
||||
vm: {},
|
||||
install (Vue) {
|
||||
install(Vue) {
|
||||
Vue.use(VueAxios, service)
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,12 @@
|
||||
export function timeFix () {
|
||||
import _ from 'lodash'
|
||||
export function timeFix() {
|
||||
const time = new Date()
|
||||
const hour = time.getHours()
|
||||
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
|
||||
}
|
||||
|
||||
export function welcome () {
|
||||
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
|
||||
export function welcome() {
|
||||
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA?', '我猜你可能累了', '你有一个小目标吗?']
|
||||
const index = Math.floor(Math.random() * arr.length)
|
||||
return arr[index]
|
||||
}
|
||||
@@ -13,18 +14,18 @@ export function welcome () {
|
||||
/**
|
||||
* 触发 window.resize
|
||||
*/
|
||||
export function triggerWindowResizeEvent () {
|
||||
export function triggerWindowResizeEvent() {
|
||||
const event = document.createEvent('HTMLEvents')
|
||||
event.initEvent('resize', true, true)
|
||||
event.eventType = 'message'
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
|
||||
export function handleScrollHeader (callback) {
|
||||
export function handleScrollHeader(callback) {
|
||||
let timer = 0
|
||||
|
||||
let beforeScrollTop = window.pageYOffset
|
||||
callback = callback || function () {}
|
||||
callback = callback || function () { }
|
||||
window.addEventListener(
|
||||
'scroll',
|
||||
event => {
|
||||
@@ -50,7 +51,7 @@ export function handleScrollHeader (callback) {
|
||||
* @param id parent element id or class
|
||||
* @param timeout
|
||||
*/
|
||||
export function removeLoadingAnimate (id = '', timeout = 1500) {
|
||||
export function removeLoadingAnimate(id = '', timeout = 1500) {
|
||||
if (id === '') {
|
||||
return
|
||||
}
|
||||
@@ -58,3 +59,103 @@ export function removeLoadingAnimate (id = '', timeout = 1500) {
|
||||
document.body.removeChild(document.getElementById(id))
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
export function debounce(fn, timeout = 300) {
|
||||
let timer
|
||||
return function (_this, ...args) {
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(_this, args)
|
||||
}, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
export function copyArray(arr) {
|
||||
return arr.map((e) => {
|
||||
if (typeof e === 'object') {
|
||||
return Object.assign({}, e)
|
||||
} else {
|
||||
return e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function sleep(n) {
|
||||
return new Promise((resolve) => setTimeout(resolve, n))
|
||||
}
|
||||
|
||||
export async function flicker(ele, property, value, interval = 300, times = 4) {
|
||||
const origin = ele.style[property]
|
||||
for (let i = 0; i < times * 2; i++) {
|
||||
if (i % 2) {
|
||||
ele.style[property] = value
|
||||
} else {
|
||||
ele.style[property] = origin
|
||||
}
|
||||
await sleep(interval)
|
||||
}
|
||||
ele.style[property] = origin
|
||||
}
|
||||
|
||||
// 数字加逗号
|
||||
export const toThousands = (num = 0) => {
|
||||
return num.toString().replace(/\d+/, function (n) {
|
||||
return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
|
||||
})
|
||||
}
|
||||
|
||||
// 从id得到部门名称
|
||||
export const getDepartmentName = (allFlatDepartments, id) => {
|
||||
const _find = allFlatDepartments.find((item) => item.department_id === id)
|
||||
return _find?.department_name || ''
|
||||
}
|
||||
|
||||
// 从id得到员工姓名
|
||||
export const getDirectorName = (allFlatEmployees, id) => {
|
||||
const _find = allFlatEmployees.find((item) => item.employee_id === id)
|
||||
return _find?.nickname || ''
|
||||
}
|
||||
|
||||
export const isEmptySubDepartments = (item) => {
|
||||
if (item.employees.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < item.sub_departments.length; i++) {
|
||||
if (!isEmptySubDepartments(item.sub_departments[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// format部门员工树
|
||||
export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentKey = 'department_id', employeeKey = 'employee_id') => {
|
||||
// idType 1 表示 员工id为`${department_id}-${employee_id}`
|
||||
// 2 表示 department-${department_id} employee-${employee_id}
|
||||
let _data = _.cloneDeep(data)
|
||||
_data = _data.filter((item) => {
|
||||
return item.employees.length || (item.sub_departments.length && !isEmptySubDepartments(item))
|
||||
})
|
||||
_data.forEach((item) => {
|
||||
if (isDisabledAllCompany) {
|
||||
item.isDisabled = !item.department_id
|
||||
}
|
||||
item.id = idType === 1 ? item[departmentKey] : `department-${item[departmentKey]}`
|
||||
item.label = item.department_name
|
||||
item.children = [
|
||||
...formatOption(
|
||||
item.sub_departments.map((dep) => {
|
||||
return { ...dep, id: idType === 1 ? dep[departmentKey] : `department-${dep[departmentKey]}`, label: dep.department_name }
|
||||
}),
|
||||
idType,
|
||||
isDisabledAllCompany,
|
||||
departmentKey,
|
||||
employeeKey
|
||||
),
|
||||
...item.employees.map((employee) => {
|
||||
return { ...employee, id: idType === 1 ? `${item[departmentKey]}-${employee[employeeKey]}` : `employee-${employee[employeeKey]}`, label: employee.nickname }
|
||||
}),
|
||||
]
|
||||
})
|
||||
return _data
|
||||
}
|
||||
|
0
cmdb-ui/src/utils/utils.css
Normal file
0
cmdb-ui/src/utils/utils.css
Normal file
Reference in New Issue
Block a user