Commit d13791ea by yuwei

2.0.0项目初始化

parent dc41b1a8
# 数据源配置 # 数据源配置
spring: spring:
mail:
host: smtp.qq.com
username: 312075478@qq.com
password: ohxmhfsefapibjee
protocol: smtp
default-encoding: utf-8
properties.mail.smtp.auth: true
properties.mail.smtp.port: 465
properties.mail.display.sendmail: 312075478@qq.com
properties.mail.display.sendname: 测试
properties.mail.smtp.starttls.enable: true
properties.mail.smtp.starttls.required: true
properties.mail.smtp.ssl.enable: true
from: 测试1
datasource: datasource:
dynamic: dynamic:
type: com.zaxxer.hikari.HikariDataSource type: com.zaxxer.hikari.HikariDataSource
......
...@@ -64,8 +64,8 @@ public class DataApiDto implements Serializable { ...@@ -64,8 +64,8 @@ public class DataApiDto implements Serializable {
private List<ReqParam> reqParams; private List<ReqParam> reqParams;
@ApiModelProperty(value = "返回参数") @ApiModelProperty(value = "返回参数")
@Valid @Valid
@NotEmpty(message = "返回参数不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class}) @NotEmpty(message = "返回字段不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
@Size(min = 1, message="返回参数长度不能少于{min}位") @Size(min = 1, message="返回字段长度不能少于{min}位")
private List<ResParam> resParams; private List<ResParam> resParams;
@ApiModelProperty(value = "状态") @ApiModelProperty(value = "状态")
@NotNull(message = "状态不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class}) @NotNull(message = "状态不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
......
...@@ -87,7 +87,7 @@ public class DataApiEntity extends DataScopeBaseEntity { ...@@ -87,7 +87,7 @@ public class DataApiEntity extends DataScopeBaseEntity {
private List<ReqParam> reqParams; private List<ReqParam> reqParams;
/** /**
* 返回参数 * 返回字段
*/ */
@TableField(value = "res_json", typeHandler = JacksonTypeHandler.class) @TableField(value = "res_json", typeHandler = JacksonTypeHandler.class)
private List<ResParam> resParams; private List<ResParam> resParams;
......
...@@ -173,7 +173,7 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit ...@@ -173,7 +173,7 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit
List<ReqParam> reqParams = variables.stream().map(s -> { List<ReqParam> reqParams = variables.stream().map(s -> {
ReqParam reqParam = new ReqParam(); ReqParam reqParam = new ReqParam();
reqParam.setParamName(s); reqParam.setParamName(s);
reqParam.setNullable(DataConstant.TrueOrFalse.TRUE.getKey()); reqParam.setNullable(DataConstant.TrueOrFalse.FALSE.getKey());
return reqParam; return reqParam;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
sqlParseVo.setReqParams(reqParams); sqlParseVo.setReqParams(reqParams);
......
...@@ -5,44 +5,18 @@ import cn.datax.service.email.service.EmailService; ...@@ -5,44 +5,18 @@ import cn.datax.service.email.service.EmailService;
import cn.datax.service.email.utils.EmailUtil; import cn.datax.service.email.utils.EmailUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
@Slf4j @Slf4j
@Service @Service
public class EmailServiceImpl implements EmailService { public class EmailServiceImpl implements EmailService {
@Value("${spring.mail.from}")
private String fromNick;
@Value("${spring.mail.username}")
private String fromAddress;
@Autowired @Autowired
private JavaMailSender mailSender; private EmailUtil emailUtil;
@Override @Override
public void sendEmail(EmailEntity emailEntity) { public void sendEmail(EmailEntity emailEntity) {
log.info("实体类 {}", emailEntity); log.info("实体类 {}", emailEntity);
InternetAddress from = null;
String alias = null;
try {
alias = MimeUtility.encodeText(fromNick);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
from = new InternetAddress(alias + " <" + fromAddress + ">");
} catch (AddressException e) {
e.printStackTrace();
}
EmailUtil emailUtil = new EmailUtil(from, mailSender);
try { try {
emailUtil.sendEmail(emailEntity); emailUtil.sendEmail(emailEntity);
} catch (Exception e) { } catch (Exception e) {
......
...@@ -2,27 +2,47 @@ package cn.datax.service.email.utils; ...@@ -2,27 +2,47 @@ package cn.datax.service.email.utils;
import cn.datax.service.email.api.entity.EmailEntity; import cn.datax.service.email.api.entity.EmailEntity;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.File; import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.List; import java.util.List;
@Component
public class EmailUtil { public class EmailUtil {
private InternetAddress from; @Value("${spring.mail.from}")
private JavaMailSender mailSender; private String fromNick;
public EmailUtil(InternetAddress from, JavaMailSender mailSender) { @Value("${spring.mail.username}")
this.from = from; private String fromAddress;
this.mailSender = mailSender;
} @Autowired
private JavaMailSender mailSender;
public void sendEmail(EmailEntity mailEntity) throws Exception { public void sendEmail(EmailEntity mailEntity) throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
InternetAddress from = null;
String alias = null;
try {
alias = MimeUtility.encodeText(fromNick);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
from = new InternetAddress(alias + " <" + fromAddress + ">");
} catch (AddressException e) {
e.printStackTrace();
}
helper.setFrom(from); helper.setFrom(from);
helper.setSubject(mailEntity.getSubject()); helper.setSubject(mailEntity.getSubject());
helper.setText(mailEntity.getText(),true); helper.setText(mailEntity.getText(),true);
...@@ -45,5 +65,4 @@ public class EmailUtil { ...@@ -45,5 +65,4 @@ public class EmailUtil {
} }
mailSender.send(mimeMessage); mailSender.send(mimeMessage);
} }
} }
...@@ -10,31 +10,45 @@ ...@@ -10,31 +10,45 @@
</div> </div>
<div :style="classCardbody"> <div :style="classCardbody">
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="数据源" prop="sourceId"> <el-form-item label="数据API" prop="apiId">
<el-select v-model="form.sourceId" placeholder="请选择数据源"> <el-select v-model="form.apiId" placeholder="请选择数据API" @change="apiSelectChanged">
<el-option <el-option
v-for="source in sourceOptions" v-for="api in apiOptions"
:key="source.id" :key="api.id"
:label="source.sourceName" :label="api.apiName"
:value="source.id" :value="api.id"
:disabled="source.status === '0'" :disabled="api.status === '0'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集名称" prop="setName"> <el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.setName" placeholder="请输入数据集名称" /> <el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item> </el-form-item>
<el-form-item label="数据集sql" prop="setSql"> <el-form-item label="脱敏字段规则配置" prop="rules">
<sql-editor <el-table :data="resParamList" stripe border
ref="sqleditor" :max-height="300"
:value="form.setSql" style="width: 100%; margin: 15px 0;">
@changeTextarea="changeTextarea($event)" <el-table-column label="序号" width="55" align="center">
style="height: 300px;" <template slot-scope="scope">
></sql-editor> <span>{{ scope.$index +1 }}</span>
</el-form-item> </template>
<el-form-item> </el-table-column>
<el-button size="mini" type="primary" @click="formaterSql">Sql格式化</el-button> <el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
<el-button size="mini" type="primary" @click="dataPreview">预览</el-button> <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="remark" label="描述" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip >
</el-table-column>
</el-table>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
...@@ -49,54 +63,50 @@ ...@@ -49,54 +63,50 @@
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item> </el-form-item>
</el-form> </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-option>
</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-option>
</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> </div>
<el-drawer
:visible.sync="drawer"
direction="btt"
:with-header="false">
<el-table :data="previewData.dataList" stripe border
:max-height="200"
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>
<template v-for="(column, index) in previewData.columnList">
<el-table-column
:prop="column"
:label="column"
:key="index"
align="center"
show-overflow-tooltip
/>
</template>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="previewData.pageNum"
:page-size.sync="previewData.pageSize"
:total="previewData.dataTotal"
></el-pagination>
</el-drawer>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import { addDataSet } from '@/api/factory/dataset' import { addApiMask } from '@/api/market/apimask'
import { listDataSource, queryByPage } from '@/api/factory/datasource' import { listDataApi } from '@/api/market/dataapi'
import sqlFormatter from 'sql-formatter'
import SqlEditor from '@/components/SqlEditor'
export default { export default {
name: 'ApiMaskAdd', name: 'ApiMaskAdd',
components: {
SqlEditor
},
props: { props: {
data: { data: {
type: Object, type: Object,
...@@ -128,27 +138,50 @@ export default { ...@@ -128,27 +138,50 @@ export default {
}, },
// 表单参数 // 表单参数
form: { form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1', status: '1',
sourceId: undefined, remark: undefined
setSql: undefined
}, },
// 表单校验 // 表单校验
rules: { rules: {
setName: [ apiId: [
{ required: true, message: '数据集名称不能为空', trigger: 'blur' } { 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: [], statusOptions: [],
// 数据源数据字典 // 数据API数据字典
sourceOptions: [], apiOptions: [],
drawer: false, // 脱敏字段信息
previewData: { resParamList: [],
dataList: [], // 脱敏类型数据字典
columnList: [], cipherTypeOptions: [],
pageNum: 1, cryptTypeOptions: [],
pageSize: 20, // 正则替换数据字典
dataTotal: 0 regexCryptoOptions: [],
// 加密算法数据字典
algorithmCryptoOptions: [],
cipher: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "脱敏规则配置"
} }
} }
}, },
...@@ -158,73 +191,93 @@ export default { ...@@ -158,73 +191,93 @@ export default {
this.statusOptions = response.data this.statusOptions = response.data
} }
}) })
this.getDataSourceList() 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: { methods: {
showCard () { showCard () {
this.$emit('showCard', this.showOptions) this.$emit('showCard', this.showOptions)
}, },
getDataSourceList () { getDataApiList () {
listDataSource().then(response => { listDataApi().then(response => {
if (response.success) { if (response.success) {
this.sourceOptions = response.data this.apiOptions = response.data
} }
}) })
}, },
// 绑定编辑器value值的变化 apiSelectChanged (val) {
changeTextarea (val) { this.resParamList = this.apiOptions.filter(item => item.id === val).map(function (item) {
this.$set(this.form, 'setSql', val) return item.resParams
})
}, },
formaterSql () { fieldRule (fieldName) {
if (!this.form.setSql) { this.cipher.open = true
return this.form2.fieldName = fieldName
} this.form2.cipherType = undefined
this.$refs.sqleditor.editor.setValue(sqlFormatter.format(this.$refs.sqleditor.editor.getValue())) this.form2.cryptType = undefined
this.cryptTypeOptions = []
}, },
dataPreview () { cipherTypeSelectChanged (val) {
if (!this.form.sourceId) { this.form2.cryptType = undefined
return this.cryptTypeOptions = []
} if (val === '1') {
if (!this.form.setSql) { // 正则替换
return this.cryptTypeOptions = this.regexCryptoOptions
} else if (val === '2') {
// 加密算法
this.cryptTypeOptions = this.algorithmCryptoOptions
} }
let data = {} },
data.dataSourceId = this.form.sourceId submitFieldCipherForm () {
data.sql = this.form.setSql let fieldRuleIndex = this.form.rules.findIndex((item) => {
data.pageNum = this.previewData.pageNum return item.fieldName === this.form2.fieldName
data.pageSize = this.previewData.pageSize })
queryByPage(data).then(response => { if (fieldRuleIndex != -1) {
if (response.success) { // 当返回-1时,则说明数组中没有
const { data } = response this.form.rules.splice(fieldRuleIndex, 1)
let dataList = data.data || []
let columnList = []
if (dataList.length > 0) {
columnList = Object.keys(dataList[0])
} }
this.previewData.dataList = dataList if (this.form2.cipherType && this.form2.cryptType) {
this.previewData.columnList = columnList this.form.rules.push(this.form2)
this.previewData.dataTotal = data.total
this.drawer = true
} }
let cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === this.form2.cipherType
}) })
}, let crypt = this.cryptTypeOptions.find((item) => {
handleSizeChange (val) { return item.itemText === this.form2.cryptType
this.previewData.pageNum = 1 })
this.previewData.pageSize = val let fieldParamIndex = this.resParamList.findIndex((item) => {
this.dataPreview() return item.fieldName === this.form2.fieldName
}, })
handleCurrentChange (val) { let resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.previewData.pageNum = val this.$set(this.resParamList, fieldParamIndex, resParam)
this.dataPreview() this.cipher.open = false
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function () { submitForm: function () {
this.$refs['form'].validate(valid => { this.$refs['form'].validate(valid => {
if (valid) { if (valid) {
if (this.form.rules.length <= 0) {
this.$message.error('脱敏字段规则配置不能为空')
return
}
this.loadingOptions.loading = true this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...' this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true this.loadingOptions.isDisabled = true
addDataSet(this.form).then(response => { addApiMask(this.form).then(response => {
if (response.success) { if (response.success) {
this.$message.success('保存成功') this.$message.success('保存成功')
setTimeout(() => { setTimeout(() => {
......
...@@ -4,33 +4,47 @@ ...@@ -4,33 +4,47 @@
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>{{ title }}</span> <span>{{ title }}</span>
<el-button-group style="float: right;"> <el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-s-data" round @click="dataPreview">数据预览</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button> <el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group> </el-button-group>
</div> </div>
<div :style="classCardbody"> <div :style="classCardbody">
<el-form ref="form" :model="form" label-width="80px" disabled> <el-form ref="form" :model="form" :rules="rules" label-width="80px" disabled>
<el-form-item label="数据源" prop="sourceId"> <el-form-item label="数据API" prop="apiId">
<el-select v-model="form.sourceId" placeholder="请选择数据源"> <el-select v-model="form.apiId" placeholder="请选择数据API">
<el-option <el-option
v-for="source in sourceOptions" v-for="api in apiOptions"
:key="source.id" :key="api.id"
:label="source.sourceName" :label="api.apiName"
:value="source.id" :value="api.id"
:disabled="source.status === '0'" :disabled="api.status === '0'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集名称" prop="setName"> <el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.setName" placeholder="请输入数据集名称" /> <el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item> </el-form-item>
<el-form-item label="数据集sql" prop="setSql"> <el-form-item label="脱敏字段规则配置" prop="rules">
<sql-editor <el-table :data="resParamList" stripe border
ref="sqleditor" :max-height="300"
:value="form.setSql" style="width: 100%; margin: 15px 0;">
:readOnly="true" <el-table-column label="序号" width="55" align="center">
style="height: 300px;" <template slot-scope="scope">
></sql-editor> <span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip >
</el-table-column>
</el-table>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
...@@ -45,53 +59,17 @@ ...@@ -45,53 +59,17 @@
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-drawer
:visible.sync="drawer"
direction="btt"
:with-header="false">
<el-table :data="previewData.dataList" stripe border
:max-height="200"
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>
<template v-for="(column, index) in previewData.columnList">
<el-table-column
:prop="column"
:label="column"
:key="index"
align="center"
show-overflow-tooltip
/>
</template>
</el-table>
<el-pagination
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="previewData.pageNum"
:page-size.sync="previewData.pageSize"
:total="previewData.dataTotal"
></el-pagination>
</el-drawer>
</div> </div>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import { getDataSet } from '@/api/factory/dataset' import { getApiMask } from '@/api/market/apimask'
import { listDataSource, queryByPage } from '@/api/factory/datasource' import { listDataApi } from '@/api/market/dataapi'
import SqlEditor from '@/components/SqlEditor'
export default { export default {
name: 'ApiMaskDetail', name: 'ApiMaskDetail',
components: {
SqlEditor
},
props: { props: {
data: { data: {
type: Object, type: Object,
...@@ -116,19 +94,26 @@ export default { ...@@ -116,19 +94,26 @@ export default {
showDetail: false showDetail: false
}, },
// 表单参数 // 表单参数
form: {}, form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1',
remark: undefined
},
// 状态数据字典 // 状态数据字典
statusOptions: [], statusOptions: [],
// 数据数据字典 // 数据API数据字典
sourceOptions: [], apiOptions: [],
drawer: false, // 脱敏字段信息
previewData: { resParamList: [],
dataList: [], // 脱敏类型数据字典
columnList: [], cipherTypeOptions: [],
pageNum: 1, // 正则替换数据字典
pageSize: 20, regexCryptoOptions: [],
dataTotal: 0 // 加密算法数据字典
} algorithmCryptoOptions: []
} }
}, },
created () { created () {
...@@ -138,64 +123,60 @@ export default { ...@@ -138,64 +123,60 @@ export default {
this.statusOptions = response.data this.statusOptions = response.data
} }
}) })
this.getDataSourceList() this.getDataApiList()
this.getDataSet(this.data.id) 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.getApiMask(this.data.id)
}, },
methods: { methods: {
showCard () { showCard () {
this.$emit('showCard', this.showOptions) this.$emit('showCard', this.showOptions)
}, },
getDataSourceList () { getDataApiList () {
listDataSource().then(response => { listDataApi().then(response => {
if (response.success) { if (response.success) {
this.sourceOptions = response.data this.apiOptions = response.data
} }
}) })
}, },
/** 获取详情 */ /** 获取详情 */
getDataSet: function (id) { getApiMask: function (id) {
getDataSet(id).then(response => { getApiMask(id).then(response => {
if (response.success) { if (response.success) {
this.form = response.data this.form = response.data
this.$refs.sqleditor.editor.setValue(this.form.setSql) this.resParamList = this.apiOptions.filter(item => item.id === this.form.apiId).map(function (item) {
} return item.resParams
}) })
}, this.form.rules.forEach(rule => {
dataPreview () { let fieldParamIndex = this.resParamList.findIndex((param) => {
if (!this.form.sourceId) { return param.fieldName === rule.fieldName
return })
} if (fieldParamIndex != -1) {
if (!this.form.setSql) { let cipher = this.cipherTypeOptions.find((item) => {
return return item.itemText === rule.cipherType
} })
let data = {} let crypt = this.cryptTypeOptions.find((item) => {
data.dataSourceId = this.form.sourceId return item.itemText === rule.cryptType
data.sql = this.form.setSql })
data.pageNum = this.previewData.pageNum let resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
data.pageSize = this.previewData.pageSize this.$set(this.resParamList, fieldParamIndex, resParam)
queryByPage(data).then(response => {
if (response.success) {
const { data } = response
let dataList = data.data || []
let columnList = []
if (dataList.length > 0) {
columnList = Object.keys(dataList[0])
} }
this.previewData.dataList = dataList })
this.previewData.columnList = columnList
this.previewData.dataTotal = data.total
this.drawer = true
} }
}) })
},
handleSizeChange (val) {
this.previewData.pageNum = 1
this.previewData.pageSize = val
this.dataPreview()
},
handleCurrentChange (val) {
this.previewData.pageNum = val
this.dataPreview()
} }
} }
} }
......
...@@ -10,31 +10,45 @@ ...@@ -10,31 +10,45 @@
</div> </div>
<div :style="classCardbody"> <div :style="classCardbody">
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="数据源" prop="sourceId"> <el-form-item label="数据API" prop="apiId">
<el-select v-model="form.sourceId" placeholder="请选择数据源"> <el-select v-model="form.apiId" placeholder="请选择数据API" @change="apiSelectChanged">
<el-option <el-option
v-for="source in sourceOptions" v-for="api in apiOptions"
:key="source.id" :key="api.id"
:label="source.sourceName" :label="api.apiName"
:value="source.id" :value="api.id"
:disabled="source.status === '0'" :disabled="api.status === '0'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集名称" prop="setName"> <el-form-item label="脱敏名称" prop="maskName">
<el-input v-model="form.setName" placeholder="请输入数据集名称" /> <el-input v-model="form.maskName" placeholder="请输入脱敏名称" />
</el-form-item> </el-form-item>
<el-form-item label="数据集sql" prop="setSql"> <el-form-item label="脱敏字段规则配置" prop="rules">
<sql-editor <el-table :data="resParamList" stripe border
ref="sqleditor" :max-height="300"
:value="form.setSql" style="width: 100%; margin: 15px 0;">
@changeTextarea="changeTextarea($event)" <el-table-column label="序号" width="55" align="center">
style="height: 300px;" <template slot-scope="scope">
></sql-editor> <span>{{ scope.$index +1 }}</span>
</el-form-item> </template>
<el-form-item> </el-table-column>
<el-button size="mini" type="primary" @click="formaterSql">Sql格式化</el-button> <el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
<el-button size="mini" type="primary" @click="dataPreview">预览</el-button> <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="remark" label="描述" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cipherType" label="脱敏类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="cryptType" label="规则类型" align="center" show-overflow-tooltip >
</el-table-column>
</el-table>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
...@@ -49,54 +63,50 @@ ...@@ -49,54 +63,50 @@
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-drawer
:visible.sync="drawer" <!-- 脱敏规则对话框 -->
direction="btt" <el-dialog :title="cipher.title" :visible.sync="cipher.open" width="400px" append-to-body>
:with-header="false"> <el-form ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-table :data="previewData.dataList" stripe border <el-form-item label="字段名称" prop="fieldName">
:max-height="200" <el-input v-model="form2.fieldName" placeholder="请输入字段名称" :disabled="true"/>
style="width: 100%; margin: 15px 0;"> </el-form-item>
<el-table-column label="序号" width="55" align="center"> <el-form-item label="脱敏类型" prop="cipherType">
<template slot-scope="scope"> <el-select v-model="form2.cipherType" clearable placeholder="请选择脱敏类型" @change="cipherTypeSelectChanged">
<span>{{ scope.$index + 1 }}</span> <el-option
</template> v-for="dict in cipherTypeOptions"
</el-table-column> :key="dict.id"
<template v-for="(column, index) in previewData.columnList"> :label="dict.itemValue"
<el-table-column :value="dict.itemText"
:prop="column" ></el-option>
:label="column" </el-select>
:key="index" </el-form-item>
align="center" <el-form-item label="规则类型" prop="cryptType">
show-overflow-tooltip <el-select v-model="form2.cryptType" clearable placeholder="请选择规则类型">
/> <el-option
</template> v-for="dict in cryptTypeOptions"
</el-table> :key="dict.id"
<el-pagination :label="dict.itemValue"
:page-sizes="[10, 20, 50, 100]" :value="dict.itemText"
layout="total, sizes, prev, pager, next, jumper" ></el-option>
@size-change="handleSizeChange" </el-select>
@current-change="handleCurrentChange" </el-form-item>
:current-page.sync="previewData.pageNum" </el-form>
:page-size.sync="previewData.pageSize" <div slot="footer" class="dialog-footer">
:total="previewData.dataTotal" <el-button type="primary" @click="submitFieldCipherForm">确 定</el-button>
></el-pagination> <el-button @click="cipher.open = false">取 消</el-button>
</el-drawer> </div>
</el-dialog>
</div> </div>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import { getDataSet, updateDataSet } from '@/api/factory/dataset' import { getApiMask, updateApiMask } from '@/api/market/apimask'
import { listDataSource, queryByPage } from '@/api/factory/datasource' import { listDataApi } from '@/api/market/dataapi'
import sqlFormatter from 'sql-formatter'
import SqlEditor from '@/components/SqlEditor'
export default { export default {
name: 'ApiMaskEdit', name: 'ApiMaskEdit',
components: {
SqlEditor
},
props: { props: {
data: { data: {
type: Object, type: Object,
...@@ -127,24 +137,51 @@ export default { ...@@ -127,24 +137,51 @@ export default {
isDisabled: false isDisabled: false
}, },
// 表单参数 // 表单参数
form: {}, form: {
id: undefined,
apiId: undefined,
maskName: undefined,
rules: [],
status: '1',
remark: undefined
},
// 表单校验 // 表单校验
rules: { rules: {
setName: [ apiId: [
{ required: true, message: '数据集名称不能为空', trigger: 'blur' } { 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: [], statusOptions: [],
// 数据源数据字典 // 数据API数据字典
sourceOptions: [], apiOptions: [],
drawer: false, // 脱敏字段信息
previewData: { resParamList: [],
dataList: [], // 脱敏类型数据字典
columnList: [], cipherTypeOptions: [],
pageNum: 1, cryptTypeOptions: [],
pageSize: 20, // 正则替换数据字典
dataTotal: 0 regexCryptoOptions: [],
// 加密算法数据字典
algorithmCryptoOptions: [],
cipher: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "脱敏规则配置"
} }
} }
}, },
...@@ -155,80 +192,120 @@ export default { ...@@ -155,80 +192,120 @@ export default {
this.statusOptions = response.data this.statusOptions = response.data
} }
}) })
this.getDataSourceList() this.getDataApiList()
this.getDataSet(this.data.id) 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.getApiMask(this.data.id)
}, },
methods: { methods: {
showCard () { showCard () {
this.$emit('showCard', this.showOptions) this.$emit('showCard', this.showOptions)
}, },
getDataSourceList () { getDataApiList () {
listDataSource().then(response => { listDataApi().then(response => {
if (response.success) { if (response.success) {
this.sourceOptions = response.data this.apiOptions = response.data
} }
}) })
}, },
/** 获取详情 */ /** 获取详情 */
getDataSet: function (id) { getApiMask: function (id) {
getDataSet(id).then(response => { getApiMask(id).then(response => {
if (response.success) { if (response.success) {
this.form = response.data this.form = response.data
this.$refs.sqleditor.editor.setValue(this.form.setSql) this.resParamList = this.apiOptions.filter(item => item.id === this.form.apiId).map(function (item) {
return item.resParams
})
this.form.rules.forEach(rule => {
let fieldParamIndex = this.resParamList.findIndex((param) => {
return param.fieldName === rule.fieldName
})
if (fieldParamIndex != -1) {
let cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === rule.cipherType
})
let crypt = this.cryptTypeOptions.find((item) => {
return item.itemText === rule.cryptType
})
let resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.$set(this.resParamList, fieldParamIndex, resParam)
}
})
} }
}) })
}, },
// 绑定编辑器value值的变化 apiSelectChanged (val) {
changeTextarea (val) { this.resParamList = this.apiOptions.filter(item => item.id === val).map(function (item) {
this.$set(this.form, 'setSql', val) return item.resParams
})
}, },
formaterSql (val) { fieldRule (fieldName) {
this.$refs.sqleditor.editor.setValue(sqlFormatter.format(this.$refs.sqleditor.editor.getValue())) this.cipher.open = true
this.form2.fieldName = fieldName
this.form2.cipherType = undefined
this.form2.cryptType = undefined
this.cryptTypeOptions = []
}, },
dataPreview () { cipherTypeSelectChanged (val) {
if (!this.form.sourceId) { this.form2.cryptType = undefined
return this.cryptTypeOptions = []
} if (val === '1') {
if (!this.form.setSql) { // 正则替换
return this.cryptTypeOptions = this.regexCryptoOptions
} else if (val === '2') {
// 加密算法
this.cryptTypeOptions = this.algorithmCryptoOptions
} }
let data = {} },
data.dataSourceId = this.form.sourceId submitFieldCipherForm () {
data.sql = this.form.setSql let fieldRuleIndex = this.form.rules.findIndex((item) => {
data.pageNum = this.previewData.pageNum return item.fieldName === this.form2.fieldName
data.pageSize = this.previewData.pageSize })
queryByPage(data).then(response => { if (fieldRuleIndex != -1) {
if (response.success) { // 当返回-1时,则说明数组中没有
const { data } = response this.form.rules.splice(fieldRuleIndex, 1)
let dataList = data.data || []
let columnList = []
if (dataList.length > 0) {
columnList = Object.keys(dataList[0])
} }
this.previewData.dataList = dataList if (this.form2.cipherType && this.form2.cryptType) {
this.previewData.columnList = columnList this.form.rules.push(this.form2)
this.previewData.dataTotal = data.total
this.drawer = true
} }
let cipher = this.cipherTypeOptions.find((item) => {
return item.itemText === this.form2.cipherType
}) })
}, let crypt = this.cryptTypeOptions.find((item) => {
handleSizeChange (val) { return item.itemText === this.form2.cryptType
this.previewData.pageNum = 1 })
this.previewData.pageSize = val let fieldParamIndex = this.resParamList.findIndex((item) => {
this.dataPreview() return item.fieldName === this.form2.fieldName
}, })
handleCurrentChange (val) { let resParam = Object.assign({}, this.resParamList[fieldParamIndex], { cipherType: (cipher && cipher.itemValue) || undefined, cryptType: (crypt && crypt.itemValue) || undefined })
this.previewData.pageNum = val this.$set(this.resParamList, fieldParamIndex, resParam)
this.dataPreview() this.cipher.open = false
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function () { submitForm: function () {
this.$refs['form'].validate(valid => { this.$refs['form'].validate(valid => {
if (valid) { if (valid) {
if (this.form.rules.length <= 0) {
this.$message.error('脱敏字段规则配置不能为空')
return
}
this.loadingOptions.loading = true this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...' this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true this.loadingOptions.isDisabled = true
updateDataSet(this.form).then(response => { updateApiMask(this.form).then(response => {
if (response.success) { if (response.success) {
this.$message.success('保存成功') this.$message.success('保存成功')
setTimeout(() => { setTimeout(() => {
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
<el-form-item label="是否限流" prop="rateLimit"> <el-form-item label="是否限流" prop="rateLimit">
<el-radio-group v-model="form1.rateLimit"> <el-radio-group v-model="form1.rateLimit">
<el-radio <el-radio
v-for="dict in rateLimitOptions" v-for="dict in whetherOptions"
:key="dict.id" :key="dict.id"
:label="dict.itemText" :label="dict.itemText"
>{{dict.itemValue}}</el-radio> >{{dict.itemValue}}</el-radio>
...@@ -97,8 +97,8 @@ ...@@ -97,8 +97,8 @@
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="form2.configType === '1'"> <el-form-item label="数据库表" prop="tableName" v-if="form2.configType === '1'">
<el-select v-model="form2.tableName" placeholder="请选择" @change="tableNameSelectChanged"> <el-select v-model="form2.tableName" placeholder="请选择数据库表" @change="tableNameSelectChanged">
<el-option <el-option
v-for="item in tableNameOptions" v-for="item in tableNameOptions"
:key="item.tableName" :key="item.tableName"
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item v-if="form2.configType === '1'"> <el-form-item label="字段列表" v-if="form2.configType === '1'">
<el-table :data="fieldParamList" stripe border <el-table :data="fieldParamList" stripe border
:max-height="300" :max-height="300"
style="width: 100%; margin: 15px 0;"> style="width: 100%; margin: 15px 0;">
...@@ -166,6 +166,82 @@ ...@@ -166,6 +166,82 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-form ref="form3" :model="form3" :rules="rules3" label-width="80px" v-if="active == 3"> <el-form ref="form3" :model="form3" :rules="rules3" label-width="80px" v-if="active == 3">
<el-form-item label="请求参数">
<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>
<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"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</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-option>
</el-select>
</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-option>
</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-form-item>
<el-form-item label="返回字段">
<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>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</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-item>
</el-form> </el-form>
<el-button style="margin-top: 12px;" @click="handleNextStep" v-if="active < 3">下一步</el-button> <el-button style="margin-top: 12px;" @click="handleNextStep" v-if="active < 3">下一步</el-button>
<el-button style="margin-top: 12px;" @click="handleLastStep" v-if="active > 1">上一步</el-button> <el-button style="margin-top: 12px;" @click="handleLastStep" v-if="active > 1">上一步</el-button>
...@@ -274,8 +350,8 @@ export default { ...@@ -274,8 +350,8 @@ export default {
reqMethodOptions: [], reqMethodOptions: [],
// 返回格式数据字典 // 返回格式数据字典
resTypeOptions: [], resTypeOptions: [],
// 是否限流数据字典 // 是否数据字典
rateLimitOptions: [], whetherOptions: [],
// 状态数据字典 // 状态数据字典
statusOptions: [], statusOptions: [],
// 数据源数据字典 // 数据源数据字典
...@@ -285,7 +361,11 @@ export default { ...@@ -285,7 +361,11 @@ export default {
// 数据库表字段列表 // 数据库表字段列表
fieldParamList: [], fieldParamList: [],
// 配置方式数据字典 // 配置方式数据字典
configTypeOptions: [] configTypeOptions: [],
// 操作符数据字典
whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
} }
}, },
created () { created () {
...@@ -301,7 +381,7 @@ export default { ...@@ -301,7 +381,7 @@ export default {
}) })
this.getDicts('sys_yes_no').then(response => { this.getDicts('sys_yes_no').then(response => {
if (response.success) { if (response.success) {
this.rateLimitOptions = response.data this.whetherOptions = response.data
} }
}) })
this.getDicts('sys_common_status').then(response => { this.getDicts('sys_common_status').then(response => {
...@@ -315,6 +395,16 @@ export default { ...@@ -315,6 +395,16 @@ export default {
this.configTypeOptions = response.data 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: { methods: {
showCard () { showCard () {
...@@ -342,23 +432,22 @@ export default { ...@@ -342,23 +432,22 @@ export default {
this.form3.reqParams = this.fieldParamList.filter(item => item.reqable).map(function (item) { this.form3.reqParams = this.fieldParamList.filter(item => item.reqable).map(function (item) {
let json = {} let json = {}
json.paramName = item.colName json.paramName = item.colName
json.nullable = false json.nullable = item.nullable || '0'
json.remark = item.colComment json.remark = item.remark || undefined
json.paramType = undefined json.paramType = item.paramType || undefined
json.whereType = undefined json.whereType = item.whereType || undefined
json.exampleValue = undefined json.exampleValue = item.exampleValue || undefined
json.defaultValue = undefined json.defaultValue = item.defaultValue || undefined
return json return json
}) })
this.form3.resParams = this.fieldParamList.filter(item => item.resable).map(function (item) { this.form3.resParams = this.fieldParamList.filter(item => item.resable).map(function (item) {
let json = {} let json = {}
json.fieldName = item.colName json.fieldName = item.colName
json.remark = item.colComment json.remark = item.colComment || undefined
json.dataType = item.dataType json.dataType = item.dataType || undefined
json.exampleValue = undefined json.exampleValue = item.exampleValue || undefined
return json return json
}) })
console.log(this.form3)
} }
this.active++ this.active++
} }
...@@ -413,7 +502,28 @@ export default { ...@@ -413,7 +502,28 @@ export default {
sqlParse(data).then(response => { sqlParse(data).then(response => {
if (response.success) { if (response.success) {
const { data } = response const { data } = response
console.log(data) let reqParams = data.reqParams
let resParams = data.resParams
this.form3.reqParams = reqParams.map(function (item) {
let json = {}
json.paramName = item.paramName
json.nullable = item.nullable || '0'
json.remark = item.remark || undefined
json.paramType = item.paramType || undefined
json.whereType = item.whereType || undefined
json.exampleValue = item.exampleValue || undefined
json.defaultValue = item.defaultValue || undefined
return json
})
this.form3.resParams = resParams.map(function (item) {
let json = {}
json.fieldName = item.fieldName
json.remark = item.remark || undefined
json.dataType = item.dataType || undefined
json.exampleValue = item.exampleValue || undefined
return json
})
this.$message.success('解析成功,请进行下一步')
} }
}) })
}, },
...@@ -421,10 +531,21 @@ export default { ...@@ -421,10 +531,21 @@ export default {
submitForm: function () { submitForm: function () {
this.$refs['form3'].validate(valid => { this.$refs['form3'].validate(valid => {
if (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.executeConfig = this.form2
this.form1.reqParams = this.form3.reqParams
this.form1.resParams = this.form3.resParams
this.loadingOptions.loading = true this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...' this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true this.loadingOptions.isDisabled = true
addDataApi(this.form).then(response => { addDataApi(this.form1).then(response => {
if (response.success) { if (response.success) {
this.$message.success('保存成功') this.$message.success('保存成功')
setTimeout(() => { setTimeout(() => {
......
...@@ -4,36 +4,65 @@ ...@@ -4,36 +4,65 @@
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>{{ title }}</span> <span>{{ title }}</span>
<el-button-group style="float: right;"> <el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-s-data" round @click="dataPreview">数据预览</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button> <el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group> </el-button-group>
</div> </div>
<div :style="classCardbody"> <div :style="classCardbody">
<el-form ref="form" :model="form" label-width="80px" disabled> <el-steps :active="active" finish-status="success" align-center>
<el-form-item label="数据源" prop="sourceId"> <el-step title="属性配置"></el-step>
<el-select v-model="form.sourceId" placeholder="请选择数据源"> <el-step title="执行配置"></el-step>
<el-step title="参数配置"></el-step>
</el-steps>
<el-form ref="form1" :model="form1" :rules="rules1" label-width="80px" v-if="active == 1" 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 <el-option
v-for="source in sourceOptions" v-for="dict in reqMethodOptions"
:key="source.id" :key="dict.id"
:label="source.sourceName" :label="dict.itemValue"
:value="source.id" :value="dict.itemText"
:disabled="source.status === '0'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集名称" prop="setName"> <el-form-item label="返回格式" prop="resType">
<el-input v-model="form.setName" placeholder="请输入数据集名称" /> <el-select v-model="form1.resType" placeholder="请选择返回格式">
<el-option
v-for="dict in resTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集sql" prop="setSql"> <el-form-item label="IP黑名单" prop="deny">
<sql-editor <el-input v-model="form1.deny" type="textarea" placeholder="请输入IP黑名单多个用,隔开" />
ref="sqleditor" </el-form-item>
:value="form.setSql" <el-form-item label="是否限流" prop="rateLimit">
:readOnly="true" <el-radio-group v-model="form1.rateLimit">
style="height: 300px;" <el-radio
></sql-editor> v-for="dict in whetherOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="请求次数" prop="times" v-if="form1.rateLimit === '1'">
<el-input-number v-model="form1.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="请求时间范围" prop="seconds" v-if="form1.rateLimit === '1'">
<el-input-number v-model="form1.seconds" controls-position="right" :min="1"/>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form1.status">
<el-radio <el-radio
v-for="dict in statusOptions" v-for="dict in statusOptions"
:key="dict.id" :key="dict.id"
...@@ -42,49 +71,187 @@ ...@@ -42,49 +71,187 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="80px" v-if="active == 2" disabled>
<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-option>
</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-option>
</el-select>
</el-form-item>
<el-form-item label="数据库表" prop="tableName" v-if="form2.configType === '1'">
<el-select v-model="form2.tableName" placeholder="请选择数据库表" @change="tableNameSelectChanged">
<el-option
v-for="item in tableNameOptions"
:key="item.tableName"
:label="item.tableComment"
:value="item.tableName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="字段列表" v-if="form2.configType === '1'">
<el-table :data="fieldParamList" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;">
<el-table-column prop="colPosition" label="序号" width="55" align="center" >
</el-table-column>
<el-table-column prop="colName" label="列名" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="colKey" label="是否主键" align="center" show-overflow-tooltip >
<template slot-scope="scope">
<span v-if="scope.row.colKey === true"></span>
<span v-if="scope.row.colKey === false"></span>
</template>
</el-table-column>
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip >
<template slot-scope="scope">
<span v-if="scope.row.nullable === true"></span>
<span v-if="scope.row.nullable === false"></span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="colComment" label="列注释" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50" >
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable"></el-checkbox>
</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"></el-checkbox>
</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"
@changeTextarea="changeTextarea($event)"
style="height: 300px;margin: 10px 10px;"
></sql-editor>
</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-item>
</el-form> </el-form>
<el-drawer <el-form ref="form3" :model="form3" :rules="rules3" label-width="80px" v-if="active == 3" disabled>
:visible.sync="drawer" <el-form-item label="请求参数">
direction="btt" <el-table :data="form3.reqParams" stripe border
:with-header="false"> :max-height="300"
<el-table :data="previewData.dataList" stripe border style="width: 100%; margin: 15px 0;">
:max-height="200" <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>
<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"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</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-option>
</el-select>
</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-option>
</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-form-item>
<el-form-item label="返回字段">
<el-table :data="form3.resParams" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;"> style="width: 100%; margin: 15px 0;">
<el-table-column label="序号" width="55" align="center"> <el-table-column label="序号" width="55" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span> <span>{{ scope.$index +1 }}</span>
</template> </template>
</el-table-column> </el-table-column>
<template v-for="(column, index) in previewData.columnList"> <el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
<el-table-column </el-table-column>
:prop="column" <el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
:label="column" </el-table-column>
:key="index" <el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
align="center" </el-table-column>
show-overflow-tooltip <el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
/> <template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template> </template>
</el-table-column>
</el-table> </el-table>
<el-pagination </el-form-item>
:page-sizes="[10, 20, 50, 100]" </el-form>
layout="total, sizes, prev, pager, next, jumper" <el-button style="margin-top: 12px;" @click="handleNextStep" v-if="active < 3">下一步</el-button>
@size-change="handleSizeChange" <el-button style="margin-top: 12px;" @click="handleLastStep" v-if="active > 1">上一步</el-button>
@current-change="handleCurrentChange"
:current-page.sync="previewData.pageNum"
:page-size.sync="previewData.pageSize"
:total="previewData.dataTotal"
></el-pagination>
</el-drawer>
</div> </div>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import { getDataSet } from '@/api/factory/dataset' import { getDataApi, sqlParse } from '@/api/market/dataapi'
import { listDataSource, queryByPage } from '@/api/factory/datasource' import { listDataSource, getDbTables, getDbTableColumns } from '@/api/factory/datasource'
import SqlEditor from '@/components/SqlEditor' import SqlEditor from '@/components/SqlEditor'
export default { export default {
...@@ -115,31 +282,124 @@ export default { ...@@ -115,31 +282,124 @@ export default {
showEdit: false, showEdit: false,
showDetail: false showDetail: false
}, },
active: 1,
// 表单参数 // 表单参数
form: {}, form1: {
id: undefined,
apiName: undefined,
apiVersion: undefined,
apiUrl: undefined,
reqMethod: undefined,
resType: undefined,
deny: undefined,
rateLimit: '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: 'blur' }
],
resType: [
{ required: true, message: '返回格式不能为空', trigger: 'blur' }
]
},
form2: {
configType: undefined,
sourceId: undefined,
tableName: undefined,
fieldParams: [],
sqlText: undefined
},
rules2: {
configType: [
{ required: true, message: '配置方式不能为空', trigger: 'blur' }
],
sourceId: [
{ required: true, message: '数据源不能为空', trigger: 'blur' }
]
},
form3: {
reqParams: [],
resParams: []
},
rules3: {},
// 请求方式数据字典
reqMethodOptions: [],
// 返回格式数据字典
resTypeOptions: [],
// 是否数据字典
whetherOptions: [],
// 状态数据字典 // 状态数据字典
statusOptions: [], statusOptions: [],
// 数据源数据字典 // 数据源数据字典
sourceOptions: [], sourceOptions: [],
drawer: false, // 数据库表数据字典
previewData: { tableNameOptions: [],
dataList: [], // 数据库表字段列表
columnList: [], fieldParamList: [],
pageNum: 1, // 配置方式数据字典
pageSize: 20, configTypeOptions: [],
dataTotal: 0 // 操作符数据字典
} whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
} }
}, },
created () { created () {
console.log('id:' + this.data.id) console.log('id:' + this.data.id)
this.getDicts('sys_job_status').then(response => { 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('sys_common_status').then(response => {
if (response.success) { if (response.success) {
this.statusOptions = response.data this.statusOptions = response.data
} }
}) })
this.getDataSourceList() this.getDataSourceList()
this.getDataSet(this.data.id) 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
}
})
this.getDataApi(this.data.id)
}, },
methods: { methods: {
showCard () { showCard () {
...@@ -152,50 +412,141 @@ export default { ...@@ -152,50 +412,141 @@ export default {
} }
}) })
}, },
/** 获取详情 */ /** 步骤条下一步 */
getDataSet: function (id) { handleNextStep () {
getDataSet(id).then(response => { 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) {
if (this.form2.configType && this.form2.configType === '1') {
this.form3.reqParams = this.fieldParamList.filter(item => item.reqable).map(function (item) {
let json = {}
json.paramName = item.colName
json.nullable = item.nullable || '0'
json.remark = item.remark || undefined
json.paramType = item.paramType || undefined
json.whereType = item.whereType || undefined
json.exampleValue = item.exampleValue || undefined
json.defaultValue = item.defaultValue || undefined
return json
})
this.form3.resParams = this.fieldParamList.filter(item => item.resable).map(function (item) {
let json = {}
json.fieldName = item.colName
json.remark = item.colComment || undefined
json.dataType = item.dataType || undefined
json.exampleValue = item.exampleValue || undefined
return json
})
}
this.active++
}
})
}
},
/** 步骤条上一步 */
handleLastStep () {
this.active--
},
changeTextarea (val) {
this.form2.sqlText = val
},
configTypeSelectChanged (val) {
if (this.form2.configType === '1' && this.form2.sourceId && this.tableNameOptions.length <= 0) {
getDbTables(this.form2.sourceId).then(response => {
if (response.success) { if (response.success) {
this.form = response.data this.tableNameOptions = response.data
this.$refs.sqleditor.editor.setValue(this.form.setSql) this.fieldParamList = []
} }
}) })
}
}, },
dataPreview () { sourceSelectChanged (val) {
if (!this.form.sourceId) { if (this.form2.configType && this.form2.configType === '1') {
getDbTables(val).then(response => {
if (response.success) {
this.tableNameOptions = response.data
this.fieldParamList = []
}
})
}
},
tableNameSelectChanged (val) {
getDbTableColumns(this.form2.sourceId, val).then(response => {
if (response.success) {
this.fieldParamList = response.data
}
})
},
sqlParse () {
if (!this.form2.sourceId) {
this.$message.error('数据源不能为空')
return return
} }
if (!this.form.setSql) { if (!this.form2.sqlText) {
this.$message.error('解析SQL不能为空')
return return
} }
let data = {} let data = {}
data.dataSourceId = this.form.sourceId data.sqlText = this.form2.sqlText
data.sql = this.form.setSql sqlParse(data).then(response => {
data.pageNum = this.previewData.pageNum
data.pageSize = this.previewData.pageSize
queryByPage(data).then(response => {
if (response.success) { if (response.success) {
const { data } = response const { data } = response
let dataList = data.data || [] let reqParams = data.reqParams
let columnList = [] let resParams = data.resParams
if (dataList.length > 0) { this.form3.reqParams = reqParams.map(function (item) {
columnList = Object.keys(dataList[0]) let json = {}
} json.paramName = item.paramName
this.previewData.dataList = dataList json.nullable = item.nullable || '0'
this.previewData.columnList = columnList json.remark = item.remark || undefined
this.previewData.dataTotal = data.total json.paramType = item.paramType || undefined
this.drawer = true json.whereType = item.whereType || undefined
json.exampleValue = item.exampleValue || undefined
json.defaultValue = item.defaultValue || undefined
return json
})
this.form3.resParams = resParams.map(function (item) {
let json = {}
json.fieldName = item.fieldName
json.remark = item.remark || undefined
json.dataType = item.dataType || undefined
json.exampleValue = item.exampleValue || undefined
return json
})
this.$message.success('解析成功,请进行下一步')
} }
}) })
}, },
handleSizeChange (val) { /** 获取详情 */
this.previewData.pageNum = 1 getDataApi: function (id) {
this.previewData.pageSize = val getDataApi(id).then(response => {
this.dataPreview() if (response.success) {
}, this.form1 = response.data
handleCurrentChange (val) { this.form2 = this.form1.executeConfig
this.previewData.pageNum = val this.form3.reqParams = this.form1.reqParams
this.dataPreview() this.form3.resParams = this.form1.resParams
if (this.form2.configType === '1') {
getDbTables(this.form2.sourceId).then(response => {
if (response.success) {
this.tableNameOptions = response.data
getDbTableColumns(this.form2.sourceId, this.form2.tableName).then(response => {
if (response.success) {
this.fieldParamList = response.data
}
})
}
})
}
if (this.form2.configType === '2') {
this.$refs.sqleditor.editor.setValue(this.form2.sqlText)
}
}
})
} }
} }
} }
......
...@@ -9,35 +9,61 @@ ...@@ -9,35 +9,61 @@
</el-button-group> </el-button-group>
</div> </div>
<div :style="classCardbody"> <div :style="classCardbody">
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-steps :active="active" finish-status="success" align-center>
<el-form-item label="数据源" prop="sourceId"> <el-step title="属性配置"></el-step>
<el-select v-model="form.sourceId" placeholder="请选择数据源"> <el-step title="执行配置"></el-step>
<el-step title="参数配置"></el-step>
</el-steps>
<el-form ref="form1" :model="form1" :rules="rules1" label-width="80px" v-if="active == 1">
<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 <el-option
v-for="source in sourceOptions" v-for="dict in reqMethodOptions"
:key="source.id" :key="dict.id"
:label="source.sourceName" :label="dict.itemValue"
:value="source.id" :value="dict.itemText"
:disabled="source.status === '0'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集名称" prop="setName"> <el-form-item label="返回格式" prop="resType">
<el-input v-model="form.setName" placeholder="请输入数据集名称" /> <el-select v-model="form1.resType" placeholder="请选择返回格式">
<el-option
v-for="dict in resTypeOptions"
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="数据集sql" prop="setSql"> <el-form-item label="IP黑名单" prop="deny">
<sql-editor <el-input v-model="form1.deny" type="textarea" placeholder="请输入IP黑名单多个用,隔开" />
ref="sqleditor"
:value="form.setSql"
@changeTextarea="changeTextarea($event)"
style="height: 300px;"
></sql-editor>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item label="是否限流" prop="rateLimit">
<el-button size="mini" type="primary" @click="formaterSql">Sql格式化</el-button> <el-radio-group v-model="form1.rateLimit">
<el-button size="mini" type="primary" @click="dataPreview">预览</el-button> <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 label="请求次数" prop="times" v-if="form1.rateLimit === '1'">
<el-input-number v-model="form1.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="请求时间范围" prop="seconds" v-if="form1.rateLimit === '1'">
<el-input-number v-model="form1.seconds" controls-position="right" :min="1"/>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form1.status">
<el-radio <el-radio
v-for="dict in statusOptions" v-for="dict in statusOptions"
:key="dict.id" :key="dict.id"
...@@ -46,50 +72,187 @@ ...@@ -46,50 +72,187 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="80px" v-if="active == 2">
<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-option>
</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-option>
</el-select>
</el-form-item>
<el-form-item label="数据库表" prop="tableName" v-if="form2.configType === '1'">
<el-select v-model="form2.tableName" placeholder="请选择数据库表" @change="tableNameSelectChanged">
<el-option
v-for="item in tableNameOptions"
:key="item.tableName"
:label="item.tableComment"
:value="item.tableName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="字段列表" v-if="form2.configType === '1'">
<el-table :data="fieldParamList" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;">
<el-table-column prop="colPosition" label="序号" width="55" align="center" >
</el-table-column>
<el-table-column prop="colName" label="列名" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="colKey" label="是否主键" align="center" show-overflow-tooltip >
<template slot-scope="scope">
<span v-if="scope.row.colKey === true"></span>
<span v-if="scope.row.colKey === false"></span>
</template>
</el-table-column>
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip >
<template slot-scope="scope">
<span v-if="scope.row.nullable === true"></span>
<span v-if="scope.row.nullable === false"></span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="colComment" label="列注释" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50" >
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable"></el-checkbox>
</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"></el-checkbox>
</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"
@changeTextarea="changeTextarea($event)"
style="height: 300px;margin: 10px 10px;"
></sql-editor>
</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-item>
</el-form> </el-form>
<el-drawer <el-form ref="form3" :model="form3" :rules="rules3" label-width="80px" v-if="active == 3">
:visible.sync="drawer" <el-form-item label="请求参数">
direction="btt" <el-table :data="form3.reqParams" stripe border
:with-header="false"> :max-height="300"
<el-table :data="previewData.dataList" stripe border
:max-height="200"
style="width: 100%; margin: 15px 0;"> style="width: 100%; margin: 15px 0;">
<el-table-column label="序号" width="55" align="center"> <el-table-column label="序号" width="55" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span> <span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip >
</el-table-column>
<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"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</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-option>
</el-select>
</template> </template>
</el-table-column> </el-table-column>
<template v-for="(column, index) in previewData.columnList"> <el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip >
<el-table-column <template slot-scope="scope">
:prop="column" <el-select v-model="scope.row.paramType" placeholder="请选择参数类型">
:label="column" <el-option
:key="index" v-for="dict in paramTypeOptions"
align="center" :key="dict.id"
show-overflow-tooltip :label="dict.itemValue"
/> :value="dict.itemText"
></el-option>
</el-select>
</template> </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-table>
<el-pagination </el-form-item>
:page-sizes="[10, 20, 50, 100]" <el-form-item label="返回字段">
layout="total, sizes, prev, pager, next, jumper" <el-table :data="form3.resParams" stripe border
@size-change="handleSizeChange" :max-height="300"
@current-change="handleCurrentChange" style="width: 100%; margin: 15px 0;">
:current-page.sync="previewData.pageNum" <el-table-column label="序号" width="55" align="center">
:page-size.sync="previewData.pageSize" <template slot-scope="scope">
:total="previewData.dataTotal" <span>{{ scope.$index +1 }}</span>
></el-pagination> </template>
</el-drawer> </el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</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-item>
</el-form>
<el-button style="margin-top: 12px;" @click="handleNextStep" v-if="active < 3">下一步</el-button>
<el-button style="margin-top: 12px;" @click="handleLastStep" v-if="active > 1">上一步</el-button>
</div> </div>
</el-card> </el-card>
</div> </div>
</template> </template>
<script> <script>
import { getDataSet, updateDataSet } from '@/api/factory/dataset' import { getDataApi, updateDataApi, sqlParse } from '@/api/market/dataapi'
import { listDataSource, queryByPage } from '@/api/factory/datasource' import { listDataSource, getDbTables, getDbTableColumns } from '@/api/factory/datasource'
import sqlFormatter from 'sql-formatter'
import SqlEditor from '@/components/SqlEditor' import SqlEditor from '@/components/SqlEditor'
export default { export default {
...@@ -126,37 +289,124 @@ export default { ...@@ -126,37 +289,124 @@ export default {
loadingText: '保存', loadingText: '保存',
isDisabled: false isDisabled: false
}, },
active: 1,
// 表单参数 // 表单参数
form: {}, form1: {
id: undefined,
apiName: undefined,
apiVersion: undefined,
apiUrl: undefined,
reqMethod: undefined,
resType: undefined,
deny: undefined,
rateLimit: '1',
times: 5,
seconds: 60,
status: '1',
remark: undefined,
executeConfig: {},
reqParams: [],
resParams: []
},
// 表单校验 // 表单校验
rules: { rules1: {
setName: [ apiName: [
{ required: true, message: '数据集名称不能为空', trigger: 'blur' } { 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,
tableName: undefined,
fieldParams: [],
sqlText: undefined
},
rules2: {
configType: [
{ required: true, message: '配置方式不能为空', trigger: 'blur' }
],
sourceId: [
{ required: true, message: '数据源不能为空', trigger: 'blur' }
]
},
form3: {
reqParams: [],
resParams: []
},
rules3: {},
// 请求方式数据字典
reqMethodOptions: [],
// 返回格式数据字典
resTypeOptions: [],
// 是否数据字典
whetherOptions: [],
// 状态数据字典 // 状态数据字典
statusOptions: [], statusOptions: [],
// 数据源数据字典 // 数据源数据字典
sourceOptions: [], sourceOptions: [],
drawer: false, // 数据库表数据字典
previewData: { tableNameOptions: [],
dataList: [], // 数据库表字段列表
columnList: [], fieldParamList: [],
pageNum: 1, // 配置方式数据字典
pageSize: 20, configTypeOptions: [],
dataTotal: 0 // 操作符数据字典
} whereTypeOptions: [],
// 参数类型数据字典
paramTypeOptions: []
} }
}, },
created () { created () {
console.log('id:' + this.data.id) console.log('id:' + this.data.id)
this.getDicts('sys_job_status').then(response => { 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('sys_common_status').then(response => {
if (response.success) { if (response.success) {
this.statusOptions = response.data this.statusOptions = response.data
} }
}) })
this.getDataSourceList() this.getDataSourceList()
this.getDataSet(this.data.id) 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
}
})
this.getDataApi(this.data.id)
}, },
methods: { methods: {
showCard () { showCard () {
...@@ -169,66 +419,161 @@ export default { ...@@ -169,66 +419,161 @@ export default {
} }
}) })
}, },
/** 获取详情 */ /** 步骤条下一步 */
getDataSet: function (id) { handleNextStep () {
getDataSet(id).then(response => { if (this.active === 1) {
if (response.success) { this.$refs['form1'].validate(valid => {
this.form = response.data if (valid) {
this.$refs.sqleditor.editor.setValue(this.form.setSql) this.active++
} }
}) })
} else if (this.active === 2) {
this.$refs['form2'].validate(valid => {
if (valid) {
if (this.form2.configType && this.form2.configType === '1') {
this.form3.reqParams = this.fieldParamList.filter(item => item.reqable).map(function (item) {
let json = {}
json.paramName = item.colName
json.nullable = item.nullable || '0'
json.remark = item.remark || undefined
json.paramType = item.paramType || undefined
json.whereType = item.whereType || undefined
json.exampleValue = item.exampleValue || undefined
json.defaultValue = item.defaultValue || undefined
return json
})
this.form3.resParams = this.fieldParamList.filter(item => item.resable).map(function (item) {
let json = {}
json.fieldName = item.colName
json.remark = item.colComment || undefined
json.dataType = item.dataType || undefined
json.exampleValue = item.exampleValue || undefined
return json
})
}
this.active++
}
})
}
},
/** 步骤条上一步 */
handleLastStep () {
this.active--
}, },
// 绑定编辑器value值的变化
changeTextarea (val) { changeTextarea (val) {
this.$set(this.form, 'setSql', val) this.form2.sqlText = val
}, },
formaterSql (val) { configTypeSelectChanged (val) {
this.$refs.sqleditor.editor.setValue(sqlFormatter.format(this.$refs.sqleditor.editor.getValue())) if (this.form2.configType === '1' && this.form2.sourceId && this.tableNameOptions.length <= 0) {
getDbTables(this.form2.sourceId).then(response => {
if (response.success) {
this.tableNameOptions = response.data
this.fieldParamList = []
}
})
}
},
sourceSelectChanged (val) {
if (this.form2.configType && this.form2.configType === '1') {
getDbTables(val).then(response => {
if (response.success) {
this.tableNameOptions = response.data
this.fieldParamList = []
}
})
}
},
tableNameSelectChanged (val) {
getDbTableColumns(this.form2.sourceId, val).then(response => {
if (response.success) {
this.fieldParamList = response.data
}
})
}, },
dataPreview () { sqlParse () {
if (!this.form.sourceId) { if (!this.form2.sourceId) {
this.$message.error('数据源不能为空')
return return
} }
if (!this.form.setSql) { if (!this.form2.sqlText) {
this.$message.error('解析SQL不能为空')
return return
} }
let data = {} let data = {}
data.dataSourceId = this.form.sourceId data.sqlText = this.form2.sqlText
data.sql = this.form.setSql sqlParse(data).then(response => {
data.pageNum = this.previewData.pageNum
data.pageSize = this.previewData.pageSize
queryByPage(data).then(response => {
if (response.success) { if (response.success) {
const { data } = response const { data } = response
let dataList = data.data || [] let reqParams = data.reqParams
let columnList = [] let resParams = data.resParams
if (dataList.length > 0) { this.form3.reqParams = reqParams.map(function (item) {
columnList = Object.keys(dataList[0]) let json = {}
} json.paramName = item.paramName
this.previewData.dataList = dataList json.nullable = item.nullable || '0'
this.previewData.columnList = columnList json.remark = item.remark || undefined
this.previewData.dataTotal = data.total json.paramType = item.paramType || undefined
this.drawer = true json.whereType = item.whereType || undefined
json.exampleValue = item.exampleValue || undefined
json.defaultValue = item.defaultValue || undefined
return json
})
this.form3.resParams = resParams.map(function (item) {
let json = {}
json.fieldName = item.fieldName
json.remark = item.remark || undefined
json.dataType = item.dataType || undefined
json.exampleValue = item.exampleValue || undefined
return json
})
this.$message.success('解析成功,请进行下一步')
} }
}) })
}, },
handleSizeChange (val) { /** 获取详情 */
this.previewData.pageNum = 1 getDataApi: function (id) {
this.previewData.pageSize = val getDataApi(id).then(response => {
this.dataPreview() if (response.success) {
}, this.form1 = response.data
handleCurrentChange (val) { this.form2 = this.form1.executeConfig
this.previewData.pageNum = val this.form3.reqParams = this.form1.reqParams
this.dataPreview() this.form3.resParams = this.form1.resParams
if (this.form2.configType === '1') {
getDbTables(this.form2.sourceId).then(response => {
if (response.success) {
this.tableNameOptions = response.data
getDbTableColumns(this.form2.sourceId, this.form2.tableName).then(response => {
if (response.success) {
this.fieldParamList = response.data
}
})
}
})
}
if (this.form2.configType === '2') {
this.$refs.sqleditor.editor.setValue(this.form2.sqlText)
}
}
})
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function () { submitForm: function () {
this.$refs['form'].validate(valid => { this.$refs['form3'].validate(valid => {
if (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.executeConfig = this.form2
this.form1.reqParams = this.form3.reqParams
this.form1.resParams = this.form3.resParams
this.loadingOptions.loading = true this.loadingOptions.loading = true
this.loadingOptions.loadingText = '保存中...' this.loadingOptions.loadingText = '保存中...'
this.loadingOptions.isDisabled = true this.loadingOptions.isDisabled = true
updateDataSet(this.form).then(response => { updateDataApi(this.form1).then(response => {
if (response.success) { if (response.success) {
this.$message.success('保存成功') this.$message.success('保存成功')
setTimeout(() => { setTimeout(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment