feat: 添加年报服务集成和API自动生成功能
- 新增VUE_APP_AICEPS_SERVICE_URL环境变量配置 - 添加genapi.js用于根据swagger文档自动生成API接口文件 - 添加increpack.js打包插件用于版本管理和压缩打包 - 新增Empty.vue布局组件用于路由嵌套 - 优化Banner.vue背景样式设置 - 修改iframe页面集成oauth认证逻辑 - 更新代理配置支持年报服务接口转发 - 添加oauth API接口用于数据加密传输
This commit is contained in:
parent
fd051ebe7c
commit
d03f874202
|
|
@ -21,3 +21,6 @@ VUE_APP_RANDOM_URL=http://172.22.80.156:8085/aicods_gz_old/login/sso_home.html
|
|||
|
||||
#年报
|
||||
VUE_APP_AICEPS_URL = 'http://10.201.62.87:6891/gz-aiceps-manage'
|
||||
|
||||
VUE_APP_AICEPS_SERVICE_URL = 'http://localhost:9549'
|
||||
|
||||
|
|
|
|||
|
|
@ -14,3 +14,7 @@ VUE_APP_CAS_SERVER_UNITE = 'http://10.194.188.69/cas'
|
|||
|
||||
#年报
|
||||
VUE_APP_AICEPS_URL = 'http://10.201.62.87:6891/gz-aiceps-manage'
|
||||
|
||||
# 年报服务地址 无需写/aiceps-service-web 如和aiccs同域名同端口部署则置空
|
||||
VUE_APP_AICEPS_SERVICE_URL = ''
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
const axios = require('axios').default
|
||||
const fs = require('fs')
|
||||
const Path = require('path')
|
||||
|
||||
function mkdirsSync(dirname) {
|
||||
if (fs.existsSync(dirname)) {
|
||||
return true
|
||||
} else {
|
||||
if (mkdirsSync(Path.dirname(dirname))) {
|
||||
fs.mkdirSync(dirname)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
const fileTemplate = `/**
|
||||
* 该文件由插件根据doc.html在启动项目时自动生成,请勿修改(修改了也会被覆盖
|
||||
*/
|
||||
|
||||
import request from '@/utils/request'
|
||||
`
|
||||
const functionCodeGener = function(meta) {
|
||||
const functionParams = []
|
||||
if (Array.isArray(meta.params) && meta.params.length > 0) {
|
||||
functionParams.push('params')
|
||||
}
|
||||
if (Array.isArray(meta.data) && meta.data.length > 0) {
|
||||
functionParams.push('data')
|
||||
}
|
||||
if (Array.isArray(meta.formData) && meta.formData.length > 0) {
|
||||
functionParams.push('formData')
|
||||
}
|
||||
return `
|
||||
/**
|
||||
* ${meta.comment}
|
||||
*/
|
||||
export function ${meta.name}(${functionParams.join(', ')}) {
|
||||
return request({
|
||||
method: '${meta.method}',
|
||||
url: '${meta.url}'${meta.requestType ? ',\n requestType: \'' + meta.requestType + '\'' : ''}${functionParams.includes('params') ? ',\n params' : ''}${functionParams.includes('data') || functionParams.includes('formData') ? ',\n data' + (functionParams.includes('formData') ? ': formData' : '') : ''}
|
||||
})
|
||||
}
|
||||
`
|
||||
}
|
||||
module.exports = class Genapi {
|
||||
constructor(apiUrl, output = 'build') {
|
||||
this.apiUrl = apiUrl[apiUrl.length - 1] === '/' ? apiUrl.slice(0, apiUrl.length - 1) : apiUrl
|
||||
this.output = output
|
||||
}
|
||||
apply(compiler) {
|
||||
compiler.hooks.environment.tap('Genapi', async(compilation, callback) => {
|
||||
const projectPath = Path.join(__dirname, '../')
|
||||
const apiPath = Path.join(projectPath, 'src/api/', this.output)
|
||||
axios({
|
||||
url: this.apiUrl + '/swagger-resources',
|
||||
method: 'get'
|
||||
}).then(({ data }) => {
|
||||
const resultFile = {}
|
||||
Promise.all(data.map((apiScope) => {
|
||||
return axios({
|
||||
url: this.apiUrl + '/v2/api-docs',
|
||||
params: {
|
||||
group: apiScope.name
|
||||
},
|
||||
method: 'get'
|
||||
}).then(({ data }) => {
|
||||
const {
|
||||
basePath,
|
||||
paths
|
||||
} = data
|
||||
for (const _path in paths) {
|
||||
const path = _path.replace(new RegExp('^' + basePath, 'g'), '')
|
||||
const pathSplit = path.split('/').slice('/')
|
||||
const apiName = pathSplit[pathSplit.length - 1]
|
||||
const fileName = pathSplit.length > 2 ? pathSplit[pathSplit.length - 2] : ''
|
||||
const mkdirPath = pathSplit.slice(0, pathSplit.length - 2).join('/') || '/'
|
||||
const fileApiSet = new Set()
|
||||
const filePath = Path.join(mkdirPath, fileName)
|
||||
if (!resultFile[filePath]) {
|
||||
resultFile[filePath] = fileTemplate
|
||||
}
|
||||
for (const method in paths[_path]) {
|
||||
const apiMeta = paths[_path][method]
|
||||
const parameters = apiMeta.parameters || []
|
||||
const formData = parameters.filter((item) => {
|
||||
return item.in === 'formData'
|
||||
})
|
||||
const data = parameters.filter((item) => {
|
||||
return item.in === 'body'
|
||||
})
|
||||
const params = parameters.filter((item) => {
|
||||
return item.in === 'query'
|
||||
})
|
||||
resultFile[filePath] += functionCodeGener({
|
||||
name: (() => {
|
||||
const filterApiName = apiName.replace(/\.do$/g, '')
|
||||
let result = Object.keys(paths[_path]).length > 1 ? `${method}_${filterApiName}` : filterApiName
|
||||
if (fileApiSet.has(result)) {
|
||||
let i = 1
|
||||
while (fileApiSet.has(`${result}_${i}`)) {
|
||||
i++
|
||||
}
|
||||
result = `${result}_${i}`
|
||||
}
|
||||
return result
|
||||
})(),
|
||||
method,
|
||||
url: path,
|
||||
comment: apiMeta.summary,
|
||||
data,
|
||||
params,
|
||||
formData,
|
||||
requestType: (() => {
|
||||
if (method !== 'get') {
|
||||
if (formData.length > 0) {
|
||||
return 'formdata'
|
||||
} else {
|
||||
return 'json'
|
||||
}
|
||||
}
|
||||
})()
|
||||
})
|
||||
}
|
||||
}
|
||||
}).catch((e) => {
|
||||
console.warn(`无法读取api文档: ${apiScope.name}`)
|
||||
console.warn(e.message)
|
||||
})
|
||||
})).then(() => {
|
||||
for (const path in resultFile) {
|
||||
mkdirsSync(Path.join(apiPath, path))
|
||||
const filepath = Path.join(apiPath, path, 'index.js')
|
||||
if (fs.existsSync(filepath) && fs.readFileSync(filepath).toString() !== resultFile[path]) {
|
||||
fs.writeFileSync(filepath, resultFile[path])
|
||||
}
|
||||
}
|
||||
})
|
||||
}).catch((e) => { })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const compressing = require('compressing')
|
||||
const axios = require('axios')
|
||||
const child_process = require('child_process')
|
||||
const packageJson = require('../package.json')
|
||||
function parseTime(time, format = 'yyyy-MM-dd hh:mm:ss') {
|
||||
const date = time instanceof Date ? time : new Date(time)
|
||||
|
||||
const o = {
|
||||
'M+': date.getMonth() + 1, // 月份
|
||||
'd+': date.getDate(), // 日
|
||||
'h+': date.getHours(), // 小时
|
||||
'm+': date.getMinutes(), // 分
|
||||
's+': date.getSeconds(), // 秒
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
|
||||
'S': date.getMilliseconds() // 毫秒
|
||||
}
|
||||
if (/(y+)/.test(format)) {
|
||||
format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||
}
|
||||
for (const k in o) {
|
||||
if (new RegExp('(' + k + ')').test(format)) {
|
||||
format = format.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
|
||||
}
|
||||
}
|
||||
return format
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包插件 v2.0
|
||||
* youfool
|
||||
*/
|
||||
class IncrePack {
|
||||
apply(compiler) {
|
||||
if (process.env.VUE_APP_WEBPACK_CMD !== 'build') {
|
||||
return
|
||||
}
|
||||
const date = new Date()
|
||||
const projectPath = path.join(__dirname, '../')
|
||||
const distPath = projectPath + 'dist'
|
||||
const versionPath = `${projectPath}src/version.js`
|
||||
let hash = '000000'
|
||||
try {
|
||||
hash = child_process.execSync('git rev-parse HEAD').slice(0, 6)
|
||||
} catch (e) {
|
||||
console.log('------------------读取版本Hash失败---------------')
|
||||
console.warn(e)
|
||||
}
|
||||
const codeVersion = `${parseTime(date, 'yyyy-MM-dd hh:mm:ss')} ${hash} ${process.env.VUE_APP_ENVIRONMENT}`
|
||||
compiler.hooks.beforeRun.tapAsync('SetVersion', async(compilation, callback) => {
|
||||
const data = `/** 本文件由打包插件自动生成和修改 */\nexport default '${codeVersion}'\n`
|
||||
fs.writeFileSync(versionPath, data)
|
||||
callback()
|
||||
})
|
||||
compiler.hooks.done.tap('SetVersion', async(compilation) => {
|
||||
const data = `/** 本文件由打包插件自动生成和修改 */\nexport default ''\n`
|
||||
fs.writeFileSync(versionPath, data)
|
||||
})
|
||||
compiler.hooks.done.tap('IncrePack', async(compilation) => {
|
||||
let versionJson = {
|
||||
artifactId: packageJson.name,
|
||||
version: packageJson.version,
|
||||
appId: packageJson.appId,
|
||||
codeId: packageJson.codeId,
|
||||
codeVersion
|
||||
}
|
||||
if (packageJson.increApi) {
|
||||
// 获取版本信息
|
||||
try {
|
||||
console.log('------------------正在写入升级记录---------------')
|
||||
const res = await axios.default({
|
||||
url: packageJson.increApi + '?appId=' + packageJson.appId + '&codeId=' + packageJson.codeId,
|
||||
method: 'get',
|
||||
timeout: 5000
|
||||
})
|
||||
const { code, data } = res.data
|
||||
if (code === 0 && data) {
|
||||
versionJson = {
|
||||
...versionJson,
|
||||
artifactId: packageJson.name,
|
||||
upgradeId: data.upgradeId,
|
||||
version: data.version,
|
||||
releaseTime: data.releaseTime,
|
||||
fromCommit: data.fromCommit,
|
||||
untilCommit: data.untilCommit,
|
||||
newFeatures: data.newFeatures,
|
||||
repair: data.repair,
|
||||
other: data.other
|
||||
}
|
||||
console.log('------------------写入升级记录成功---------------')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
console.log('------------------提交升级记录到远端失败---------------')
|
||||
}
|
||||
}
|
||||
fs.mkdirSync(distPath + '/increpack-config')
|
||||
fs.writeFileSync(distPath + '/increpack-config/version.json', JSON.stringify(versionJson), 'utf8')
|
||||
const increName = `${packageJson.name}-${process.env.VUE_APP_ENVIRONMENT}-${parseTime(date, 'yyyy-MM-dd')}-${hash}.zip`
|
||||
// 打包压缩
|
||||
const tempFile = projectPath + '/' + increName
|
||||
compressing.zip.compressDir(distPath, tempFile, { ignoreBase: true })
|
||||
.then(() => {
|
||||
// 剪切回dist目录下
|
||||
fs.renameSync(tempFile, distPath + '/' + increName)
|
||||
console.log('------------------打包成功------------------')
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
module.exports = IncrePack
|
||||
|
|
@ -139,3 +139,10 @@ export function isHaveUser(phone) {
|
|||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
export function oauth() {
|
||||
return request({
|
||||
url: '/aiccs-api/oauth2/sm4/encrypted/data',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<template>
|
||||
<router-view v-slot="scoped">
|
||||
{{
|
||||
(() => {
|
||||
routerView = scoped
|
||||
})()
|
||||
}}
|
||||
<keep-alive>
|
||||
<component :is="scoped.Component" v-if="$route.meta.keepAlive" :key="$route.path" />
|
||||
</keep-alive>
|
||||
<component :is="scoped.Component" v-if="!$route.meta.keepAlive" :key="$route.path" />
|
||||
</router-view>
|
||||
</template>
|
||||
|
|
@ -98,7 +98,9 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* background: linear-gradient(66deg,#054dd3 0%, #3296fa 89%); */
|
||||
background: url('../../assets/images/banner.png') no-repeat;
|
||||
background-image: url('../../assets/images/banner.png') ;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
/* box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.16); */
|
||||
font-family: 'Source Han Sans CN';
|
||||
z-index: 2000;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { getUserMenus } from '@/api/router'
|
|||
import user from './user'
|
||||
import { Message } from 'element-ui'
|
||||
import Layout from '@/layout'
|
||||
import Empty from '@/layout/Empty'
|
||||
|
||||
/**
|
||||
* Use meta.role to determine if the current user has permission
|
||||
|
|
@ -47,10 +48,18 @@ export function generaMenu(routes, data, curPath = '') {
|
|||
} else {
|
||||
iconName = 'default'
|
||||
}
|
||||
let component = () => import('@/views/iframe/index')
|
||||
if (item.children && item.children.length > 0) {
|
||||
if (item.level === 1) {
|
||||
component = Layout
|
||||
} else {
|
||||
component = Empty
|
||||
}
|
||||
}
|
||||
const menu = {
|
||||
path: (curPath === '/' ? '' : curPath) + item.path,
|
||||
component: item.pid === '' ? Layout : () => import('@/views/iframe/index'),
|
||||
redirect: item.pid === '' ? (curPath === '/' ? '' : curPath) + item.path + (item.children.length > 0 ? item.children[0].path : '') : '',
|
||||
component,
|
||||
redirect: !item.pid ? (curPath === '/' ? '' : curPath) + item.path + (item.children.length > 0 ? item.children[0].path : '') : '',
|
||||
children: [],
|
||||
name: item.path,
|
||||
meta: { title: item.title, id: item.sysMenuId, icon: iconName }
|
||||
|
|
@ -125,6 +134,7 @@ const actions = {
|
|||
})
|
||||
Object.assign(loadMenuData, data)
|
||||
generaMenu(asyncRoutes, loadMenuData)
|
||||
console.log('动态路由', asyncRoutes)
|
||||
let accessedRoutes
|
||||
roles = ['admin']
|
||||
if (roles.includes('admin')) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
</template>
|
||||
<script>
|
||||
// import router from '../../router'
|
||||
import { oauth } from '@/api/user'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
src: ''
|
||||
}
|
||||
},
|
||||
|
|
@ -19,7 +21,14 @@ export default {
|
|||
}
|
||||
return path
|
||||
})
|
||||
if (path.startsWith('/aiceps-service-web')) {
|
||||
oauth().then((res) => {
|
||||
const { data } = res
|
||||
this.src = `${process.env.VUE_APP_AICEPS_SERVICE_URL || ''}/aiceps-service-web/#/oauthLogin?redirectUri=${encodeURIComponent(path.split('/#')[1])}&isIframe=1&encryptedData=${data}`
|
||||
})
|
||||
} else {
|
||||
this.src = path
|
||||
}
|
||||
|
||||
// 3.添加监听子iframe事件
|
||||
window.addEventListener('message', this.iframeMessage, false)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,28 @@ module.exports = {
|
|||
// 如果有多个mock请往里面继续添加
|
||||
'/gz-aiceps-manage': {
|
||||
// target: `http://localhost:8085/`,
|
||||
target: `http://172.22.80.35`,
|
||||
// target: `http://172.22.80.35`,
|
||||
// target: 'http://121.8.152.133/',
|
||||
target: `http://172.22.80.67:8089`,
|
||||
// target: `http://10.194.188.237`,
|
||||
// target: `http://127.0.0.1:8093`,
|
||||
// target: `http://192.168.100.26:9528`,
|
||||
changeOrigin: true
|
||||
},
|
||||
'/aiceps-service-server': {
|
||||
// target: `http://localhost:8085/`,
|
||||
// target: `http://172.22.80.35`,
|
||||
target: `http://localhost:9549/`,
|
||||
// target: `http://10.194.188.238`,
|
||||
// target: `http://10.194.188.237`,
|
||||
// target: `http://127.0.0.1:8093`,
|
||||
// target: `http://192.168.100.26:9528`,
|
||||
changeOrigin: true
|
||||
},
|
||||
'/aiceps-service-web': {
|
||||
// target: `http://localhost:8085/`,
|
||||
// target: `http://172.22.80.35`,
|
||||
target: 'http://localhost:9549/',
|
||||
// target: `http://10.194.188.238`,
|
||||
// target: `http://10.194.188.237`,
|
||||
// target: `http://127.0.0.1:8093`,
|
||||
|
|
@ -51,7 +72,9 @@ module.exports = {
|
|||
},
|
||||
'/': {
|
||||
// target: `http://localhost:8085/`,
|
||||
target: `http://172.22.80.35`,
|
||||
// target: `http://172.22.80.35`,
|
||||
target: `http://172.22.80.67:8089`,
|
||||
// target: 'http://192.168.100.233:8086/',
|
||||
// target: `http://10.194.188.238`,
|
||||
// target: `http://10.194.188.237`,
|
||||
// target: `http://127.0.0.1:8090`,
|
||||
|
|
|
|||
Loading…
Reference in New Issue