前后端全面升级

This commit is contained in:
pycook
2023-07-10 17:42:15 +08:00
parent c444fed436
commit db5ff60aff
629 changed files with 97789 additions and 23995 deletions

View File

@@ -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
}
}

View File

@@ -16,4 +16,4 @@ export const setDocumentTitle = function (title) {
}
}
export const domTitle = 'CMDB'
export const domTitle = 'OneOps'

View 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
}

View File

@@ -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') {

View 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
}

View File

@@ -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 }

View File

@@ -1,8 +0,0 @@
export function actionToObject (json) {
try {
return JSON.parse(json)
} catch (e) {
console.log('err', e.message)
}
return []
}

View File

@@ -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)
}
}

View File

@@ -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
}

View File