This commit is contained in:
Jane
2023-12-22 12:18:52 +08:00
parent 340f82a67e
commit 812109656a
746 changed files with 84928 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="接口名称" prop="apiName">
<el-input v-model="form.apiName" />
</el-form-item>
<el-form-item label="调用者ip" prop="callerIp">
<el-input v-model="form.callerIp" />
</el-form-item>
<el-form-item label="调用接口url" prop="callerUrl">
<el-input v-model="form.callerUrl" />
</el-form-item>
<el-form-item label="调用参数" prop="callerParams">
<el-input v-model="form.callerParams" />
</el-form-item>
<el-form-item label="调用时间" prop="callerDate">
<el-input v-model="form.callerDate" />
</el-form-item>
<el-form-item label="调用耗时" prop="time">
<el-input v-model="form.time" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="信息记录" prop="msg">
<el-input v-model="form.msg" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { getApiLog } from '@/api/market/apilog'
export default {
name: 'ApiLogDetail',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
classCardbody: {
overflow: 'auto',
height: document.body.offsetHeight - 240 + 'px'
},
title: '接口日志详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 表单参数
form: {},
// 状态数据字典
statusOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_normal_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
},
mounted() {
this.getLog(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getLog: function(id) {
getApiLog(id).then(response => {
if (response.success) {
this.form = response.data
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,283 @@
<template>
<el-card class="box-card" shadow="always">
<el-form ref="queryForm" :model="queryParams" :inline="true">
<el-form-item label="接口名称" prop="apiName">
<el-input
v-model="queryParams.apiName"
placeholder="请输入接口名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group />
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="logList"
border
tooltip-effect="dark"
:size="tableSize"
:height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:key="index"
:prop="item.prop"
:label="item.label"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-popover
placement="left"
trigger="click"
>
<el-button
v-hasPerm="['market:api:log:detail']"
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPerm="['market:api:log:remove']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script>
import { pageApiLog, delApiLog } from '@/api/market/apilog'
export default {
name: 'ApiLogList',
data() {
return {
tableHeight: document.body.offsetHeight - 310 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 遮罩层
loading: true,
// 表格头
tableColumns: [
{ prop: 'apiName', label: '接口名称', show: true },
{ prop: 'callerIp', label: '调用者ip', show: true },
{ prop: 'callerSize', label: '调用数据量', show: true },
{ prop: 'time', label: '调用耗时', show: true },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'callerDate', label: '调用时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 日志表格数据
logList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
apiName: ''
},
// 状态数据字典
statusOptions: []
}
},
created() {
this.getDicts('sys_normal_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getList()
},
mounted() {
this.initCols()
},
methods: {
/** 查询日志列表 */
getList() {
this.loading = true
pageApiLog(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.logList = data.data
this.total = data.total
}
})
},
initCols() {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange(val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand(command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
apiName: ''
}
this.handleQuery()
},
/** 刷新列表 */
handleRefresh() {
this.getList()
},
/** 详情按钮操作 */
handleDetail(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delApiLog(row.id).then(response => {
if (response.success) {
this.$message.success('删除成功')
this.getList()
}
})
}).catch(() => {
})
},
handleSizeChange(val) {
console.log(`每页 ${val}`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
statusFormatter(row, column, cellValue, index) {
const dictLabel = this.selectDictLabel(this.statusOptions, cellValue)
if (cellValue === '1') {
return <el-tag type='success'>{dictLabel}</el-tag>
} else {
return <el-tag type='warning'>{dictLabel}</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
.el-card ::v-deep .el-card__body {
height: calc(100vh - 170px);
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<log-list v-if="options.showList" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<log-detail v-if="options.showDetail" :data="options.data" @showCard="showCard" />
</transition>
</div>
</template>
<script>
import LogList from './LogList'
import LogDetail from './LogDetail'
export default {
name: 'ApiLog',
components: { LogList, LogDetail },
data() {
return {
options: {
data: {},
showList: true,
showDetail: false
}
}
},
methods: {
showCard(data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,305 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:mask:add']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="数据API" prop="apiId">
<el-select v-model="form.apiId" placeholder="请选择数据API" @change="apiSelectChanged">
<el-option
v-for="api in apiOptions"
:key="api.id"
:label="api.apiName"
:value="api.id"
:disabled="api.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item>
<el-form-item label="脱敏字段规则配置" prop="rules">
<el-table
:data="resParamList"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" @click="fieldRule(scope.row.fieldName)">{{ scope.row.fieldName }}</el-button>
</template>
</el-table-column>
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip />
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip />
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip />
</el-table>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<!-- 脱敏规则对话框 -->
<el-dialog :title="cipher.title" :visible.sync="cipher.open" width="400px" append-to-body>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-form-item label="字段名称" prop="fieldName">
<el-input v-model="form2.fieldName" placeholder="请输入字段名称" :disabled="true" />
</el-form-item>
<el-form-item label="脱敏类型" prop="cipherType">
<el-select v-model="form2.cipherType" clearable placeholder="请选择脱敏类型" @change="cipherTypeSelectChanged">
<el-option
v-for="dict in cipherTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="规则类型" prop="cryptType">
<el-select v-model="form2.cryptType" clearable placeholder="请选择规则类型">
<el-option
v-for="dict in cryptTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFieldCipherForm"> </el-button>
<el-button @click="cipher.open = false"> </el-button>
</div>
</el-dialog>
</div>
</el-card>
</template>
<script>
import { addApiMask } from '@/api/market/apimask'
import { listDataApi, getDataApi } from '@/api/market/dataapi'
export default {
name: 'ApiMaskAdd',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API脱敏新增',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1',
remark: undefined
},
// 表单校验
rules: {
apiId: [
{ required: true, message: '数据API不能为空', trigger: 'blur' }
],
maskName: [
{ required: true, message: '脱敏名称不能为空', trigger: 'blur' }
]
},
form2: {
fieldName: undefined,
cipherType: undefined,
cryptType: undefined
},
rules2: {
fieldName: [
{ required: true, message: '字段名称不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: [],
// 数据API数据字典
apiOptions: [],
// 脱敏字段信息
resParamList: [],
// 脱敏类型数据字典
cipherTypeOptions: [],
cryptTypeOptions: [],
// 正则替换数据字典
regexCryptoOptions: [],
// 加密算法数据字典
algorithmCryptoOptions: [],
cipher: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: '脱敏规则配置'
}
}
},
created() {
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDataApiList()
this.getDicts('data_cipher_type').then(response => {
if (response.success) {
this.cipherTypeOptions = response.data
}
})
this.getDicts('data_regex_crypto').then(response => {
if (response.success) {
this.regexCryptoOptions = response.data
}
})
this.getDicts('data_algorithm_crypto').then(response => {
if (response.success) {
this.algorithmCryptoOptions = response.data
}
})
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataApiList() {
listDataApi().then(response => {
if (response.success) {
this.apiOptions = response.data
}
})
},
apiSelectChanged(val) {
getDataApi(val).then(response => {
if (response.success) {
this.resParamList = response.data.resParams
}
})
},
fieldRule(fieldName) {
this.cipher.open = true
this.form2.fieldName = fieldName
this.form2.cipherType = undefined
this.form2.cryptType = undefined
this.cryptTypeOptions = []
},
cipherTypeSelectChanged(val) {
this.form2.cryptType = undefined
this.cryptTypeOptions = []
if (val === '1') {
// 正则替换
this.cryptTypeOptions = this.regexCryptoOptions
} else if (val === '2') {
// 加密算法
this.cryptTypeOptions = this.algorithmCryptoOptions
}
},
submitFieldCipherForm() {
const fieldRuleIndex = this.form.rules.findIndex((item) => {
return item.fieldName === this.form2.fieldName
})
if (fieldRuleIndex !== -1) {
// 当返回-1时则说明数组中没有
this.form.rules.splice(fieldRuleIndex, 1)
}
if (this.form2.cipherType && this.form2.cryptType) {
this.form.rules.push(this.form2)
}
const cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === this.form2.cipherType
})
const crypt = this.cryptTypeOptions.find((item) => {
return item.itemText === this.form2.cryptType
})
const fieldParamIndex = this.resParamList.findIndex((item) => {
return item.fieldName === this.form2.fieldName
})
const resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.$set(this.resParamList, fieldParamIndex, resParam)
this.cipher.open = false
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.rules.length <= 0) {
this.$message.error('脱敏字段规则配置不能为空')
return
}
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
addApiMask(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,198 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="数据API" prop="apiId">
<el-select v-model="form.apiId" placeholder="请选择数据API">
<el-option
v-for="api in apiOptions"
:key="api.id"
:label="api.apiName"
:value="api.id"
:disabled="api.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item>
<el-form-item label="脱敏字段规则配置" prop="rules">
<el-table
:data="resParamList"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip />
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip />
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip />
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip />
</el-table>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { getApiMask } from '@/api/market/apimask'
import { listDataApi, getDataApi } from '@/api/market/dataapi'
export default {
name: 'ApiMaskDetail',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API脱敏详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 表单参数
form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1',
remark: undefined
},
// 状态数据字典
statusOptions: [],
// 数据API数据字典
apiOptions: [],
// 脱敏字段信息
resParamList: [],
// 脱敏类型数据字典
cipherTypeOptions: [],
// 正则替换数据字典
regexCryptoOptions: [],
// 加密算法数据字典
algorithmCryptoOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_cipher_type').then(response => {
if (response.success) {
this.cipherTypeOptions = response.data
}
})
this.getDicts('data_regex_crypto').then(response => {
if (response.success) {
this.regexCryptoOptions = response.data
}
})
this.getDicts('data_algorithm_crypto').then(response => {
if (response.success) {
this.algorithmCryptoOptions = response.data
}
})
this.getDataApiList()
},
mounted() {
this.getApiMask(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataApiList() {
listDataApi().then(response => {
if (response.success) {
this.apiOptions = response.data
}
})
},
/** 获取详情 */
async getApiMask() {
this.form = await getApiMask(this.data.id).then(response => {
if (response.success) {
return response.data
}
}) || {}
if (this.form && this.form.apiId) {
const dataApi = await getDataApi(this.form.apiId).then(response => {
if (response.success) {
return response.data
}
}) || {}
if (dataApi && dataApi.resParams.length > 0) {
this.resParamList = dataApi.resParams
this.form.rules.forEach(rule => {
const fieldParamIndex = this.resParamList.findIndex((param) => {
return param.fieldName === rule.fieldName
})
if (fieldParamIndex !== -1) {
const cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === rule.cipherType
})
let crypt = {}
if (rule.cipherType === '1') {
crypt = this.regexCryptoOptions.find((item) => {
return item.itemText === rule.cryptType
})
} else if (rule.cipherType === '2') {
crypt = this.algorithmCryptoOptions.find((item) => {
return item.itemText === rule.cryptType
})
}
const resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.$set(this.resParamList, fieldParamIndex, resParam)
}
})
}
}
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,342 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:mask:edit']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="数据API" prop="apiId">
<el-select v-model="form.apiId" placeholder="请选择数据API" disabled>
<el-option
v-for="api in apiOptions"
:key="api.id"
:label="api.apiName"
:value="api.id"
:disabled="api.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item>
<el-form-item label="脱敏字段规则配置" prop="rules">
<el-table
:data="resParamList"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" @click="fieldRule(scope.row.fieldName)">{{ scope.row.fieldName }}</el-button>
</template>
</el-table-column>
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip />
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip />
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip />
</el-table>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<!-- 脱敏规则对话框 -->
<el-dialog :title="cipher.title" :visible.sync="cipher.open" width="400px" append-to-body>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-form-item label="字段名称" prop="fieldName">
<el-input v-model="form2.fieldName" placeholder="请输入字段名称" :disabled="true" />
</el-form-item>
<el-form-item label="脱敏类型" prop="cipherType">
<el-select v-model="form2.cipherType" clearable placeholder="请选择脱敏类型" @change="cipherTypeSelectChanged">
<el-option
v-for="dict in cipherTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="规则类型" prop="cryptType">
<el-select v-model="form2.cryptType" clearable placeholder="请选择规则类型">
<el-option
v-for="dict in cryptTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFieldCipherForm"> </el-button>
<el-button @click="cipher.open = false"> </el-button>
</div>
</el-dialog>
</div>
</el-card>
</template>
<script>
import { getApiMask, updateApiMask } from '@/api/market/apimask'
import { listDataApi, getDataApi } from '@/api/market/dataapi'
export default {
name: 'ApiMaskEdit',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API脱敏编辑',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1',
remark: undefined
},
// 表单校验
rules: {
apiId: [
{ required: true, message: '数据API不能为空', trigger: 'blur' }
],
maskName: [
{ required: true, message: '脱敏名称不能为空', trigger: 'blur' }
]
},
form2: {
fieldName: undefined,
cipherType: undefined,
cryptType: undefined
},
rules2: {
fieldName: [
{ required: true, message: '字段名称不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: [],
// 数据API数据字典
apiOptions: [],
// 脱敏字段信息
resParamList: [],
// 脱敏类型数据字典
cipherTypeOptions: [],
cryptTypeOptions: [],
// 正则替换数据字典
regexCryptoOptions: [],
// 加密算法数据字典
algorithmCryptoOptions: [],
cipher: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: '脱敏规则配置'
}
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_cipher_type').then(response => {
if (response.success) {
this.cipherTypeOptions = response.data
}
})
this.getDicts('data_regex_crypto').then(response => {
if (response.success) {
this.regexCryptoOptions = response.data
}
})
this.getDicts('data_algorithm_crypto').then(response => {
if (response.success) {
this.algorithmCryptoOptions = response.data
}
})
this.getDataApiList()
},
mounted() {
this.getApiMask()
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataApiList() {
listDataApi().then(response => {
if (response.success) {
this.apiOptions = response.data
}
})
},
/** 获取详情 */
async getApiMask() {
this.form = await getApiMask(this.data.id).then(response => {
if (response.success) {
return response.data
}
}) || {}
if (this.form && this.form.apiId) {
const dataApi = await getDataApi(this.form.apiId).then(response => {
if (response.success) {
return response.data
}
}) || {}
if (dataApi && dataApi.resParams.length > 0) {
this.resParamList = dataApi.resParams
this.form.rules.forEach(rule => {
const fieldParamIndex = this.resParamList.findIndex((param) => {
return param.fieldName === rule.fieldName
})
if (fieldParamIndex !== -1) {
const cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === rule.cipherType
})
let crypt = {}
if (rule.cipherType === '1') {
crypt = this.regexCryptoOptions.find((item) => {
return item.itemText === rule.cryptType
})
} else if (rule.cipherType === '2') {
crypt = this.algorithmCryptoOptions.find((item) => {
return item.itemText === rule.cryptType
})
}
const resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.$set(this.resParamList, fieldParamIndex, resParam)
}
})
}
}
},
fieldRule(fieldName) {
this.cipher.open = true
this.form2.fieldName = fieldName
this.form2.cipherType = undefined
this.form2.cryptType = undefined
this.cryptTypeOptions = []
},
cipherTypeSelectChanged(val) {
this.form2.cryptType = undefined
this.cryptTypeOptions = []
if (val === '1') {
// 正则替换
this.cryptTypeOptions = this.regexCryptoOptions
} else if (val === '2') {
// 加密算法
this.cryptTypeOptions = this.algorithmCryptoOptions
}
},
submitFieldCipherForm() {
const fieldRuleIndex = this.form.rules.findIndex((item) => {
return item.fieldName === this.form2.fieldName
})
if (fieldRuleIndex !== -1) {
// 当返回-1时则说明数组中没有
this.form.rules.splice(fieldRuleIndex, 1)
}
if (this.form2.cipherType && this.form2.cryptType) {
this.form.rules.push(this.form2)
}
const cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === this.form2.cipherType
})
const crypt = this.cryptTypeOptions.find((item) => {
return item.itemText === this.form2.cryptType
})
const fieldParamIndex = this.resParamList.findIndex((item) => {
return item.fieldName === this.form2.fieldName
})
const resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.$set(this.resParamList, fieldParamIndex, resParam)
this.cipher.open = false
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
if (this.form.rules.length <= 0) {
this.$message.error('脱敏字段规则配置不能为空')
return
}
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
updateApiMask(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,317 @@
<template>
<el-card class="box-card" shadow="always">
<el-form ref="queryForm" :model="queryParams" :inline="true">
<el-form-item label="脱敏名称" prop="maskName">
<el-input
v-model="queryParams.maskName"
placeholder="请输入脱敏名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
v-hasPerm="['market:mask:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="apiMaskList"
border
tooltip-effect="dark"
:size="tableSize"
:height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:key="index"
:prop="item.prop"
:label="item.label"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-popover
placement="left"
trigger="click"
>
<el-button
v-hasPerm="['market:mask:edit']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>修改</el-button>
<el-button
v-hasPerm="['market:mask:detail']"
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPerm="['market:mask:remove']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script>
import { pageApiMask, delApiMask } from '@/api/market/apimask'
export default {
name: 'ApiMaskList',
data() {
return {
tableHeight: document.body.offsetHeight - 310 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 遮罩层
loading: true,
// 表格头
tableColumns: [
{ prop: 'maskName', label: '脱敏名称', show: true },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'createTime', label: '创建时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 状态数据字典
statusOptions: [],
// 数据集表格数据
apiMaskList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
maskName: ''
}
}
},
created() {
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getList()
},
mounted() {
this.initCols()
},
methods: {
/** 查询数据Api脱敏列表 */
getList() {
this.loading = true
pageApiMask(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.apiMaskList = data.data
this.total = data.total
}
})
},
initCols() {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange(val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand(command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
maskName: ''
}
this.handleQuery()
},
/** 刷新列表 */
handleRefresh() {
this.getList()
},
/** 新增按钮操作 */
handleAdd() {
this.showOptions.data = {}
this.showOptions.showList = false
this.showOptions.showAdd = true
this.showOptions.showEdit = false
this.showOptions.showDetail = false
this.$emit('showCard', this.showOptions)
},
/** 修改按钮操作 */
handleEdit(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = true
this.showOptions.showDetail = false
this.$emit('showCard', this.showOptions)
},
/** 详情按钮操作 */
handleDetail(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delApiMask(row.id).then(response => {
if (response.success) {
this.$message.success('删除成功')
this.getList()
}
})
}).catch(() => {
})
},
handleSizeChange(val) {
console.log(`每页 ${val}`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
statusFormatter(row, column, cellValue, index) {
const dictLabel = this.selectDictLabel(this.statusOptions, cellValue)
if (cellValue === '1') {
return <el-tag type='success'>{dictLabel}</el-tag>
} else {
return <el-tag type='warning'>{dictLabel}</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
.el-card ::v-deep .el-card__body {
height: calc(100vh - 170px);
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<api-mask-list v-if="options.showList" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<api-mask-add v-if="options.showAdd" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<api-mask-edit v-if="options.showEdit" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<api-mask-detail v-if="options.showDetail" :data="options.data" @showCard="showCard" />
</transition>
</div>
</template>
<script>
import ApiMaskList from './ApiMaskList'
import ApiMaskAdd from './ApiMaskAdd'
import ApiMaskEdit from './ApiMaskEdit'
import ApiMaskDetail from './ApiMaskDetail'
export default {
name: 'ApiMask',
components: { ApiMaskList, ApiMaskAdd, ApiMaskEdit, ApiMaskDetail },
data() {
return {
options: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
}
}
},
methods: {
showCard(data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,577 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:api:add']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-steps :active="active" finish-status="success" align-center>
<el-step title="属性配置" />
<el-step title="执行配置" />
<el-step title="参数配置" />
</el-steps>
<el-form v-if="active == 1" ref="form1" :model="form1" :rules="rules1" label-width="80px">
<el-form-item label="API名称" prop="apiName">
<el-input v-model="form1.apiName" placeholder="请输入API名称" />
</el-form-item>
<el-form-item label="API版本" prop="apiVersion">
<el-input v-model="form1.apiVersion" placeholder="请输入API版本如v1.0.0" />
</el-form-item>
<el-form-item label="API路径" prop="apiUrl">
<el-input v-model="form1.apiUrl" placeholder="请输入API路径" />
</el-form-item>
<el-form-item label="请求方式" prop="reqMethod">
<el-select v-model="form1.reqMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in reqMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="返回格式" prop="resType">
<el-select v-model="form1.resType" placeholder="请选择返回格式">
<el-option
v-for="dict in resTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="IP黑名单" prop="deny">
<el-input v-model="form1.deny" type="textarea" placeholder="请输入IP黑名单多个用英文,隔开" />
</el-form-item>
<el-form-item label="是否限流" prop="rateLimit">
<el-radio-group v-model="form1.rateLimit.enable">
<el-radio
v-for="dict in whetherOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form1.rateLimit.enable === '1'" label="限流配置">
<el-input-number v-model="form1.rateLimit.seconds" controls-position="right" :min="1" />秒内限制请求
<el-input-number v-model="form1.rateLimit.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form1.status" disabled>
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form v-if="active == 2" ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-form-item label="配置方式" prop="configType">
<el-select v-model="form2.configType" placeholder="请选择配置方式" @change="configTypeSelectChanged">
<el-option
v-for="dict in configTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="数据源" prop="sourceId">
<el-select v-model="form2.sourceId" placeholder="请选择数据源" @change="sourceSelectChanged">
<el-option
v-for="source in sourceOptions"
:key="source.id"
:label="source.sourceName"
:value="source.id"
:disabled="source.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="数据库表" prop="tableName">
<el-select v-model="form2.table" value-key="id" placeholder="请选择数据库表" @change="tableSelectChanged">
<el-option
v-for="item in tableOptions"
:key="item.id"
:label="item.tableComment ? item.tableComment : item.tableName"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="字段列表">
<el-table
:data="form2.fieldParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column prop="columnPosition" label="序号" width="55" align="center" />
<el-table-column prop="columnName" label="列名" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip />
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip />
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip />
<el-table-column prop="columnKey" label="是否主键" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnKey === '1'">Y</span>
<span v-if="scope.row.columnKey === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="columnNullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnNullable === '1'">Y</span>
<span v-if="scope.row.columnNullable === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip />
<el-table-column prop="columnComment" label="列注释" align="center" show-overflow-tooltip />
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable" true-label="1" false-label="0" @change="checked=>reqCheckChange(scope.row, checked)" />
</template>
</el-table-column>
<el-table-column prop="resable" label="是否作为返回参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.resable" true-label="1" false-label="0" @change="checked=>resCheckChange(scope.row, checked)" />
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-row v-if="form2.configType === '2'">
<el-col :span="24">
<sql-editor
ref="sqleditor"
:value="form2.sqlText"
style="height: 300px;margin: 10px 10px;"
@changeTextarea="changeTextarea($event)"
/>
</el-col>
</el-row>
<el-form-item v-if="form2.configType === '2'">
<el-button size="mini" type="primary" @click="sqlParse">SQL解析</el-button>
</el-form-item>
</el-form>
<el-form v-if="active == 3" ref="form3" :model="form3" label-width="80px">
<el-divider content-position="left">请求参数</el-divider>
<el-table
:data="form3.reqParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip />
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" />
</template>
</el-table-column>
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.paramComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型">
<el-option
v-for="dict in paramTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.whereType" placeholder="请选择操作符">
<el-option
v-for="dict in whereTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.defaultValue" placeholder="请输入默认值" />
</template>
</el-table-column>
</el-table>
<el-divider content-position="left">返回字段</el-divider>
<el-table
:data="form3.resParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip />
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.fieldComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.dataType" placeholder="请输入数据类型" />
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
</el-table>
</el-form>
<el-button v-if="active < 3" style="margin-top: 12px;" @click="handleNextStep">下一步</el-button>
<el-button v-if="active > 1" style="margin-top: 12px;" @click="handleLastStep">上一步</el-button>
</div>
</el-card>
</template>
<script>
import { addDataApi, sqlParse } from '@/api/market/dataapi'
import { listDataSource } from '@/api/metadata/datasource'
import { listDataTable } from '@/api/metadata/datatable'
import { listDataColumn } from '@/api/metadata/datacolumn'
import SqlEditor from '@/components/SqlEditor'
export default {
name: 'DataApiAdd',
components: {
SqlEditor
},
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API新增',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
active: 1,
// 表单参数
form1: {
id: undefined,
apiName: undefined,
apiVersion: undefined,
apiUrl: undefined,
reqMethod: undefined,
resType: undefined,
deny: undefined,
rateLimit: {
enable: '1',
times: 5,
seconds: 60
},
status: '1',
remark: undefined,
executeConfig: {},
reqParams: [],
resParams: []
},
// 表单校验
rules1: {
apiName: [
{ required: true, message: 'API名称不能为空', trigger: 'blur' }
],
apiVersion: [
{ required: true, message: 'API版本不能为空', trigger: 'blur' }
],
apiUrl: [
{ required: true, message: 'API路径不能为空', trigger: 'blur' }
],
reqMethod: [
{ required: true, message: '请求方式不能为空', trigger: 'change' }
],
resType: [
{ required: true, message: '返回格式不能为空', trigger: 'change' }
]
},
form2: {
configType: undefined,
sourceId: undefined,
tableId: undefined,
tableName: undefined,
fieldParams: [],
sqlText: undefined
},
rules2: {
configType: [
{ required: true, message: '配置方式不能为空', trigger: 'change' }
],
sourceId: [
{ required: true, message: '数据源不能为空', trigger: 'change' }
]
},
form3: {
reqParams: [],
resParams: []
},
// 请求方式数据字典
reqMethodOptions: [],
// 返回格式数据字典
resTypeOptions: [],
// 是否数据字典
whetherOptions: [],
// 状态数据字典
statusOptions: [],
// 数据源数据字典
sourceOptions: [],
// 数据库表数据字典
tableOptions: [],
// 配置方式数据字典
configTypeOptions: [],
// 操作符数据字典
whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
}
},
created() {
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.reqMethodOptions = response.data
}
})
this.getDicts('data_res_type').then(response => {
if (response.success) {
this.resTypeOptions = response.data
}
})
this.getDicts('sys_yes_no').then(response => {
if (response.success) {
this.whetherOptions = response.data
}
})
this.getDicts('data_api_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDataSourceList()
this.getDicts('data_config_type').then(response => {
if (response.success) {
this.configTypeOptions = response.data
}
})
this.getDicts('data_where_type').then(response => {
if (response.success) {
this.whereTypeOptions = response.data
}
})
this.getDicts('data_param_type').then(response => {
if (response.success) {
this.paramTypeOptions = response.data
}
})
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataSourceList() {
listDataSource().then(response => {
if (response.success) {
this.sourceOptions = response.data
}
})
},
/** 步骤条下一步 */
handleNextStep() {
if (this.active === 1) {
this.$refs['form1'].validate(valid => {
if (valid) {
this.active++
}
})
} else if (this.active === 2) {
this.$refs['form2'].validate(valid => {
if (valid) {
this.active++
}
})
}
},
/** 步骤条上一步 */
handleLastStep() {
this.active--
},
changeTextarea(val) {
this.form2.sqlText = val
},
configTypeSelectChanged(val) {
if (this.form2.configType === '1' && this.form2.sourceId && this.tableOptions.length <= 0) {
const data = {}
data.sourceId = this.form2.sourceId
listDataTable(data).then(response => {
if (response.success) {
this.tableOptions = response.data
this.form2.fieldParams = []
}
})
}
},
sourceSelectChanged(val) {
if (this.form2.configType && this.form2.configType === '1') {
const data = {}
data.sourceId = val
listDataTable(data).then(response => {
if (response.success) {
this.tableOptions = response.data
this.form2.fieldParams = []
}
})
}
},
tableSelectChanged(item) {
const data = {}
data.sourceId = item.sourceId
data.tableId = item.id
this.form2.tableId = item.id
this.form2.tableName = item.tableName
listDataColumn(data).then(response => {
if (response.success) {
this.form2.fieldParams = response.data
this.form3.reqParams = []
this.form3.resParams = []
}
})
},
sqlParse() {
if (!this.form2.sourceId) {
this.$message.error('数据源不能为空')
return
}
if (!this.form2.sqlText) {
this.$message.error('解析SQL不能为空')
return
}
const data = {}
data.sourceId = this.form2.sourceId
data.sqlText = this.form2.sqlText
sqlParse(data).then(response => {
if (response.success) {
const { data } = response
this.form3.reqParams = data.reqParams
this.form3.resParams = data.resParams
this.$message.success('解析成功,请进行下一步')
}
})
},
reqCheckChange(row, checked) {
if (checked === '1') {
const json = {}
json.paramName = row.columnName
json.paramComment = row.columnComment || undefined
json.nullable = '0'
this.form3.reqParams.push(json)
} else {
this.form3.reqParams.splice(this.form3.reqParams.findIndex(item => item.paramName === row.columnName), 1)
}
},
resCheckChange(row, checked) {
if (checked === '1') {
const json = {}
json.fieldName = row.columnName
json.fieldComment = row.columnComment || undefined
json.dataType = row.dataType || undefined
this.form3.resParams.push(json)
} else {
this.form3.resParams.splice(this.form3.resParams.findIndex(item => item.fieldName === row.columnName), 1)
}
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form3'].validate(valid => {
if (valid) {
if (this.form3.reqParams.length <= 0) {
this.$message.error('请求参数不能为空')
return
}
if (this.form3.resParams.length <= 0) {
this.$message.error('返回字段不能为空')
return
}
this.form1.sourceId = this.form2.sourceId
this.form1.executeConfig = this.form2
this.form1.reqParams = this.form3.reqParams
this.form1.resParams = this.form3.resParams
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
addDataApi(this.form1).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,464 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:api:word']" size="mini" icon="el-icon-coin" round @click="handleWord">接口文档</el-button>
<el-button v-hasPerm="['market:api:example']" size="mini" icon="el-icon-s-data" round @click="handleExample">接口示例</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-steps :active="active" finish-status="success" align-center>
<el-step title="属性配置" />
<el-step title="执行配置" />
<el-step title="参数配置" />
</el-steps>
<el-form v-if="active == 1" ref="form1" :model="form1" label-width="80px" disabled>
<el-form-item label="API名称" prop="apiName">
<el-input v-model="form1.apiName" placeholder="请输入API名称" />
</el-form-item>
<el-form-item label="API版本" prop="apiVersion">
<el-input v-model="form1.apiVersion" placeholder="请输入API版本" />
</el-form-item>
<el-form-item label="API路径" prop="apiUrl">
<el-input v-model="form1.apiUrl" placeholder="请输入API路径" />
</el-form-item>
<el-form-item label="请求方式" prop="reqMethod">
<el-select v-model="form1.reqMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in reqMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="返回格式" prop="resType">
<el-select v-model="form1.resType" placeholder="请选择返回格式">
<el-option
v-for="dict in resTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="IP黑名单" prop="deny">
<el-input v-model="form1.deny" type="textarea" placeholder="请输入IP黑名单多个用英文,隔开" />
</el-form-item>
<el-form-item label="是否限流" prop="rateLimit">
<el-radio-group v-model="form1.rateLimit.enable">
<el-radio
v-for="dict in whetherOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form1.rateLimit.enable === '1'" label="限流配置">
<el-input-number v-model="form1.rateLimit.seconds" controls-position="right" :min="1" />秒内限制请求
<el-input-number v-model="form1.rateLimit.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form1.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form v-if="active == 2" ref="form2" :model="form2" label-width="80px" disabled>
<el-form-item label="配置方式" prop="configType">
<el-select v-model="form2.configType" placeholder="请选择配置方式">
<el-option
v-for="dict in configTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="数据源" prop="sourceId">
<el-select v-model="form2.sourceId" placeholder="请选择数据源">
<el-option
v-for="source in sourceOptions"
:key="source.id"
:label="source.sourceName"
:value="source.id"
:disabled="source.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="数据库表" prop="tableName">
<el-select v-model="form2.table" value-key="id" placeholder="请选择数据库表">
<el-option
v-for="item in tableOptions"
:key="item.id"
:label="item.tableComment ? item.tableComment : item.tableName"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="字段列表">
<el-table
:data="form2.fieldParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column prop="columnPosition" label="序号" width="55" align="center" />
<el-table-column prop="columnName" label="列名" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip />
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip />
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip />
<el-table-column prop="columnKey" label="是否主键" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnKey === '1'">Y</span>
<span v-if="scope.row.columnKey === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="columnNullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnNullable === '1'">Y</span>
<span v-if="scope.row.columnNullable === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip />
<el-table-column prop="columnComment" label="列注释" align="center" show-overflow-tooltip />
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable" true-label="1" false-label="0" />
</template>
</el-table-column>
<el-table-column prop="resable" label="是否作为返回参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.resable" true-label="1" false-label="0" />
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-row v-if="form2.configType === '2'">
<el-col :span="24">
<sql-editor
ref="sqleditor"
:value="form2.sqlText"
:read-only="true"
style="height: 300px;margin: 10px 10px;"
/>
</el-col>
</el-row>
</el-form>
<el-form v-if="active == 3" ref="form3" :model="form3" label-width="80px" disabled>
<el-divider content-position="left">请求参数</el-divider>
<el-table
:data="form3.reqParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip />
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" />
</template>
</el-table-column>
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型">
<el-option
v-for="dict in paramTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.whereType" placeholder="请选择操作符">
<el-option
v-for="dict in whereTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip />
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip />
</el-table>
<el-divider content-position="left">返回字段</el-divider>
<el-table
:data="form3.resParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip />
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip />
</el-table>
</el-form>
<el-button v-if="active < 3" style="margin-top: 12px;" @click="handleNextStep">下一步</el-button>
<el-button v-if="active > 1" style="margin-top: 12px;" @click="handleLastStep">上一步</el-button>
</div>
</el-card>
</template>
<script>
import { getDataApi, word } from '@/api/market/dataapi'
import { listDataSource } from '@/api/metadata/datasource'
import { listDataTable } from '@/api/metadata/datatable'
import SqlEditor from '@/components/SqlEditor'
export default {
name: 'DataApiDetail',
components: {
SqlEditor
},
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
},
active: 1,
// 表单参数
form1: {
id: undefined,
apiName: undefined,
apiVersion: undefined,
apiUrl: undefined,
reqMethod: undefined,
resType: undefined,
deny: undefined,
rateLimit: {
enable: '1',
times: 5,
seconds: 60
},
times: 5,
seconds: 60,
status: '1',
remark: undefined,
executeConfig: {},
reqParams: [],
resParams: []
},
// 表单校验
rules1: {
apiName: [
{ required: true, message: 'API名称不能为空', trigger: 'blur' }
],
apiVersion: [
{ required: true, message: 'API版本不能为空', trigger: 'blur' }
],
apiUrl: [
{ required: true, message: 'API路径不能为空', trigger: 'blur' }
],
reqMethod: [
{ required: true, message: '请求方式不能为空', trigger: 'blur' }
],
resType: [
{ required: true, message: '返回格式不能为空', trigger: 'blur' }
]
},
form2: {
configType: undefined,
sourceId: undefined,
tableId: undefined,
tableName: undefined,
fieldParams: [],
sqlText: undefined
},
rules2: {
configType: [
{ required: true, message: '配置方式不能为空', trigger: 'blur' }
],
sourceId: [
{ required: true, message: '数据源不能为空', trigger: 'blur' }
]
},
form3: {
reqParams: [],
resParams: []
},
// 请求方式数据字典
reqMethodOptions: [],
// 返回格式数据字典
resTypeOptions: [],
// 是否数据字典
whetherOptions: [],
// 状态数据字典
statusOptions: [],
// 数据源数据字典
sourceOptions: [],
// 数据库表数据字典
tableOptions: [],
// 配置方式数据字典
configTypeOptions: [],
// 操作符数据字典
whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.reqMethodOptions = response.data
}
})
this.getDicts('data_res_type').then(response => {
if (response.success) {
this.resTypeOptions = response.data
}
})
this.getDicts('sys_yes_no').then(response => {
if (response.success) {
this.whetherOptions = response.data
}
})
this.getDicts('data_api_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDataSourceList()
this.getDicts('data_config_type').then(response => {
if (response.success) {
this.configTypeOptions = response.data
}
})
this.getDicts('data_where_type').then(response => {
if (response.success) {
this.whereTypeOptions = response.data
}
})
this.getDicts('data_param_type').then(response => {
if (response.success) {
this.paramTypeOptions = response.data
}
})
},
mounted() {
this.getDataApi(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataSourceList() {
listDataSource().then(response => {
if (response.success) {
this.sourceOptions = response.data
}
})
},
/** 步骤条下一步 */
handleNextStep() {
this.active++
},
/** 步骤条上一步 */
handleLastStep() {
this.active--
},
/** 获取详情 */
async getDataApi(id) {
this.form1 = await getDataApi(id).then(response => {
if (response.success) {
return response.data
}
}) || {}
this.form2 = this.form1.executeConfig
this.form2.table = { id: this.form2.tableId }
this.form3.reqParams = this.form1.reqParams
this.form3.resParams = this.form1.resParams
if (this.form2.configType === '1') {
this.tableOptions = await listDataTable({ sourceId: this.form2.sourceId }).then(response => {
if (response.success) {
return response.data
}
}) || []
}
},
handleExample() {
this.showOptions.data.id = this.data.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = false
this.showOptions.showDetail = false
this.showOptions.showExample = true
this.$emit('showCard', this.showOptions)
},
/** 接口文档 */
handleWord() {
word(this.data.id).then(response => {
const blob = new Blob([response])
const fileName = '接口文档.docx'
if ('download' in document.createElement('a')) {
// 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
// 释放URL 对象
document.body.removeChild(elink)
} else {
// IE10+下载
navigator.msSaveBlob(blob, fileName)
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,608 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:api:edit']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div>
<el-steps :active="active" finish-status="success" align-center>
<el-step title="属性配置" />
<el-step title="执行配置" />
<el-step title="参数配置" />
</el-steps>
<el-form v-if="active == 1" ref="form1" :model="form1" :rules="rules1" label-width="80px">
<el-form-item label="API名称" prop="apiName">
<el-input v-model="form1.apiName" placeholder="请输入API名称" />
</el-form-item>
<el-form-item label="API版本" prop="apiVersion">
<el-input v-model="form1.apiVersion" placeholder="请输入API版本如v1.0.0" />
</el-form-item>
<el-form-item label="API路径" prop="apiUrl">
<el-input v-model="form1.apiUrl" placeholder="请输入API路径" />
</el-form-item>
<el-form-item label="请求方式" prop="reqMethod">
<el-select v-model="form1.reqMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in reqMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="返回格式" prop="resType">
<el-select v-model="form1.resType" placeholder="请选择返回格式">
<el-option
v-for="dict in resTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="IP黑名单" prop="deny">
<el-input v-model="form1.deny" type="textarea" placeholder="请输入IP黑名单多个用英文,隔开" />
</el-form-item>
<el-form-item label="是否限流" prop="rateLimit">
<el-radio-group v-model="form1.rateLimit.enable">
<el-radio
v-for="dict in whetherOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form1.rateLimit.enable === '1'" label="限流配置">
<el-input-number v-model="form1.rateLimit.seconds" controls-position="right" :min="1" />秒内限制请求
<el-input-number v-model="form1.rateLimit.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form1.status" disabled>
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form v-if="active == 2" ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-form-item label="配置方式" prop="configType">
<el-select v-model="form2.configType" placeholder="请选择配置方式" @change="configTypeSelectChanged">
<el-option
v-for="dict in configTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
<el-form-item label="数据源" prop="sourceId">
<el-select v-model="form2.sourceId" placeholder="请选择数据源" @change="sourceSelectChanged">
<el-option
v-for="source in sourceOptions"
:key="source.id"
:label="source.sourceName"
:value="source.id"
:disabled="source.status === '0'"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="数据库表" prop="tableName">
<el-select v-model="form2.table" value-key="id" placeholder="请选择数据库表" @change="tableSelectChanged">
<el-option
v-for="item in tableOptions"
:key="item.id"
:label="item.tableComment ? item.tableComment : item.tableName"
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item v-if="form2.configType === '1'" label="字段列表">
<el-table
:data="form2.fieldParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column prop="columnPosition" label="序号" width="55" align="center" />
<el-table-column prop="columnName" label="列名" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip />
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip />
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip />
<el-table-column prop="columnKey" label="是否主键" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnKey === '1'">Y</span>
<span v-if="scope.row.columnKey === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="columnNullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnNullable === '1'">Y</span>
<span v-if="scope.row.columnNullable === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip />
<el-table-column prop="columnComment" label="列注释" align="center" show-overflow-tooltip />
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable" true-label="1" false-label="0" @change="checked=>reqCheckChange(scope.row, checked)" />
</template>
</el-table-column>
<el-table-column prop="resable" label="是否作为返回参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.resable" true-label="1" false-label="0" @change="checked=>resCheckChange(scope.row, checked)" />
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-row v-if="form2.configType === '2'">
<el-col :span="24">
<sql-editor
ref="sqleditor"
:value="form2.sqlText"
style="height: 300px;margin: 10px 10px;"
@changeTextarea="changeTextarea($event)"
/>
</el-col>
</el-row>
<el-form-item v-if="form2.configType === '2'">
<el-button size="mini" type="primary" @click="sqlParse">SQL解析</el-button>
</el-form-item>
</el-form>
<el-form v-if="active == 3" ref="form3" :model="form3" label-width="80px">
<el-divider content-position="left">请求参数</el-divider>
<el-table
:data="form3.reqParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip />
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" />
</template>
</el-table-column>
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.paramComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型">
<el-option
v-for="dict in paramTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.whereType" placeholder="请选择操作符">
<el-option
v-for="dict in whereTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.defaultValue" placeholder="请输入默认值" />
</template>
</el-table-column>
</el-table>
<el-divider content-position="left">返回字段</el-divider>
<el-table
:data="form3.resParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip />
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.fieldComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.dataType" placeholder="请输入数据类型" />
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
</el-table>
</el-form>
<el-button v-if="active < 3" style="margin-top: 12px;" @click="handleNextStep">下一步</el-button>
<el-button v-if="active > 1" style="margin-top: 12px;" @click="handleLastStep">上一步</el-button>
</div>
</el-card>
</template>
<script>
import { getDataApi, updateDataApi, sqlParse } from '@/api/market/dataapi'
import { listDataSource } from '@/api/metadata/datasource'
import { listDataTable } from '@/api/metadata/datatable'
import { listDataColumn } from '@/api/metadata/datacolumn'
import SqlEditor from '@/components/SqlEditor'
export default {
name: 'DataApiEdit',
components: {
SqlEditor
},
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API编辑',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
active: 1,
// 表单参数
form1: {
id: undefined,
apiName: undefined,
apiVersion: undefined,
apiUrl: undefined,
reqMethod: undefined,
resType: undefined,
deny: undefined,
rateLimit: {
enable: '1',
times: 5,
seconds: 60
},
times: 5,
seconds: 60,
status: '1',
remark: undefined,
executeConfig: {},
reqParams: [],
resParams: []
},
// 表单校验
rules1: {
apiName: [
{ required: true, message: 'API名称不能为空', trigger: 'blur' }
],
apiVersion: [
{ required: true, message: 'API版本不能为空', trigger: 'blur' }
],
apiUrl: [
{ required: true, message: 'API路径不能为空', trigger: 'blur' }
],
reqMethod: [
{ required: true, message: '请求方式不能为空', trigger: 'change' }
],
resType: [
{ required: true, message: '返回格式不能为空', trigger: 'change' }
]
},
form2: {
configType: undefined,
sourceId: undefined,
tableId: undefined,
tableName: undefined,
fieldParams: [],
sqlText: undefined
},
rules2: {
configType: [
{ required: true, message: '配置方式不能为空', trigger: 'change' }
],
sourceId: [
{ required: true, message: '数据源不能为空', trigger: 'change' }
]
},
form3: {
reqParams: [],
resParams: []
},
// 请求方式数据字典
reqMethodOptions: [],
// 返回格式数据字典
resTypeOptions: [],
// 是否数据字典
whetherOptions: [],
// 状态数据字典
statusOptions: [],
// 数据源数据字典
sourceOptions: [],
// 数据库表数据字典
tableOptions: [],
// 配置方式数据字典
configTypeOptions: [],
// 操作符数据字典
whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.reqMethodOptions = response.data
}
})
this.getDicts('data_res_type').then(response => {
if (response.success) {
this.resTypeOptions = response.data
}
})
this.getDicts('sys_yes_no').then(response => {
if (response.success) {
this.whetherOptions = response.data
}
})
this.getDicts('data_api_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDataSourceList()
this.getDicts('data_config_type').then(response => {
if (response.success) {
this.configTypeOptions = response.data
}
})
this.getDicts('data_where_type').then(response => {
if (response.success) {
this.whereTypeOptions = response.data
}
})
this.getDicts('data_param_type').then(response => {
if (response.success) {
this.paramTypeOptions = response.data
}
})
},
mounted() {
this.getDataApi(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataSourceList() {
listDataSource().then(response => {
if (response.success) {
this.sourceOptions = response.data
}
})
},
/** 步骤条下一步 */
handleNextStep() {
if (this.active === 1) {
this.$refs['form1'].validate(valid => {
if (valid) {
// 计算参数
this.active++
}
})
} else if (this.active === 2) {
this.$refs['form2'].validate(valid => {
if (valid) {
this.active++
}
})
}
},
/** 步骤条上一步 */
handleLastStep() {
this.active--
},
changeTextarea(val) {
this.form2.sqlText = val
},
configTypeSelectChanged(val) {
if (this.form2.configType === '1' && this.form2.sourceId && this.tableOptions.length <= 0) {
const data = {}
data.sourceId = this.form2.sourceId
listDataTable(data).then(response => {
if (response.success) {
this.tableOptions = response.data
this.form2.fieldParams = []
}
})
}
},
sourceSelectChanged(val) {
if (this.form2.configType && this.form2.configType === '1') {
const data = {}
data.sourceId = val
listDataTable(data).then(response => {
if (response.success) {
this.tableOptions = response.data
this.form2.fieldParams = []
}
})
}
},
tableSelectChanged(item) {
const data = {}
data.sourceId = item.sourceId
data.tableId = item.id
this.form2.tableId = item.id
this.form2.tableName = item.tableName
listDataColumn(data).then(response => {
if (response.success) {
this.form2.fieldParams = response.data
this.form3.reqParams = []
this.form3.resParams = []
}
})
},
sqlParse() {
if (!this.form2.sourceId) {
this.$message.error('数据源不能为空')
return
}
if (!this.form2.sqlText) {
this.$message.error('解析SQL不能为空')
return
}
const data = {}
data.sourceId = this.form2.sourceId
data.sqlText = this.form2.sqlText
sqlParse(data).then(response => {
if (response.success) {
const { data } = response
this.form3.reqParams = data.reqParams
this.form3.resParams = data.resParams
this.$message.success('解析成功,请进行下一步')
}
})
},
/** 获取详情 */
async getDataApi(id) {
this.form1 = await getDataApi(id).then(response => {
if (response.success) {
return response.data
}
}) || {}
this.form2 = this.form1.executeConfig
this.form2.table = { id: this.form2.tableId }
this.form3.reqParams = this.form1.reqParams
this.form3.resParams = this.form1.resParams
if (this.form2.configType === '1') {
this.tableOptions = await listDataTable({ sourceId: this.form2.sourceId }).then(response => {
if (response.success) {
return response.data
}
}) || []
// this.tableOptions = await getDbTables(this.form2.sourceId).then(response => {
// if (response.success) {
// return response.data
// }
// }) || []
}
},
reqCheckChange(row, checked) {
if (checked === '1') {
const json = {}
json.paramName = row.columnName
json.paramComment = row.columnComment || undefined
json.nullable = '0'
this.form3.reqParams.push(json)
} else {
this.form3.reqParams.splice(this.form3.reqParams.findIndex(item => item.paramName === row.columnName), 1)
}
},
resCheckChange(row, checked) {
if (checked === '1') {
const json = {}
json.fieldName = row.columnName
json.fieldComment = row.columnComment || undefined
json.dataType = row.dataType || undefined
this.form3.resParams.push(json)
} else {
this.form3.resParams.splice(this.form3.resParams.findIndex(item => item.fieldName === row.columnName), 1)
}
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form3'].validate(valid => {
if (valid) {
if (this.form3.reqParams.length <= 0) {
this.$message.error('请求参数不能为空')
return
}
if (this.form3.resParams.length <= 0) {
this.$message.error('返回字段不能为空')
return
}
this.form1.sourceId = this.form2.sourceId
this.form1.executeConfig = this.form2
this.form1.reqParams = this.form3.reqParams
this.form1.resParams = this.form3.resParams
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
updateDataApi(this.form1).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,298 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:api:example']" size="mini" icon="el-icon-s-data" round @click="handleCall">接口调用</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form1" :model="form" label-width="80px" :disabled="true">
<el-row>
<el-col :span="8">
<el-form-item label="API名称">
<el-input v-model="form.apiName" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="API版本">
<el-input v-model="form.apiVersion" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="请求类型">
<el-input v-model="form.reqMethod" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="返回格式">
<el-input v-model="form.resType" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="16">
<el-form-item label="调用路径">
<el-input v-model="'/services/' + form.apiVersion + form.apiUrl" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">请求数据</el-divider>
<el-row>
<el-col :span="24">
<el-tabs v-model="activeTabName" type="border-card">
<el-tab-pane label="请求头" name="table0">
<el-table
:data="apiHeaderList"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="KEY" label="键" align="center" show-overflow-tooltip />
<el-table-column prop="VALUE" label="值" align="center" show-overflow-tooltip />
<el-table-column prop="DESCRIPTION" label="描述" align="center" show-overflow-tooltip />
</el-table>
</el-tab-pane>
<el-tab-pane label="请求参数" name="table1">
<el-table
:data="form.reqParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip />
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" disabled />
</template>
</el-table-column>
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型" disabled>
<el-option
v-for="dict in paramTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.whereType" placeholder="请选择操作符" disabled>
<el-option
v-for="dict in whereTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="paramValue" label="参数值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.paramValue" placeholder="请输入参数值" />
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<el-divider content-position="left">返回数据</el-divider>
<el-row>
<el-col :span="24">
<div v-if="apiExecuting">
<el-table
:data="callData.dataList"
stripe
border
:max-height="200"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(column, index) in callData.columnList">
<el-table-column
:key="index"
:prop="column"
:label="column"
align="center"
show-overflow-tooltip
/>
</template>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="callData.pageNum"
:page-size.sync="callData.pageSize"
:total="callData.dataTotal"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
<div v-else>暂无数据</div>
</el-col>
</el-row>
</div>
</el-card>
</template>
<script>
import { getDataApiDetail } from '@/api/market/dataapi'
import { getApiCall, postApiCall } from '@/api/market/apimapping'
export default {
name: 'DataApiExample',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '数据API调用',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
},
activeTabName: 'table0',
form: {},
apiHeader: {},
apiHeaderList: [],
// 操作符数据字典
whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: [],
apiExecuting: false,
callData: {
dataList: [],
columnList: [],
pageNum: 1,
pageSize: 20,
dataTotal: 0
}
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('data_where_type').then(response => {
if (response.success) {
this.whereTypeOptions = response.data
}
})
this.getDicts('data_param_type').then(response => {
if (response.success) {
this.paramTypeOptions = response.data
}
})
},
mounted() {
this.getDataApi(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getDataApi: function(id) {
getDataApiDetail(id).then(response => {
if (response.success) {
const { data } = response
this.form = data.data
this.apiHeader = data.header
this.apiHeaderList.push({ 'KEY': 'api_key', 'VALUE': data.header.apiKey, 'DESCRIPTION': '' })
this.apiHeaderList.push({ 'KEY': 'secret_key', 'VALUE': data.header.secretKey, 'DESCRIPTION': '' })
}
})
},
handleSizeChange(val) {
this.callData.pageNum = 1
this.callData.pageSize = val
this.handleCall()
},
handleCurrentChange(val) {
this.callData.pageNum = val
this.handleCall()
},
handleCall() {
const url = 'services/' + this.form.apiVersion + this.form.apiUrl
const header = { api_key: this.apiHeader.apiKey, secret_key: this.apiHeader.secretKey }
const data = {}
data.pageNum = this.callData.pageNum
data.pageSize = this.callData.pageSize
this.form.reqParams.forEach(param => {
this.$set(data, param.paramName, param.paramValue)
})
if (this.form.reqMethod === 'GET') {
getApiCall(url, header, data).then(response => {
if (response.success) {
const { data } = response
const dataList = data.data || []
let columnList = []
if (dataList.length > 0) {
columnList = Object.keys(dataList[0])
}
this.callData.dataList = dataList
this.callData.columnList = columnList
this.callData.dataTotal = data.total
this.apiExecuting = true
}
})
} else if (this.form.reqMethod === 'POST') {
postApiCall(url, header, data).then(response => {
if (response.success) {
const { data } = response
const dataList = data.data || []
let columnList = []
if (dataList.length > 0) {
columnList = Object.keys(dataList[0])
}
this.callData.dataList = dataList
this.callData.columnList = columnList
this.callData.dataTotal = data.total
this.apiExecuting = true
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,384 @@
<template>
<el-card class="box-card" shadow="always">
<el-form ref="queryForm" :model="queryParams" :inline="true">
<el-form-item label="API名称" prop="apiName">
<el-input
v-model="queryParams.apiName"
placeholder="请输入API名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
v-hasPerm="['market:api:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="dataApiList"
border
tooltip-effect="dark"
:size="tableSize"
:height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:key="index"
:prop="item.prop"
:label="item.label"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-popover
placement="left"
trigger="click"
>
<el-button
v-hasPerm="['market:api:edit']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>修改</el-button>
<el-button
v-hasPerm="['market:api:detail']"
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPerm="['market:api:remove']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button
v-hasPerm="['market:api:copy']"
size="mini"
type="text"
icon="el-icon-copy-document"
@click="handleCopy(scope.row)"
>拷贝</el-button>
<el-button
v-if="scope.row.status !== '2'"
v-hasPerm="['market:api:release']"
size="mini"
type="text"
icon="el-icon-upload2"
@click="handleRelease(scope.row)"
>发布</el-button>
<el-button
v-if="scope.row.status === '2'"
v-hasPerm="['market:api:cancel']"
size="mini"
type="text"
icon="el-icon-download"
@click="handleCancel(scope.row)"
>注销</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script>
import { pageDataApi, delDataApi, copyDataApi, releaseDataApi, cancelDataApi } from '@/api/market/dataapi'
export default {
name: 'DataApiList',
data() {
return {
tableHeight: document.body.offsetHeight - 310 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
},
// 遮罩层
loading: true,
// 表格头
tableColumns: [
{ prop: 'apiName', label: 'API名称', show: true },
{ prop: 'apiVersion', label: 'API版本', show: true },
{ prop: 'apiUrl', label: 'API路径', show: true },
{ prop: 'reqMethod', label: '请求类型', show: true },
{ prop: 'resType', label: '返回格式', show: true },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'createTime', label: '创建时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 状态数据字典
statusOptions: [],
// 数据集表格数据
dataApiList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
apiName: ''
}
}
},
created() {
this.getDicts('data_api_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getList()
},
mounted() {
this.initCols()
},
methods: {
/** 查询数据Api列表 */
getList() {
this.loading = true
pageDataApi(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.dataApiList = data.data
this.total = data.total
}
})
},
initCols() {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange(val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand(command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
apiName: ''
}
this.handleQuery()
},
/** 刷新列表 */
handleRefresh() {
this.getList()
},
/** 新增按钮操作 */
handleAdd() {
this.showOptions.data = {}
this.showOptions.showList = false
this.showOptions.showAdd = true
this.showOptions.showEdit = false
this.showOptions.showDetail = false
this.showOptions.showExample = false
this.$emit('showCard', this.showOptions)
},
/** 修改按钮操作 */
handleEdit(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = true
this.showOptions.showDetail = false
this.showOptions.showExample = false
this.$emit('showCard', this.showOptions)
},
/** 详情按钮操作 */
handleDetail(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = false
this.showOptions.showDetail = true
this.showOptions.showExample = false
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delDataApi(row.id).then(response => {
if (response.success) {
this.$message.success('删除成功')
this.getList()
}
})
}).catch(() => {
})
},
/** 接口拷贝 */
handleCopy(row) {
this.$confirm('确认拷贝当前接口, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
copyDataApi(row.id).then(response => {
if (response.success) {
this.$message.success('拷贝成功')
this.getList()
}
})
}).catch(() => {
})
},
/** 接口发布 */
handleRelease(row) {
releaseDataApi(row.id).then(response => {
if (response.success) {
this.$message.success('接口发布成功')
this.getList()
}
})
},
/** 接口注销 */
handleCancel(row) {
cancelDataApi(row.id).then(response => {
if (response.success) {
this.$message.success('接口注销成功')
this.getList()
}
})
},
handleSizeChange(val) {
console.log(`每页 ${val}`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
statusFormatter(row, column, cellValue, index) {
const dictLabel = this.selectDictLabel(this.statusOptions, cellValue)
if (cellValue === '1') {
return <el-tag>{dictLabel}</el-tag>
} else if (cellValue === '2') {
return <el-tag type='success'>{dictLabel}</el-tag>
} else if (cellValue === '3') {
return <el-tag type='warning'>{dictLabel}</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
.el-card ::v-deep .el-card__body {
height: calc(100vh - 170px);
}
</style>

View File

@@ -0,0 +1,53 @@
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<data-api-list v-if="options.showList" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<data-api-add v-if="options.showAdd" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<data-api-edit v-if="options.showEdit" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<data-api-detail v-if="options.showDetail" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<data-api-example v-if="options.showExample" :data="options.data" @showCard="showCard" />
</transition>
</div>
</template>
<script>
import DataApiList from './DataApiList'
import DataApiAdd from './DataApiAdd'
import DataApiEdit from './DataApiEdit'
import DataApiDetail from './DataApiDetail'
import DataApiExample from './DataApiExample'
export default {
name: 'DataApi',
components: { DataApiList, DataApiAdd, DataApiEdit, DataApiDetail, DataApiExample },
data() {
return {
options: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false,
showExample: false
}
}
},
methods: {
showCard(data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,205 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:service:add']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="服务名称" prop="serviceName">
<el-input v-model="form.serviceName" placeholder="请输入服务名称" />
</el-form-item>
<el-form-item label="服务类型" prop="serviceType">
<el-select v-model="form.serviceType">
<el-option
v-for="item in serviceTypeOptions"
:key="item.id"
:label="item.itemValue"
:value="item.itemText"
/>
</el-select>
</el-form-item>
<template v-if="form.serviceType === '1'">
<el-form-item label="服务请求地址" prop="httpService.url">
<el-input v-model="form.httpService.url" placeholder="请输入服务请求地址" />
</el-form-item>
<el-form-item label="服务请求头">
<el-input v-model="form.httpService.header" placeholder="请输入服务请求头,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求参数">
<el-input v-model="form.httpService.param" placeholder="请输入服务请求参数,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求方式" prop="httpService.httpMethod">
<el-select v-model="form.httpService.httpMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in httpMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
</template>
<template v-if="form.serviceType === '2'">
<el-form-item label="服务wsdl地址" prop="webService.wsdl">
<el-input v-model="form.webService.wsdl" placeholder="请输入服务wsdl地址" />
</el-form-item>
<el-form-item label="服务命名空间" prop="webService.targetNamespace">
<el-input v-model="form.webService.targetNamespace" placeholder="请输入服务命名空间" />
</el-form-item>
<el-form-item label="服务方法" prop="webService.method">
<el-input v-model="form.webService.method" placeholder="请输入服务方法" />
</el-form-item>
<el-form-item label="服务请求报文" prop="webService.soap">
<el-input v-model="form.webService.soap" type="textarea" placeholder="请输入服务请求报文" />
</el-form-item>
</template>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { addDataService } from '@/api/market/dataservice'
export default {
name: 'DataServiceAdd',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '服务集成新增',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {
serviceType: '1',
status: '1',
httpService: {},
webService: {}
},
// 表单校验
rules: {
serviceName: [
{ required: true, message: '服务名称不能为空', trigger: 'blur' }
],
serviceType: [
{ required: true, message: '服务类型不能为空', trigger: 'change' }
],
'httpService.url': [
{ required: true, message: '请求地址不能为空', trigger: 'blur' }
],
'httpService.httpMethod': [
{ required: true, message: '服务请求方式不能为空', trigger: 'blur' }
],
'webService.wsdl': [
{ required: true, message: '服务wsdl地址不能为空', trigger: 'blur' }
],
'webService.targetNamespace': [
{ required: true, message: '服务命名空间不能为空', trigger: 'blur' }
],
'webService.method': [
{ required: true, message: '服务方法不能为空', trigger: 'blur' }
],
'webService.soap': [
{ required: true, message: '服务请求报文不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: [],
serviceTypeOptions: [],
httpMethodOptions: []
}
},
created() {
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_service_type').then(response => {
if (response.success) {
this.serviceTypeOptions = response.data
}
})
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.httpMethodOptions = response.data
}
})
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
addDataService(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,182 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-row>
<el-col :span="24">
<el-tabs type="border-card">
<el-tab-pane label="请求头">
<el-table
:data="serviceHeaderList"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="KEY" label="键" align="center" show-overflow-tooltip />
<el-table-column prop="VALUE" label="值" align="center" show-overflow-tooltip />
<el-table-column prop="DESCRIPTION" label="描述" align="center" show-overflow-tooltip />
</el-table>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<el-divider content-position="left">服务信息</el-divider>
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="服务名称">
<el-input v-model="form.serviceName" placeholder="请输入服务名称" />
</el-form-item>
<el-form-item label="服务编号">
<el-input v-model="form.serviceNo" />
</el-form-item>
<el-form-item label="服务类型">
<el-select v-model="form.serviceType">
<el-option
v-for="item in serviceTypeOptions"
:key="item.id"
:label="item.itemValue"
:value="item.itemText"
/>
</el-select>
</el-form-item>
<template v-if="form.serviceType === '1'">
<el-form-item label="服务请求地址">
<el-input v-model="form.httpService.url" placeholder="请输入服务请求地址" />
</el-form-item>
<el-form-item label="服务请求头">
<el-input v-model="form.httpService.header" placeholder="请输入服务请求头,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求参数">
<el-input v-model="form.httpService.param" placeholder="请输入服务请求参数,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求方式">
<el-select v-model="form.httpService.httpMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in httpMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
</template>
<template v-if="form.serviceType === '2'">
<el-form-item label="服务wsdl地址">
<el-input v-model="form.webService.wsdl" placeholder="请输入服务wsdl地址" />
</el-form-item>
<el-form-item label="服务命名空间">
<el-input v-model="form.webService.targetNamespace" placeholder="请输入服务命名空间" />
</el-form-item>
<el-form-item label="服务方法">
<el-input v-model="form.webService.method" placeholder="请输入服务方法" />
</el-form-item>
<el-form-item label="服务请求报文">
<el-input v-model="form.webService.soap" type="textarea" placeholder="请输入服务请求报文" />
</el-form-item>
</template>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { getDataServiceDetail } from '@/api/market/dataservice'
export default {
name: 'DataServiceDetail',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '服务集成详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 表单参数
form: {},
// 状态数据字典
statusOptions: [],
serviceTypeOptions: [],
httpMethodOptions: [],
serviceHeaderList: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_service_type').then(response => {
if (response.success) {
this.serviceTypeOptions = response.data
}
})
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.httpMethodOptions = response.data
}
})
},
mounted() {
this.getDataService(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getDataService: function(id) {
getDataServiceDetail(id).then(response => {
if (response.success) {
const { data } = response
this.form = data.data
this.serviceHeaderList.push({ 'KEY': 'service_key', 'VALUE': data.header.serviceKey, 'DESCRIPTION': '' })
this.serviceHeaderList.push({ 'KEY': 'secret_key', 'VALUE': data.header.secretKey, 'DESCRIPTION': '' })
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,215 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button v-hasPerm="['market:service:edit']" size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="服务名称" prop="serviceName">
<el-input v-model="form.serviceName" placeholder="请输入服务名称" />
</el-form-item>
<el-form-item label="服务编号" prop="serviceNo">
<el-input v-model="form.serviceNo" :disabled="true" />
</el-form-item>
<el-form-item label="服务类型" prop="serviceType">
<el-select v-model="form.serviceType">
<el-option
v-for="item in serviceTypeOptions"
:key="item.id"
:label="item.itemValue"
:value="item.itemText"
/>
</el-select>
</el-form-item>
<template v-if="form.serviceType === '1'">
<el-form-item label="服务请求地址" prop="serviceUrl">
<el-input v-model="form.httpService.url" placeholder="请输入服务请求地址" />
</el-form-item>
<el-form-item label="服务请求头" prop="serviceHeader">
<el-input v-model="form.httpService.header" placeholder="请输入服务请求头,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求参数" prop="serviceParam">
<el-input v-model="form.httpService.param" placeholder="请输入服务请求参数,如{key:val}格式" />
</el-form-item>
<el-form-item label="服务请求方式" prop="serviceHttpMethod">
<el-select v-model="form.httpService.httpMethod" placeholder="请选择请求方式">
<el-option
v-for="dict in httpMethodOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
/>
</el-select>
</el-form-item>
</template>
<template v-if="form.serviceType === '2'">
<el-form-item label="服务wsdl地址" prop="serviceWsdl">
<el-input v-model="form.webService.wsdl" placeholder="请输入服务wsdl地址" />
</el-form-item>
<el-form-item label="服务命名空间" prop="serviceTargetNamespace">
<el-input v-model="form.webService.targetNamespace" placeholder="请输入服务命名空间" />
</el-form-item>
<el-form-item label="服务方法" prop="serviceMethod">
<el-input v-model="form.webService.method" placeholder="请输入服务方法" />
</el-form-item>
<el-form-item label="服务请求报文" prop="serviceSoap">
<el-input v-model="form.webService.soap" type="textarea" placeholder="请输入服务请求报文" />
</el-form-item>
</template>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { getDataService, updateDataService } from '@/api/market/dataservice'
export default {
name: 'DataServiceEdit',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '服务集成编辑',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 保存按钮
loadingOptions: {
loading: false,
loadingText: '保存',
isDisabled: false
},
// 表单参数
form: {},
// 表单校验
rules: {
serviceName: [
{ required: true, message: '服务名称不能为空', trigger: 'blur' }
],
serviceType: [
{ required: true, message: '服务类型不能为空', trigger: 'change' }
],
serviceUrl: [
{ required: true, message: '服务请求地址不能为空', trigger: 'blur' }
],
serviceHttpMethod: [
{ required: true, message: '服务请求方式不能为空', trigger: 'blur' }
],
serviceWsdl: [
{ required: true, message: '服务wsdl地址不能为空', trigger: 'blur' }
],
serviceTargetNamespace: [
{ required: true, message: '服务命名空间不能为空', trigger: 'blur' }
],
serviceSoap: [
{ required: true, message: '服务请求报文不能为空', trigger: 'blur' }
],
serviceMethod: [
{ required: true, message: '服务方法不能为空', trigger: 'blur' }
]
},
// 状态数据字典
statusOptions: [],
serviceTypeOptions: [],
httpMethodOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_service_type').then(response => {
if (response.success) {
this.serviceTypeOptions = response.data
}
})
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.httpMethodOptions = response.data
}
})
},
mounted() {
this.getDataService(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getDataService: function(id) {
getDataService(id).then(response => {
if (response.success) {
this.form = response.data
}
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
if (valid) {
this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true
updateDataService(this.form).then(response => {
if (response.success) {
this.$message.success('保存成功')
setTimeout(() => {
// 2秒后跳转列表页
this.$emit('showCard', this.showOptions)
}, 2000)
} else {
this.$message.error('保存失败')
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
}
}).catch(() => {
this.loadingOptions.loading = false
this.loadingOptions.loadingText = '保存'
this.loadingOptions.isDisabled = false
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,329 @@
<template>
<el-card class="box-card" shadow="always">
<el-form ref="queryForm" :model="queryParams" :inline="true">
<el-form-item label="服务名称" prop="serviceName">
<el-input
v-model="queryParams.serviceName"
placeholder="请输入服务名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group>
<el-button
v-hasPerm="['market:service:add']"
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-button-group>
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="dataServiceList"
border
tooltip-effect="dark"
:size="tableSize"
:height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:key="index"
:prop="item.prop"
:label="item.label"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-popover
placement="left"
trigger="click"
>
<el-button
v-hasPerm="['market:service:edit']"
size="mini"
type="text"
icon="el-icon-edit-outline"
@click="handleEdit(scope.row)"
>修改</el-button>
<el-button
v-hasPerm="['market:service:detail']"
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPerm="['market:service:remove']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script>
import { pageDataService, delDataService } from '@/api/market/dataservice'
import { getDicts } from '@/api/system/dict'
export default {
name: 'DataServiceList',
data() {
return {
tableHeight: document.body.offsetHeight - 310 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
},
// 遮罩层
loading: true,
// 表格头
tableColumns: [
{ prop: 'serviceNo', label: '服务编号', show: true },
{ prop: 'serviceName', label: '服务名称', show: true },
{ prop: 'serviceType', label: '服务类型', show: true, formatter: this.serviceTypeFormatter },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'createTime', label: '创建时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 状态数据字典
statusOptions: [],
// 表格数据
dataServiceList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
serviceName: ''
},
serviceTypeOptions: []
}
},
created() {
this.getDicts('sys_common_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getDicts('data_service_type').then(response => {
if (response.success) {
this.serviceTypeOptions = response.data
}
})
this.getList()
},
mounted() {
this.initCols()
},
methods: {
/** 查询数据源列表 */
getList() {
this.loading = true
pageDataService(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.dataServiceList = data.data
this.total = data.total
}
})
},
initCols() {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange(val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand(command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
serviceName: ''
}
this.handleQuery()
},
/** 刷新列表 */
handleRefresh() {
this.getList()
},
/** 新增按钮操作 */
handleAdd() {
this.showOptions.data = {}
this.showOptions.showList = false
this.showOptions.showAdd = true
this.showOptions.showEdit = false
this.showOptions.showDetail = false
this.$emit('showCard', this.showOptions)
},
/** 修改按钮操作 */
handleEdit(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = true
this.showOptions.showDetail = false
this.$emit('showCard', this.showOptions)
},
/** 详情按钮操作 */
handleDetail(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showAdd = false
this.showOptions.showEdit = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delDataService(row.id).then(response => {
if (response.success) {
this.$message.success('删除成功')
this.getList()
}
})
}).catch(() => {
})
},
handleSizeChange(val) {
console.log(`每页 ${val}`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
serviceTypeFormatter(row, column, cellValue, index) {
return this.selectDictLabel(this.serviceTypeOptions, cellValue)
},
statusFormatter(row, column, cellValue, index) {
const dictLabel = this.selectDictLabel(this.statusOptions, cellValue)
if (cellValue === '1') {
return <el-tag type='success'>{dictLabel}</el-tag>
} else {
return <el-tag type='warning'>{dictLabel}</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
.el-card ::v-deep .el-card__body {
height: calc(100vh - 170px);
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<data-service-list v-if="options.showList" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<data-service-add v-if="options.showAdd" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-top">
<data-service-edit v-if="options.showEdit" :data="options.data" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<data-service-detail v-if="options.showDetail" :data="options.data" @showCard="showCard" />
</transition>
</div>
</template>
<script>
import DataServiceList from './DataServiceList'
import DataServiceAdd from './DataServiceAdd'
import DataServiceEdit from './DataServiceEdit'
import DataServiceDetail from './DataServiceDetail'
export default {
name: 'DataSource',
components: { DataServiceList, DataServiceAdd, DataServiceEdit, DataServiceDetail },
data() {
return {
options: {
data: {},
showList: true,
showAdd: false,
showEdit: false,
showDetail: false
}
}
},
methods: {
showCard(data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div class="app-container">
Market
</div>
</template>
<script>
export default {
name: 'Market'
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,109 @@
<template>
<el-card class="box-card" shadow="always">
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div class="body-wrapper">
<el-form ref="form" :model="form" label-width="80px" disabled>
<el-form-item label="服务名称" prop="serviceName">
<el-input v-model="form.serviceName" />
</el-form-item>
<el-form-item label="调用者ip" prop="callerIp">
<el-input v-model="form.callerIp" />
</el-form-item>
<el-form-item label="调用请求头" prop="callerHeader">
<el-input v-model="form.callerHeader" />
</el-form-item>
<el-form-item label="调用请求参数" prop="callerParam">
<el-input v-model="form.callerParam" />
</el-form-item>
<el-form-item label="调用报文" prop="callerSoap">
<el-input v-model="form.callerSoap" />
</el-form-item>
<el-form-item label="调用时间" prop="callerDate">
<el-input v-model="form.callerDate" />
</el-form-item>
<el-form-item label="调用耗时" prop="time">
<el-input v-model="form.time" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="信息记录" prop="msg">
<el-input v-model="form.msg" />
</el-form-item>
</el-form>
</div>
</el-card>
</template>
<script>
import { getDataServiceLog } from '@/api/market/dataservicelog'
export default {
name: 'ServiceLogDetail',
props: {
data: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
title: '服务日志详情',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 表单参数
form: {},
// 状态数据字典
statusOptions: []
}
},
created() {
console.log('id:' + this.data.id)
this.getDicts('sys_normal_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
},
mounted() {
this.getLog(this.data.id)
},
methods: {
showCard() {
this.$emit('showCard', this.showOptions)
},
/** 获取详情 */
getLog: function(id) {
getDataServiceLog(id).then(response => {
if (response.success) {
this.form = response.data
}
})
}
}
}
</script>
<style lang="scss" scoped>
.el-card ::v-deep .el-card__body {
height: calc(100vh - 230px);
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,282 @@
<template>
<el-card class="box-card" shadow="always">
<el-form ref="queryForm" :model="queryParams" :inline="true">
<el-form-item label="服务名称" prop="serviceName">
<el-input
v-model="queryParams.serviceName"
placeholder="请输入服务名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row type="flex" justify="space-between">
<el-col :span="12">
<el-button-group />
</el-col>
<el-col :span="12">
<div class="right-toolbar">
<el-tooltip content="密度" effect="dark" placement="top">
<el-dropdown trigger="click" @command="handleCommand">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="colum-height" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="medium">正常</el-dropdown-item>
<el-dropdown-item command="small">中等</el-dropdown-item>
<el-dropdown-item command="mini">紧凑</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip content="刷新" effect="dark" placement="top">
<el-button circle size="mini" @click="handleRefresh">
<svg-icon class-name="size-icon" icon-class="shuaxin" />
</el-button>
</el-tooltip>
<el-tooltip content="列设置" effect="dark" placement="top">
<el-popover placement="bottom" width="100" trigger="click">
<el-checkbox-group v-model="checkedTableColumns" @change="handleCheckedColsChange">
<el-checkbox
v-for="(item, index) in tableColumns"
:key="index"
:label="item.prop"
>{{ item.label }}</el-checkbox>
</el-checkbox-group>
<span slot="reference">
<el-button circle size="mini">
<svg-icon class-name="size-icon" icon-class="shezhi" />
</el-button>
</span>
</el-popover>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="logList"
border
tooltip-effect="dark"
:size="tableSize"
:height="tableHeight"
style="width: 100%;margin: 15px 0;"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<template v-for="(item, index) in tableColumns">
<el-table-column
v-if="item.show"
:key="index"
:prop="item.prop"
:label="item.label"
:formatter="item.formatter"
align="center"
show-overflow-tooltip
/>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-popover
placement="left"
trigger="click"
>
<el-button
v-hasPerm="['market:service:log:detail']"
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
>详情</el-button>
<el-button
v-hasPerm="['market:service:log:remove']"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="queryParams.pageNum"
:page-size.sync="queryParams.pageSize"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script>
import { pageDataServiceLog, delDataServiceLog } from '@/api/market/dataservicelog'
export default {
name: 'ServiceLogList',
data() {
return {
tableHeight: document.body.offsetHeight - 310 + 'px',
// 展示切换
showOptions: {
data: {},
showList: true,
showDetail: false
},
// 遮罩层
loading: true,
// 表格头
tableColumns: [
{ prop: 'serviceName', label: '服务名称', show: true },
{ prop: 'callerIp', label: '调用者ip', show: true },
{ prop: 'time', label: '调用耗时', show: true },
{
prop: 'status',
label: '状态',
show: true,
formatter: this.statusFormatter
},
{ prop: 'callerDate', label: '调用时间', show: true }
],
// 默认选择中表格头
checkedTableColumns: [],
tableSize: 'medium',
// 日志表格数据
logList: [],
// 总数据条数
total: 0,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 20,
serviceName: ''
},
// 状态数据字典
statusOptions: []
}
},
created() {
this.getDicts('sys_normal_status').then(response => {
if (response.success) {
this.statusOptions = response.data
}
})
this.getList()
},
mounted() {
this.initCols()
},
methods: {
/** 查询日志列表 */
getList() {
this.loading = true
pageDataServiceLog(this.queryParams).then(response => {
this.loading = false
if (response.success) {
const { data } = response
this.logList = data.data
this.total = data.total
}
})
},
initCols() {
this.checkedTableColumns = this.tableColumns.map(col => col.prop)
},
handleCheckedColsChange(val) {
this.tableColumns.forEach(col => {
if (!this.checkedTableColumns.includes(col.prop)) {
col.show = false
} else {
col.show = true
}
})
},
handleCommand(command) {
this.tableSize = command
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 20,
serviceName: ''
}
this.handleQuery()
},
/** 刷新列表 */
handleRefresh() {
this.getList()
},
/** 详情按钮操作 */
handleDetail(row) {
this.showOptions.data.id = row.id
this.showOptions.showList = false
this.showOptions.showDetail = true
this.$emit('showCard', this.showOptions)
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm('选中数据将被永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delDataServiceLog(row.id).then(response => {
if (response.success) {
this.$message.success('删除成功')
this.getList()
}
})
}).catch(() => {
})
},
handleSizeChange(val) {
console.log(`每页 ${val}`)
this.queryParams.pageNum = 1
this.queryParams.pageSize = val
this.getList()
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`)
this.queryParams.pageNum = val
this.getList()
},
statusFormatter(row, column, cellValue, index) {
const dictLabel = this.selectDictLabel(this.statusOptions, cellValue)
if (cellValue === '1') {
return <el-tag type='success'>{dictLabel}</el-tag>
} else {
return <el-tag type='warning'>{dictLabel}</el-tag>
}
}
}
}
</script>
<style lang="scss" scoped>
.right-toolbar {
float: right;
}
.el-card ::v-deep .el-card__body {
height: calc(100vh - 170px);
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div class="app-container">
<transition name="el-zoom-in-center">
<log-list v-if="options.showList" @showCard="showCard" />
</transition>
<transition name="el-zoom-in-bottom">
<log-detail v-if="options.showDetail" :data="options.data" @showCard="showCard" />
</transition>
</div>
</template>
<script>
import LogList from './LogList'
import LogDetail from './LogDetail'
export default {
name: 'ServiceLog',
components: { LogList, LogDetail },
data() {
return {
options: {
data: {},
showList: true,
showDetail: false
}
}
},
methods: {
showCard(data) {
Object.assign(this.options, data)
}
}
}
</script>
<style lang="scss" scoped>
</style>