ER图测试,域账号登录测试,修改数据查询的展示问题
This commit is contained in:
@@ -1 +0,0 @@
|
||||
.about-zyplayer-doc{text-align:left;line-height:normal}.about-zyplayer-doc .el-dialog__body{padding:20px}#app,.el-container,.el-menu{height:100%}.el-header{background-color:#1d4e89!important}.database-list-tree{overflow-x:auto;min-height:150px}.database-list-tree,.database-list-tree .el-loading-mask{background-color:#fafafa}.database-list-tree .el-tree-node>.el-tree-node__children{overflow:unset}.el-tree-node__content .el-icon-more{margin-left:5px;color:#606266;font-size:12px;display:none;padding:2px 5px}.el-tree-node__content:hover .el-icon-more{display:inline-block}.login-container{border-radius:5px;-moz-border-radius:5px;background-clip:padding-box;margin:0 auto;width:350px;padding:35px 35px 15px 35px;background:#fff;border:1px solid #eaeaea;-webkit-box-shadow:0 0 25px #cac6c6;box-shadow:0 0 25px #cac6c6}.title{margin:0 auto 40px auto;text-align:center;color:#505458}.remember{margin:0 0 35px 0}.my-info-vue .box-card{margin:10px}.table-info-vue{padding:0 20px}.table-info-vue .el-dialog__body{padding:0 20px 10px}.table-info-vue .el-form-item{margin-bottom:5px}.table-info-vue .edit-table-desc{cursor:pointer;color:#409eff}.table-info-vue .description{cursor:pointer;min-height:23px}.table-info-vue .el-table td,.table-info-vue .el-table th{padding:5px 0}.table-info-vue .status-info-row{padding:8px 0}.table-info-vue .status-info-row .label{width:80px;display:inline-block;text-align:right;color:#606266}.table-database-vue .el-table td,.table-database-vue .el-table th{padding:5px 0}.table-database-vue .label{width:140px;text-align:right}.table-database-vue .el-table th,.table-procedure-edit-vue .el-table td,.table-procedure-vue .el-table td{padding:5px 0}body,html{margin:0;padding:0;height:100%}.header-right-user-name{color:#fff;padding-right:5px}.el-menu-vertical{border-right:0}.el-menu-vertical,.el-menu-vertical .el-menu{background:#fafafa}.el-header{background-color:#409eff;color:#333;line-height:40px;text-align:right;height:40px!important}.data-executor-vue .ace-monokai .ace_print-margin{display:none}.data-executor-vue .el-card__body{padding:10px}.data-executor-vue .sql-params .el-input-group{width:auto;margin:10px 10px 0 0}.data-executor-vue .sql-params .el-input__inner{width:200px}.data-executor-vue .el-table td,.el-table th{padding:6px 0}.data-executor-vue .execute-result-table .el-input__inner{height:25px;line-height:25px;padding:0 5px}.data-executor-vue .execute-result-table .el-textarea__inner{height:27px;min-height:27px;line-height:25px;padding:0 5px;resize:none}.data-executor-vue .sql-content-line{margin:0;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.data-executor-vue .execute-use-time{font-size:12px;margin-right:10px}.data-executor-vue-out .el-tabs__nav-scroll{padding-left:20px}.data-executor-vue-out .el-button+.el-button{margin-left:0}.data-executor-vue-out .el-table__body-wrapper{height:calc(100vh - 180px);overflow-y:auto}.data-transfer-vue .el-button+.el-button{margin-left:4px}
|
||||
1
zyplayer-doc-db/src/main/resources/dist/css/index.bb15836f.css
vendored
Normal file
1
zyplayer-doc-db/src/main/resources/dist/css/index.bb15836f.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=css/index.ae7c4106.css rel=preload as=style><link href=js/chunk-vendors.22b87709.js rel=preload as=script><link href=js/index.9af4c217.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/index.ae7c4106.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.22b87709.js></script><script src=js/index.9af4c217.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon-db.png><title>数据库文档管理</title><link href=css/chunk-vendors.8924efc6.css rel=preload as=style><link href=css/index.bb15836f.css rel=preload as=style><link href=js/chunk-vendors.c63802ce.js rel=preload as=script><link href=js/index.73fd47e8.js rel=preload as=script><link href=css/chunk-vendors.8924efc6.css rel=stylesheet><link href=css/index.bb15836f.css rel=stylesheet></head><body><noscript><strong>We're sorry but zyplayer-db-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.c63802ce.js></script><script src=js/index.73fd47e8.js></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
100
zyplayer-doc-db/src/main/resources/dist/js/chunk-vendors.c63802ce.js
vendored
Normal file
100
zyplayer-doc-db/src/main/resources/dist/js/chunk-vendors.c63802ce.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
zyplayer-doc-db/src/main/resources/dist/js/index.73fd47e8.js
vendored
Normal file
1
zyplayer-doc-db/src/main/resources/dist/js/index.73fd47e8.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -40,6 +40,10 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-ldap</artifactId>
|
||||
</dependency>
|
||||
<!-- 在线文档解析页面 -->
|
||||
<!--zyplayer-doc-core-->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.zyplayer.doc.manage.framework.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
|
||||
@Configurable
|
||||
public class LdapConfig {
|
||||
|
||||
String url = "ldap://10.0.1.1:10389";
|
||||
String base = "dc=xx,dc=net";
|
||||
String userDn = "cn=Manager,dc=xx,dc=net";
|
||||
String password = "MKDSHYDNIS";
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
@Bean
|
||||
public LdapTemplate getLdapTemplate() {
|
||||
LdapContextSource contextSource = new LdapContextSource();
|
||||
contextSource.setUrl(url);
|
||||
contextSource.setBase(base);
|
||||
contextSource.setUserDn(userDn);
|
||||
contextSource.setPassword(password);
|
||||
contextSource.setPooled(false);
|
||||
contextSource.afterPropertiesSet();
|
||||
return new LdapTemplate(contextSource);
|
||||
}
|
||||
}
|
||||
@@ -6,41 +6,75 @@ import com.zyplayer.doc.core.json.DocResponseJson;
|
||||
import com.zyplayer.doc.data.config.security.DocUserDetails;
|
||||
import com.zyplayer.doc.data.config.security.DocUserUtil;
|
||||
import com.zyplayer.doc.data.repository.manage.entity.UserInfo;
|
||||
import com.zyplayer.doc.data.service.manage.AuthInfoService;
|
||||
import com.zyplayer.doc.data.service.manage.UserAuthService;
|
||||
import com.zyplayer.doc.data.service.manage.UserInfoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import com.zyplayer.doc.manage.web.manage.param.LdapPerson;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.query.LdapQueryBuilder;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户登录控制器
|
||||
*/
|
||||
@RestController
|
||||
public class LoginController {
|
||||
|
||||
@Autowired
|
||||
private UserInfoService userInfoService;
|
||||
@Autowired
|
||||
private UserAuthService userAuthService;
|
||||
@Autowired
|
||||
private AuthInfoService authInfoService;
|
||||
|
||||
@Resource
|
||||
private UserInfoService userInfoService;
|
||||
@Resource
|
||||
private UserAuthService userAuthService;
|
||||
@Resource
|
||||
private LdapTemplate ldapTemplate;
|
||||
|
||||
// TODO 域账号登录,待测试
|
||||
@Value("${spring.ldap.domainName:}")
|
||||
private String ldapDomainName;
|
||||
@Value("${spring.ldap.urls:}")
|
||||
private String ldapUrls;
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*/
|
||||
@PostMapping(value = "/login")
|
||||
public DocResponseJson<Object> login(String username, String password, HttpServletResponse response) {
|
||||
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_no", username);
|
||||
queryWrapper.eq("del_flag", 0);
|
||||
UserInfo userInfo = userInfoService.getOne(queryWrapper);
|
||||
if (userInfo == null) {
|
||||
return DocResponseJson.warn("用户名'" + username + "'没有找到!");
|
||||
}
|
||||
String pwdMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
if (!Objects.equals(userInfo.getPassword(), pwdMd5)) {
|
||||
return DocResponseJson.warn("密码错误");
|
||||
// 如果使用域账号登录
|
||||
if (this.isUseLdapServer()) {
|
||||
LdapPerson ldapPerson = this.getUserFromLdap(username, password);
|
||||
if (null == ldapPerson) {
|
||||
return DocResponseJson.warn("用户名或密码错误");
|
||||
}
|
||||
if (userInfo == null) {
|
||||
userInfo = this.ldapAutoRegister(ldapPerson);
|
||||
}
|
||||
} else {
|
||||
if (userInfo == null) {
|
||||
return DocResponseJson.warn("用户名'" + username + "'没有找到!");
|
||||
}
|
||||
String pwdMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
if (!Objects.equals(userInfo.getPassword(), pwdMd5)) {
|
||||
return DocResponseJson.warn("用户名或密码错误");
|
||||
}
|
||||
}
|
||||
Set<String> userAuthSet = userAuthService.getUserAuthSet(userInfo.getId());
|
||||
String accessToken = RandomUtil.simpleUUID();
|
||||
@@ -52,7 +86,7 @@ public class LoginController {
|
||||
cookie.setDomain("zyplayer.com");
|
||||
cookie.setMaxAge(60 * 60 * 24);
|
||||
response.addCookie(cookie);
|
||||
// 再搞一份当前路劲的cookie
|
||||
// 再搞一份当前域名的cookie
|
||||
cookie = new Cookie("accessToken", accessToken);
|
||||
cookie.setPath("/");
|
||||
cookie.setMaxAge(60 * 60 * 24);
|
||||
@@ -60,9 +94,77 @@ public class LoginController {
|
||||
return DocResponseJson.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@PostMapping(value = "/logout")
|
||||
public DocResponseJson<Object> logout() {
|
||||
DocUserUtil.logout();
|
||||
return DocResponseJson.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 域账户注册
|
||||
*/
|
||||
private UserInfo ldapAutoRegister(LdapPerson ldapPerson) {
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setEmail(ldapPerson.getEmail());
|
||||
userInfo.setPassword("LDAP");
|
||||
userInfo.setUserName(ldapPerson.getName());
|
||||
userInfo.setUserNo(ldapPerson.getsAMAccountName());
|
||||
userInfo.setSex(1);
|
||||
userInfoService.save(userInfo);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用域账号登录
|
||||
*/
|
||||
public boolean isUseLdapServer() {
|
||||
return StringUtils.isNotEmpty(ldapUrls);
|
||||
}
|
||||
|
||||
/**
|
||||
* 鉴别域账号中是否有该用户
|
||||
*/
|
||||
public LdapPerson getUserFromLdap(String username, String password) {
|
||||
if (StringUtils.endsWithIgnoreCase(username, ldapDomainName)) {
|
||||
username = username.replaceAll("(?i)" + ldapDomainName, "");
|
||||
}
|
||||
String userDn = username + ldapDomainName;
|
||||
DirContext dirContext = null;
|
||||
try {
|
||||
dirContext = ldapTemplate.getContextSource().getContext(userDn, password);
|
||||
List<LdapPerson> search = ldapTemplate.search(
|
||||
LdapQueryBuilder.query().where("objectClass").is("person").and("sAMAccountName").is(username),
|
||||
(AttributesMapper<LdapPerson>) attributes -> {
|
||||
LdapPerson person = new LdapPerson();
|
||||
person.setName(this.getAttributeValue(attributes.get("cn")));
|
||||
person.setsAMAccountName(this.getAttributeValue(attributes.get("sAMAccountName")));
|
||||
person.setEmail(this.getAttributeValue(attributes.get("userPrincipalName")));
|
||||
return person;
|
||||
});
|
||||
if (CollectionUtils.isNotEmpty(search)) {
|
||||
return search.get(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (null != dirContext) {
|
||||
LdapUtils.closeContext(dirContext);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取值
|
||||
*/
|
||||
private String getAttributeValue(Attribute attribute) throws NamingException {
|
||||
if (attribute != null) {
|
||||
Object obj = attribute.get(0);
|
||||
return obj == null ? null : obj.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* <<
|
||||
* Davinci
|
||||
* ==
|
||||
* Copyright (C) 2016 - 2019 EDP
|
||||
* ==
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* >>
|
||||
*
|
||||
*/
|
||||
|
||||
package com.zyplayer.doc.manage.web.manage.param;
|
||||
|
||||
|
||||
public class LdapPerson {
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String sAMAccountName;
|
||||
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getsAMAccountName() {
|
||||
return sAMAccountName;
|
||||
}
|
||||
|
||||
public void setsAMAccountName(String sAMAccountName) {
|
||||
this.sAMAccountName = sAMAccountName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public LdapPerson(String name, String sAMAccountName, String email) {
|
||||
this.name = name;
|
||||
this.sAMAccountName = sAMAccountName;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public LdapPerson() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
# VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
# VUE_APP_BASE_API = 'http://local.zyplayer.com:8083/zyplayer-doc-manage'
|
||||
VUE_APP_BASE_API = 'http://doc.zyplayer.com/zyplayer-doc-manage'
|
||||
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||
|
||||
|
||||
75
zyplayer-doc-ui/db-ui/package-lock.json
generated
75
zyplayer-doc-ui/db-ui/package-lock.json
generated
@@ -4,6 +4,27 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@antv/x6": {
|
||||
"version": "1.25.0",
|
||||
"resolved": "https://registry.nlark.com/@antv/x6/download/@antv/x6-1.25.0.tgz?cache=0&sync_timestamp=1627353635830&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40antv%2Fx6%2Fdownload%2F%40antv%2Fx6-1.25.0.tgz",
|
||||
"integrity": "sha1-/0nd5n3OIP2EFOHd8luJPOEqdZk=",
|
||||
"requires": {
|
||||
"csstype": "^3.0.3",
|
||||
"jquery": "^3.5.1",
|
||||
"jquery-mousewheel": "^3.1.13",
|
||||
"lodash-es": "^4.17.15",
|
||||
"mousetrap": "^1.6.5",
|
||||
"utility-types": "^3.10.0"
|
||||
}
|
||||
},
|
||||
"@antv/x6-vue-shape": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.nlark.com/@antv/x6-vue-shape/download/@antv/x6-vue-shape-1.2.8.tgz",
|
||||
"integrity": "sha1-4XXUmNvSOM/oRVJnQlOinUpggs8=",
|
||||
"requires": {
|
||||
"vue-demi": "^0.7.4"
|
||||
}
|
||||
},
|
||||
"@babel/code-frame": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.5.5.tgz",
|
||||
@@ -1482,6 +1503,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/composition-api": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.nlark.com/@vue/composition-api/download/@vue/composition-api-1.0.4.tgz",
|
||||
"integrity": "sha1-YWKzujBqiZWv3Olppm4WjmdDcY0=",
|
||||
"requires": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.nlark.com/tslib/download/tslib-2.3.0.tgz",
|
||||
"integrity": "sha1-gDuM2rPhK6WBpMpByIObuw2ssJ4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/preload-webpack-plugin": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.1.tgz",
|
||||
@@ -3608,6 +3644,11 @@
|
||||
"css-tree": "1.0.0-alpha.37"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.nlark.com/csstype/download/csstype-3.0.8.tgz",
|
||||
"integrity": "sha1-0iZqeScp+yJ80hb7Vy9Dco4a00A="
|
||||
},
|
||||
"current-script-polyfill": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/current-script-polyfill/download/current-script-polyfill-1.0.0.tgz",
|
||||
@@ -4039,7 +4080,7 @@
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz",
|
||||
"resolved": "http://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz",
|
||||
"integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -5868,7 +5909,7 @@
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz",
|
||||
"resolved": "http://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz",
|
||||
"integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6481,6 +6522,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npm.taobao.org/jquery/download/jquery-3.6.0.tgz?cache=0&sync_timestamp=1614706801583&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjquery%2Fdownload%2Fjquery-3.6.0.tgz",
|
||||
"integrity": "sha1-xyoJ8Vwb3OFC9J2/EXC9+K2sJHA="
|
||||
},
|
||||
"jquery-mousewheel": {
|
||||
"version": "3.1.13",
|
||||
"resolved": "https://registry.nlark.com/jquery-mousewheel/download/jquery-mousewheel-3.1.13.tgz",
|
||||
"integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU="
|
||||
},
|
||||
"js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npm.taobao.org/js-cookie/download/js-cookie-2.2.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-cookie%2Fdownload%2Fjs-cookie-2.2.1.tgz",
|
||||
@@ -6884,6 +6935,11 @@
|
||||
"resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz",
|
||||
"integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.nlark.com/lodash-es/download/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha1-Q+YmxG5lkbd1C+srUBFzkMYJ4+4="
|
||||
},
|
||||
"lodash.defaultsdeep": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npm.taobao.org/lodash.defaultsdeep/download/lodash.defaultsdeep-4.6.1.tgz",
|
||||
@@ -7308,6 +7364,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"mousetrap": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.nlark.com/mousetrap/download/mousetrap-1.6.5.tgz",
|
||||
"integrity": "sha1-inZtjCcrCDk9X1YHTgtewYNIW/k="
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
|
||||
@@ -10720,6 +10781,11 @@
|
||||
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
|
||||
"dev": true
|
||||
},
|
||||
"utility-types": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.nlark.com/utility-types/download/utility-types-3.10.0.tgz",
|
||||
"integrity": "sha1-6kFI+adBAV8F7XT9YV4dIOa+2Cs="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
|
||||
@@ -10789,6 +10855,11 @@
|
||||
"clipboard": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"vue-demi": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.nlark.com/vue-demi/download/vue-demi-0.7.5.tgz",
|
||||
"integrity": "sha1-iN7nSS/Jmg+RH/A/wCxlj6Knmvg="
|
||||
},
|
||||
"vue-hljs": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-hljs/download/vue-hljs-1.1.2.tgz",
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"build": "vue-cli-service build --mode production"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/x6": "^1.25.0",
|
||||
"@antv/x6-vue-shape": "^1.1.6",
|
||||
"@vue/composition-api": "^1.0.4",
|
||||
"axios": "^0.19.0",
|
||||
"brace": "^0.11.1",
|
||||
"codemirror": "^5.61.1",
|
||||
|
||||
26
zyplayer-doc-ui/db-ui/src/components/er/ERGraph/index.less
Normal file
26
zyplayer-doc-ui/db-ui/src/components/er/ERGraph/index.less
Normal file
@@ -0,0 +1,26 @@
|
||||
.er-editor-demo-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fafafa;
|
||||
|
||||
.minimap-container {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
|
||||
/** X6推荐覆写样式 */
|
||||
.x6-widget-minimap {
|
||||
.x6-graph {
|
||||
box-shadow: 0 0 0 0 #ffffff;
|
||||
}
|
||||
|
||||
.x6-widget-minimap-viewport {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
|
||||
.x6-widget-minimap-viewport-zoom {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
zyplayer-doc-ui/db-ui/src/components/er/ERGraph/index.vue
Normal file
88
zyplayer-doc-ui/db-ui/src/components/er/ERGraph/index.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class="er-editor-demo-container">
|
||||
<div
|
||||
id="refContainer"
|
||||
ref="refContainer"
|
||||
style="width: 100%; height: 100%"/>
|
||||
<div id="refMinimapContainer" ref="refMinimapContainer" class="minimap-container" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import './index.less'
|
||||
import { BaseGraph } from '../xflow/index' // GraphData, GraphOptions
|
||||
|
||||
export default {
|
||||
name: 'index',
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
graphOptions: {
|
||||
type: Object,
|
||||
default: null,
|
||||
required: false
|
||||
},
|
||||
graphData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// graphContainer: document.getElementById('refContainer'),
|
||||
// minimapContainer: document.getElementById('refMinimapContainer'),
|
||||
baseGraph: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const that = this
|
||||
|
||||
setTimeout(() => {
|
||||
/** 初始化画布 */
|
||||
this.baseGraph = new BaseGraph({
|
||||
...this.graphOptions,
|
||||
container: document.getElementById('refContainer'),
|
||||
grid: {
|
||||
visible: false
|
||||
},
|
||||
minimap: {
|
||||
enabled: true,
|
||||
container: document.getElementById('refMinimapContainer'),
|
||||
minScale: 0.5,
|
||||
maxScale: 2
|
||||
}
|
||||
})
|
||||
/** 渲染画布内容 */
|
||||
this.baseGraph.updateGraph(that.graphData)
|
||||
}, 100)
|
||||
},
|
||||
methods: {
|
||||
onHandleToolbar (action) {
|
||||
switch (action) {
|
||||
case 'in':
|
||||
console.log('in')
|
||||
this.baseGraph.zoomGraph(0.1)
|
||||
break
|
||||
case 'out':
|
||||
console.log('out')
|
||||
this.baseGraph.zoomGraph(-0.1)
|
||||
break
|
||||
case 'fit':
|
||||
console.log('fit')
|
||||
this.baseGraph.zoomGraph('fit')
|
||||
break
|
||||
case 'real':
|
||||
console.log('real')
|
||||
this.baseGraph.zoomGraph('real')
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
113
zyplayer-doc-ui/db-ui/src/components/er/ERGraphDemo/Entity.less
Normal file
113
zyplayer-doc-ui/db-ui/src/components/er/ERGraphDemo/Entity.less
Normal file
@@ -0,0 +1,113 @@
|
||||
.entity-container {
|
||||
width: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
border-radius: 2px;
|
||||
background-color: white;
|
||||
|
||||
&.fact {
|
||||
border: 1px solid #ced4de;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.dim {
|
||||
border: 1px solid #cdddfd;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.other {
|
||||
border: 1px solid #decfea;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 1px 1px;
|
||||
width: calc(100% - 2px);
|
||||
height: calc(100% - 2px);
|
||||
display:block;
|
||||
|
||||
&.fact {
|
||||
background-color: #ced4de;
|
||||
}
|
||||
|
||||
&.dim {
|
||||
background-color: #cdddfd;
|
||||
}
|
||||
|
||||
&.other {
|
||||
background-color: #decfea;
|
||||
}
|
||||
|
||||
.head {
|
||||
width: calc(100% - 12px);
|
||||
height: 38px;
|
||||
margin-left: 6px;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.type {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.more {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
width: calc(100% - 12px);
|
||||
height: calc(100% - 36px - 6px);
|
||||
margin-left: 6px;
|
||||
margin-bottom: 6px;
|
||||
background-color: white;
|
||||
overflow: auto;
|
||||
cursor: pointer;
|
||||
|
||||
//float:clear;
|
||||
|
||||
.body-item {
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
color: #595959;
|
||||
border-bottom: 1px solid rgba(206, 212, 222, 0.2);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.name {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-left: 6px;
|
||||
|
||||
.pk,
|
||||
.fk {
|
||||
width: 12px;
|
||||
font-family: HelveticaNeue-CondensedBold;
|
||||
color: #ffd666;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.type {
|
||||
color: #bfbfbf;
|
||||
font-size: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="entity-container fact">
|
||||
<div class="content other">
|
||||
<div class="head">
|
||||
<div>
|
||||
<a-icon type="bars" class="type"/>
|
||||
<span>{{ entity.name }}</span>
|
||||
</div>
|
||||
<a-icon type="ellipsis" class="more" />
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
|
||||
<div class="body-item" v-for="(item,index) in entity.properties" :key="index">
|
||||
<div class="name">
|
||||
<!-- {{ value.isPK }} && <span class="pk">PK</span>-->
|
||||
<!-- {{value.isFK }} && <span class="fk">FK</span>-->
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="type">{{ item.propertyType }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import './Entity.less'
|
||||
export default {
|
||||
name: 'Entity',
|
||||
props: {
|
||||
entity: {
|
||||
type: Object,
|
||||
default: null,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.log(this.entity, 'this.entity')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div style="width: 100%; height: 650px">
|
||||
<ERGraph :graphData="graphData"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import ERGraph from '../ERGraph'
|
||||
import { mockEntityData, mockRelationData } from './mock'
|
||||
import Entity from './Entity'
|
||||
export default {
|
||||
name: 'index',
|
||||
components: {
|
||||
ERGraph
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
graphData: {
|
||||
nodes: '',
|
||||
edges: ''
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.calRenderData()
|
||||
},
|
||||
methods: {
|
||||
calRenderData () {
|
||||
this.graphData.nodes = mockEntityData.map((entity) => {
|
||||
const { entityId, x, y, width, height } = entity
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
id: entityId,
|
||||
component: {
|
||||
template: '<Entity :entity="entity"/>',
|
||||
data () {
|
||||
return {
|
||||
entity: entity
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Entity
|
||||
}
|
||||
}
|
||||
// data: entity
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
this.graphData.edges = mockRelationData.map((relation) => {
|
||||
const { relationId, sourceEntityId, targetEntityId } = relation
|
||||
return {
|
||||
id: relationId,
|
||||
source: sourceEntityId,
|
||||
target: targetEntityId,
|
||||
label: '1:N',
|
||||
// render: (data: RelationCanvasModel) => {
|
||||
// return null;
|
||||
// },
|
||||
data: relation
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
193
zyplayer-doc-ui/db-ui/src/components/er/ERGraphDemo/mock.js
Normal file
193
zyplayer-doc-ui/db-ui/src/components/er/ERGraphDemo/mock.js
Normal file
@@ -0,0 +1,193 @@
|
||||
// import {
|
||||
// EntityProperty,
|
||||
// EntityCanvasModel,
|
||||
// RelationCanvasModel
|
||||
// } from './interface'
|
||||
// : EntityProperty[]
|
||||
export const mockProperties = [
|
||||
{
|
||||
propertyId: 'propertyId1',
|
||||
name: '业务日期',
|
||||
propertyType: 'string',
|
||||
isPK: true
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId2',
|
||||
name: '交易号1',
|
||||
propertyType: 'bigint',
|
||||
isFK: true
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId3',
|
||||
name: '最长显示的表单名最长显示的表单名',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId4',
|
||||
name: '交易支付外键',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId5',
|
||||
name: '卖家支付日期',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId6',
|
||||
name: '网商银行',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId7',
|
||||
name: '业务日期',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId8',
|
||||
name: '业务日期111',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId9',
|
||||
name: '业务日期222',
|
||||
propertyType: 'string'
|
||||
},
|
||||
{
|
||||
propertyId: 'propertyId10',
|
||||
name: '业务日期333',
|
||||
propertyType: 'string'
|
||||
}
|
||||
]
|
||||
// : EntityCanvasModel[]
|
||||
export const mockEntityData = [
|
||||
{
|
||||
entityId: 'fact_1',
|
||||
name: '事实表',
|
||||
entityType: 'FACT',
|
||||
properties: mockProperties,
|
||||
x: 550,
|
||||
y: 400,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'fact_up',
|
||||
name: '事实表',
|
||||
entityType: 'FACT',
|
||||
properties: mockProperties,
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'dim_up',
|
||||
name: '维度表',
|
||||
entityType: 'DIM',
|
||||
properties: mockProperties,
|
||||
x: 100,
|
||||
y: 400,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'other_up',
|
||||
name: '其他表',
|
||||
entityType: 'OTHER',
|
||||
properties: mockProperties,
|
||||
x: 100,
|
||||
y: 700,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'other_down',
|
||||
name: '其他表',
|
||||
entityType: 'OTHER',
|
||||
properties: mockProperties,
|
||||
x: 900,
|
||||
y: 0,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'fact_down1',
|
||||
name: '事实表',
|
||||
entityType: 'FACT',
|
||||
properties: mockProperties,
|
||||
x: 900,
|
||||
y: 280,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'dim_down',
|
||||
name: '维度表',
|
||||
entityType: 'DIM',
|
||||
properties: mockProperties,
|
||||
x: 900,
|
||||
y: 580,
|
||||
width: 214,
|
||||
height: 248
|
||||
},
|
||||
{
|
||||
entityId: 'fact_down2',
|
||||
name: '事实表',
|
||||
entityType: 'FACT',
|
||||
properties: mockProperties,
|
||||
x: 900,
|
||||
y: 860,
|
||||
width: 214,
|
||||
height: 248
|
||||
}
|
||||
]
|
||||
|
||||
// : RelationCanvasModel[]
|
||||
|
||||
export const mockRelationData = [
|
||||
{
|
||||
relationId: 'relationId_1',
|
||||
sourceEntityId: 'fact_up',
|
||||
targetEntityId: 'fact_1'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_2',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'fact_up'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_1_loop',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'fact_1'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_2',
|
||||
sourceEntityId: 'dim_up',
|
||||
targetEntityId: 'fact_1'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_3',
|
||||
sourceEntityId: 'other_up',
|
||||
targetEntityId: 'fact_1'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_4',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'other_down'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_5',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'fact_down1'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_6',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'dim_down'
|
||||
},
|
||||
{
|
||||
relationId: 'relationId_7',
|
||||
sourceEntityId: 'fact_1',
|
||||
targetEntityId: 'fact_down2'
|
||||
}
|
||||
]
|
||||
5
zyplayer-doc-ui/db-ui/src/components/er/index.less
Normal file
5
zyplayer-doc-ui/db-ui/src/components/er/index.less
Normal file
@@ -0,0 +1,5 @@
|
||||
.erGraphDemo {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
46
zyplayer-doc-ui/db-ui/src/components/er/index.vue
Normal file
46
zyplayer-doc-ui/db-ui/src/components/er/index.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="styles.erGraphDemo">
|
||||
<ERGraphDemo />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import styles from './index.less'
|
||||
import ERGraphDemo from './ERGraphDemo'
|
||||
export default {
|
||||
name: 'index',
|
||||
components: {
|
||||
ERGraphDemo
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
graph: '',
|
||||
styles: styles
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
showDrawer () {
|
||||
// setTimeout(() => {
|
||||
// this.initGraph()
|
||||
// }, 100)
|
||||
this.visible = true
|
||||
},
|
||||
|
||||
onClose () {
|
||||
// this.graph.dispose()
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
87
zyplayer-doc-ui/db-ui/src/components/er/index2.vue
Normal file
87
zyplayer-doc-ui/db-ui/src/components/er/index2.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div style="padding: 10px;">
|
||||
<div ref="graphContainer"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Graph} from '@antv/x6';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
graphData: {
|
||||
// 节点
|
||||
nodes: [
|
||||
{
|
||||
id: 'node1', // String,可选,节点的唯一标识
|
||||
x: 40, // Number,必选,节点位置的 x 值
|
||||
y: 40, // Number,必选,节点位置的 y 值
|
||||
width: 80, // Number,可选,节点大小的 width 值
|
||||
height: 40, // Number,可选,节点大小的 height 值
|
||||
label: 'hello', // String,节点标签
|
||||
},
|
||||
{
|
||||
id: 'node2', // String,节点的唯一标识
|
||||
x: 160, // Number,必选,节点位置的 x 值
|
||||
y: 180, // Number,必选,节点位置的 y 值
|
||||
width: 80, // Number,可选,节点大小的 width 值
|
||||
height: 40, // Number,可选,节点大小的 height 值
|
||||
label: 'world', // String,节点标签
|
||||
},
|
||||
],
|
||||
// 边
|
||||
edges: [
|
||||
{
|
||||
source: 'node1', // String,必须,起始节点 id
|
||||
target: 'node2', // String,必须,目标节点 id
|
||||
},
|
||||
],
|
||||
},
|
||||
graph: {},
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.graph = new Graph({
|
||||
container: this.$refs.graphContainer,
|
||||
height: 600,
|
||||
scroller: {
|
||||
enabled: true,
|
||||
pannable: true,
|
||||
pageBreak: false,
|
||||
},
|
||||
grid: {
|
||||
size: 10,
|
||||
visible: true
|
||||
}
|
||||
});
|
||||
this.graph.fromJSON(this.graphData);
|
||||
this.graph.centerContent();
|
||||
},
|
||||
methods: {
|
||||
addNode(){
|
||||
this.graph.createNode({
|
||||
shape: 'org-node',
|
||||
attrs: {
|
||||
'.card': { fill: background },
|
||||
'.image': { xlinkHref: image },
|
||||
'.rank': {
|
||||
fill: textColor,
|
||||
text: Dom.breakText(rank, { width: 160, height: 45 }),
|
||||
},
|
||||
'.name': {
|
||||
fill: textColor,
|
||||
text: Dom.breakText(name, { width: 160, height: 45 }),
|
||||
},
|
||||
'.btn > circle': { stroke: textColor },
|
||||
'.btn > text': { fill: textColor, stroke: textColor },
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
// import { Graph } from '@antv/x6'
|
||||
import { Edge } from '@antv/x6'
|
||||
// !!!!!!!!!!!!!!!
|
||||
// import '@antv/x6-react-shape'
|
||||
// import X6BaseGraph from '../graph/baseGraph'
|
||||
// import Node from '../graph/node'
|
||||
// import Edge from '../graph/edge'
|
||||
// import { NodeConfig, EdgeConfig } from '../interface/graph-core'
|
||||
import _ from 'lodash'
|
||||
import '@antv/x6-vue-shape'
|
||||
const x6VueShape = 'vue-shape'
|
||||
|
||||
export default class CellController {
|
||||
// private graph: Graph;
|
||||
//
|
||||
// /** 记录画布中的节点 */
|
||||
// public nodes: Node[] = [];
|
||||
// /** 记录画布中的连线 */
|
||||
// public edges: Edge[] = [];
|
||||
|
||||
constructor (x6BaseGraph) {
|
||||
this.graph = x6BaseGraph.graph
|
||||
/** 记录画布中的节点 */
|
||||
this.nodes = []
|
||||
/** 记录画布中的连线 */
|
||||
this.edges = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加节点
|
||||
* @template T
|
||||
* @param {T[]} nodesData 节点数据集合
|
||||
* @memberof CellController
|
||||
*/
|
||||
addNodes (nodesData) {
|
||||
nodesData.forEach((nodeData) => {
|
||||
this.addNode(nodeData)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单个节点
|
||||
* @template T
|
||||
* @param {T} nodeData 节点数据
|
||||
* @memberof CellController
|
||||
*/
|
||||
addNode (nodeData) {
|
||||
console.log(nodeData, 'nodeData')
|
||||
const { id, x, y, width, height, component, data, ...rest } = nodeData
|
||||
const newNode = this.graph.addNode({
|
||||
id,
|
||||
x: x || 0,
|
||||
y: y || 0,
|
||||
width: width || 100,
|
||||
height: height || 60,
|
||||
// data: data || undefined,
|
||||
shape: x6VueShape,
|
||||
component: component,
|
||||
...rest
|
||||
})
|
||||
this.nodes.push(newNode)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新节点
|
||||
* @param {Node} node 节点实例
|
||||
* @param {NodeConfig} newNodeData 节点最新数据
|
||||
* @memberof CellController
|
||||
*/
|
||||
updateNode (node, newNodeData) {
|
||||
// !!! 现在仅支持data数据不一致才认为更新
|
||||
if (!_.isEqual(node.data, newNodeData.data)) {
|
||||
// 重设节点数据, 触发x6更新节点逻辑
|
||||
node.setData(newNodeData.data)
|
||||
// node.setPosition(newNodeData.x, newNodeData.y)
|
||||
// node.setSize(newNodeData.width, newNodeData.height)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除节点
|
||||
* @param {Node[]} removeNodes
|
||||
* @memberof CellController
|
||||
*/
|
||||
removeNodes (removeNodes) {
|
||||
if (_.size(removeNodes) > 0) {
|
||||
this.graph.removeCells(removeNodes)
|
||||
this.nodes = _.pullAll(this.nodes, removeNodes)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个删除节点
|
||||
* @param {(Node | string)} node
|
||||
* @memberof CellController
|
||||
*/
|
||||
removeNode (removeNode) {
|
||||
if (!removeNode) {
|
||||
return
|
||||
}
|
||||
if (removeNode instanceof Node) {
|
||||
this.removeNodes([removeNode])
|
||||
} else {
|
||||
const findNode = this.findNodeById(removeNode)
|
||||
if (findNode) {
|
||||
this.removeNodes([findNode])
|
||||
}
|
||||
}
|
||||
// !!! 待补充: 删除节点时是否需要将与之关联的连线都删除, 这里可以加一个标记
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加连线
|
||||
* @template T
|
||||
* @param {T[]} edgesData 边数据集合
|
||||
* @memberof CellController
|
||||
*/
|
||||
addEdges (edgesData) {
|
||||
edgesData.forEach((edgeData) => {
|
||||
this.addEdge(edgeData)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单个连线
|
||||
* @template T
|
||||
* @param {T} edgeData 边数据
|
||||
* @memberof CellController
|
||||
*/
|
||||
addEdge (edgeData) {
|
||||
const { id, source, target, render, data, ...rest } = edgeData
|
||||
|
||||
const sourceNode = _.find(this.nodes, (node) => node.id === source)
|
||||
const targetNode = _.find(this.nodes, (node) => node.id === target)
|
||||
if (!source || !target) {
|
||||
throw new Error('edge must has source and target!')
|
||||
}
|
||||
|
||||
const newEdge = this.graph.addEdge({
|
||||
id: id || `${source}-${target}`,
|
||||
data: data || undefined,
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
// label: (edge: Edge) => {
|
||||
// return render && render(edge && edge.data)
|
||||
// },
|
||||
attrs: {
|
||||
line: {
|
||||
stroke: '#B4BDCF',
|
||||
strokeWidth: 1
|
||||
}
|
||||
},
|
||||
...rest
|
||||
})
|
||||
this.edges.push(newEdge)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新边
|
||||
* @param {Edge} edge 边实例
|
||||
* @param {EdgeConfig} newEdgeData 边最新数据
|
||||
* @memberof CellController
|
||||
*/
|
||||
updateEdge (edge, newEdgeData) {
|
||||
// !!! 现在仅支持data数据不一致才认为更新, 需要扩展
|
||||
if (!_.isEqual(edge.data, newEdgeData.data)) {
|
||||
edge.setData(newEdgeData.data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除边
|
||||
* @param {Edge[]} removeEdges
|
||||
* @memberof CellController
|
||||
*/
|
||||
removeEdges (removeEdges) {
|
||||
this.graph.removeCells(removeEdges)
|
||||
this.edges = _.pullAll(this.edges, removeEdges)
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个删除边
|
||||
* @param {(Edge | string)} removeEdge
|
||||
* @memberof CellController
|
||||
*/
|
||||
removeEdge (removeEdge) {
|
||||
if (!removeEdge) {
|
||||
return
|
||||
}
|
||||
if (removeEdge instanceof Edge) {
|
||||
this.graph.removeCells([removeEdge])
|
||||
this.removeEdges([removeEdge])
|
||||
} else {
|
||||
const findEdge = this.findEdgeById(removeEdge)
|
||||
if (findEdge) {
|
||||
this.removeEdges([findEdge])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点id获取节点
|
||||
* @param {string} id 节点id
|
||||
* @returns {(Node | undefined)}
|
||||
* @memberof CellController
|
||||
*/
|
||||
findNodeById (id) {
|
||||
return this.nodes.find((node) => node.id === id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据连线id获取连线
|
||||
* @param {string} id 边id
|
||||
* @returns {(Edge | undefined)}
|
||||
* @memberof CellController
|
||||
*/
|
||||
findEdgeById (id) {
|
||||
return this.edges.find((edge) => edge.id === id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
// import { Graph } from '@antv/x6'
|
||||
// import X6BaseGraph from '../graph/baseGraph'
|
||||
// import { EventArg } from '../interface/graph-core'
|
||||
|
||||
export default class EventController {
|
||||
// private x6BaseGraph: X6BaseGraph;
|
||||
// private graph: Graph;
|
||||
//
|
||||
// // 是否删除X6自动生成的无实际业务含义的连线(用户在画布上拖拽生成连线, 这条连线是没有业务含义的)
|
||||
// private isDeleteX6DefaultEdge!: boolean;
|
||||
|
||||
constructor (x6BaseGraph) {
|
||||
this.x6BaseGraph = x6BaseGraph
|
||||
this.graph = x6BaseGraph.graph
|
||||
}
|
||||
|
||||
registerEvent = (events) => {
|
||||
events &&
|
||||
events.forEach((event) => {
|
||||
switch (event.eventName) {
|
||||
case 'scale': {
|
||||
this.graph.on('scale', ({ sx, sy, ox, oy }) => {
|
||||
const scale = sx
|
||||
event.handler && event.handler({ scale })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'graph:mouseenter': {
|
||||
this.graph.on('graph:mouseenter', ({ e }) => {
|
||||
event.handler && event.handler()
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'graph:mouseleave': {
|
||||
this.graph.on('graph:mouseleave', ({ e }) => {
|
||||
event.handler && event.handler()
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'blank:mouseDown': {
|
||||
this.graph.on('blank:mousedown', ({ e, x, y }) => {
|
||||
event.handler && event.handler({ x, y })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'blank:mouseUp': {
|
||||
this.graph.on('blank:mouseup', ({ e, x, y }) => {
|
||||
event.handler && event.handler({ x, y })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:added': {
|
||||
this.graph.on('node:added', ({ node }) => {
|
||||
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
|
||||
// event.handler && event.handler({ node });
|
||||
// }
|
||||
this.x6BaseGraph.bringNodesToFront([node])
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:removed': {
|
||||
this.graph.on('node:removed', ({ node }) => {
|
||||
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
|
||||
// event.handler && event.handler({ node })
|
||||
// }
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'edge:added': {
|
||||
this.graph.on('edge:added', ({ edge }) => {
|
||||
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
|
||||
// event.handler && event.handler({ edge })
|
||||
// }
|
||||
// this.x6BaseGraph.bringCellsToBack([edge])
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'edge:removed': {
|
||||
this.graph.on('edge:removed', ({ edge }) => {
|
||||
if (this.isDeleteX6DefaultEdge) {
|
||||
|
||||
}
|
||||
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
|
||||
// event.handler && event.handler({ edge })
|
||||
// }
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:mousedown': {
|
||||
this.graph.on('node:mousedown', ({ e, view, x, y }) => {
|
||||
event.handler && event.handler({ node: view.cell, x, y })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:mousemove': {
|
||||
this.graph.on('node:mousemove', ({ e, view, x, y }) => {
|
||||
event.handler && event.handler({ node: view.cell, x, y })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:mouseup': {
|
||||
this.graph.on('node:mouseup', ({ e, view, x, y }) => {
|
||||
event.handler && event.handler({ node: view.cell, x, y })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:click': {
|
||||
this.graph.on('node:click', ({ view }) => {
|
||||
event.handler && event.handler({ node: view.cell })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'node:dbclick': {
|
||||
this.graph.on('node:dblclick', ({ view }) => {
|
||||
event.handler && event.handler({ node: view.cell })
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'edge:connected': {
|
||||
this.graph.on('edge:connected', ({ edge }) => {
|
||||
// if (!this.x6BaseGraph.isDataDrivenUpdate) {
|
||||
// // 拖拽连线过程中画布会出现一条连线, 该连线无实际业务含义, 需要删除
|
||||
// if (!edge.data && edge.id.toString().startsWith('cell-', 0)) {
|
||||
// this.isDeleteX6DefaultEdge = true;
|
||||
// this.graph.removeCells([edge]);
|
||||
// this.isDeleteX6DefaultEdge = false;
|
||||
// }
|
||||
// event.handler && event.handler({ edge });
|
||||
// }
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'selection:changed': {
|
||||
this.graph.on(
|
||||
'selection:changed',
|
||||
({ selected, removed, added }) => {
|
||||
event.handler && event.handler({ selected, removed, added })
|
||||
this.x6BaseGraph.bringCellsToFront(selected)
|
||||
}
|
||||
)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { default as CellController } from './cellController'
|
||||
export { default as EventController } from './eventController'
|
||||
|
||||
/** 更多独立功能控制器, 比如快捷方式、布局等 */
|
||||
267
zyplayer-doc-ui/db-ui/src/components/er/xflow/graph/baseGraph.js
Normal file
267
zyplayer-doc-ui/db-ui/src/components/er/xflow/graph/baseGraph.js
Normal file
@@ -0,0 +1,267 @@
|
||||
import { Graph } from '@antv/x6'
|
||||
// import Node from '../graph/node'
|
||||
// import Edge from '../graph/edge'
|
||||
import { CellController, EventController } from '../controller/index'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default class X6BaseGraph {
|
||||
// public graph!: Graph;
|
||||
// public cellController!: CellController;
|
||||
// public eventController!: EventController;
|
||||
|
||||
constructor (graphOptions) {
|
||||
/** 创建X6画布实例 */
|
||||
const defaultCfg = this.getDefaultCfg()
|
||||
this.graph = new Graph({
|
||||
...defaultCfg,
|
||||
...graphOptions
|
||||
})
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
init () {
|
||||
this.cellController = new CellController(this)
|
||||
this.eventController = new EventController(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取画布默认配置项
|
||||
* @returns {Partial<GraphOptions>}
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
getDefaultCfg () {
|
||||
const defaultCfg = {
|
||||
/** 无限画布设置 */
|
||||
scroller: {
|
||||
enabled: true,
|
||||
pageVisible: false,
|
||||
pageBreak: false,
|
||||
pannable: true
|
||||
},
|
||||
/** 画布网格 */
|
||||
grid: {
|
||||
visible: true,
|
||||
size: 20,
|
||||
type: 'doubleMesh',
|
||||
args: [
|
||||
{
|
||||
color: '#888',
|
||||
thickness: 1
|
||||
}
|
||||
// {
|
||||
// color: '#ddd',
|
||||
// thickness: 1,
|
||||
// factor: 4,
|
||||
// },
|
||||
]
|
||||
},
|
||||
/** 全局连线配置 */
|
||||
// connecting: {
|
||||
// anchor: 'midSide',
|
||||
// router: {
|
||||
// name: 'er',
|
||||
// },
|
||||
// // connector: {
|
||||
// // name: 'smooth',
|
||||
// // },
|
||||
// },
|
||||
connecting: {
|
||||
connector: {
|
||||
name: 'rounded'
|
||||
},
|
||||
router: {
|
||||
name: 'er',
|
||||
args: {
|
||||
direction: 'H'
|
||||
}
|
||||
}
|
||||
},
|
||||
/** 对齐线 */
|
||||
snapline: {
|
||||
enabled: true
|
||||
},
|
||||
/** 滚轮缩放 */
|
||||
// mousewheel: {
|
||||
// enabled: true,
|
||||
// zoomAtMousePosition: false,
|
||||
// factor: 1.1,
|
||||
// },
|
||||
keyboard: {
|
||||
enabled: true
|
||||
},
|
||||
clipboard: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
return defaultCfg
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新画布内容
|
||||
* @param {GraphData} graphData 画布元素数据
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
updateGraph (graphData) {
|
||||
if (!graphData) {
|
||||
throw new Error('graphData must be defined first!')
|
||||
}
|
||||
const { addNodesData, addEdgesData } = this.graphContentDiff(graphData)
|
||||
|
||||
this.graph.batchUpdate('updateGraph', () => {
|
||||
if (addNodesData && addNodesData.length > 0) {
|
||||
this.cellController.addNodes(addNodesData)
|
||||
}
|
||||
if (addEdgesData && addEdgesData.length > 0) {
|
||||
this.cellController.addEdges(addEdgesData)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 画布缩放
|
||||
* @param {number} factor 缩放比例尺
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
zoomGraph (factor) {
|
||||
if (typeof factor === 'number') {
|
||||
this.graph.zoom(factor)
|
||||
} else if (factor === 'fit') {
|
||||
this.graph.zoomToFit({ padding: 12 })
|
||||
} else if (factor) {
|
||||
this.graph.scale(1)
|
||||
this.graph.centerContent()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动节点到画布中央
|
||||
* @param {(Node | string)} node
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
focusNodeToGraphCenter (node) {
|
||||
if (node instanceof Node) {
|
||||
this.graph.centerCell(node)
|
||||
} else {
|
||||
const temp = this.cellController.findNodeById(node)
|
||||
if (temp) {
|
||||
this.graph.centerCell(temp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Nodes置于画布最前方
|
||||
* @param {Node[]} nodes
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
bringNodesToFront (nodes) {
|
||||
nodes.forEach((node) => {
|
||||
node.toBack()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Nodes置于画布最后方
|
||||
* @param {Node[]} nodess
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
bringNodesToBack (nodes) {
|
||||
nodes.forEach((node) => {
|
||||
node.toBack()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空画布内容
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
clearGraph () {
|
||||
// todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册监听事件
|
||||
* @param {EventArg[]} events
|
||||
* @memberof X6BaseGraph
|
||||
*/
|
||||
registerEvent (events) {
|
||||
this.eventController.registerEvent(events)
|
||||
}
|
||||
|
||||
/** 画布内容Diff */
|
||||
graphContentDiff (graphData) {
|
||||
const { nodes: nodesData, edges: edgesData } = graphData
|
||||
|
||||
// 新增节点数据
|
||||
const addNodesData = []
|
||||
nodesData.forEach((nodeData) => {
|
||||
const findNode = this.cellController.findNodeById(nodeData.id)
|
||||
if (!findNode) {
|
||||
addNodesData.push(nodeData)
|
||||
}
|
||||
})
|
||||
|
||||
// 保持、更新、移除的节点
|
||||
const retainNodes = []
|
||||
const updateNodes = []
|
||||
const removeNodes = []
|
||||
this.cellController.nodes.forEach((node) => {
|
||||
const findNodeData = nodesData.find(
|
||||
(nodeData) => nodeData.id === node.id
|
||||
)
|
||||
if (!findNodeData) {
|
||||
removeNodes.push(node)
|
||||
} else {
|
||||
// !!! 目前仅支持节点data数据变化, 才认为更新
|
||||
if (_.isEqual(node.data, findNodeData.data)) {
|
||||
retainNodes.push(node)
|
||||
} else {
|
||||
updateNodes.push(node)
|
||||
this.cellController.updateNode(node, findNodeData)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 新增连线数据
|
||||
const addEdgesData = []
|
||||
edgesData.forEach((edgeData) => {
|
||||
if (!edgeData.id) {
|
||||
return
|
||||
}
|
||||
const findEdge = this.cellController.findEdgeById(edgeData.id)
|
||||
if (!findEdge) {
|
||||
addEdgesData.push(edgeData)
|
||||
}
|
||||
})
|
||||
|
||||
// 保持、更新、移除的连线
|
||||
const retainEdges = []
|
||||
const updateEdges = []
|
||||
const removeEdges = []
|
||||
this.cellController.edges.forEach((edge) => {
|
||||
const findEdgeData = edgesData.find(
|
||||
(edgeData) => edgeData.id === edge.id
|
||||
)
|
||||
if (!findEdgeData) {
|
||||
removeEdges.push(edge)
|
||||
} else {
|
||||
// !!! 目前仅支持连线data数据变化, 才认为更新
|
||||
if (_.isEqual(edge.data, findEdgeData.data)) {
|
||||
retainEdges.push(edge)
|
||||
} else {
|
||||
updateEdges.push(edge)
|
||||
this.cellController.updateEdge(edge, findEdgeData)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.cellController.removeNodes(removeNodes)
|
||||
this.cellController.removeEdges(removeEdges)
|
||||
|
||||
return {
|
||||
addNodesData,
|
||||
addEdgesData
|
||||
}
|
||||
}
|
||||
}
|
||||
7
zyplayer-doc-ui/db-ui/src/components/er/xflow/index.js
Normal file
7
zyplayer-doc-ui/db-ui/src/components/er/xflow/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/** 类型定义 */
|
||||
// export * from './interface/graph-core'
|
||||
|
||||
/** BaseGraph、Node、Edge */
|
||||
export { default as BaseGraph } from './graph/baseGraph'
|
||||
// export { default as Node } from './graph/node'
|
||||
// export { default as Edge } from './graph/edge'
|
||||
@@ -1,4 +1,5 @@
|
||||
import Home from './views/home/Home.vue'
|
||||
import Er from './views/home/Er.vue'
|
||||
|
||||
import UserLogin from './views/user/Login.vue'
|
||||
import UserMyInfo from './views/user/MyInfo.vue'
|
||||
@@ -45,6 +46,7 @@ let routes = [
|
||||
{path: '/data/transferData', name: '数据互导工具',component: DataTransferData},
|
||||
{path: '/data/dataPreview', name: '表数据预览',component: DataPreview},
|
||||
{path: '/user/myInfo', name: '我的信息',component: UserMyInfo},
|
||||
// {path: '/home/er', name: 'ER图测试',component: Er},
|
||||
]
|
||||
}, {
|
||||
path: '/user',
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
},
|
||||
executorSource: {},
|
||||
columnMap: {},
|
||||
primaryKeyColumn: {}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -200,9 +201,13 @@
|
||||
}
|
||||
this.pageParam = param;
|
||||
this.executorSource = {sourceId: param.sourceId, dbName: param.dbName, tableName: param.tableName};
|
||||
let columnMap = {};
|
||||
columnList.forEach(item => columnMap[item.name] = item);
|
||||
this.columnMap = columnMap;
|
||||
this.columnMap = {};
|
||||
columnList.forEach(item => {
|
||||
this.columnMap[item.name] = item;
|
||||
if (item.primaryKey == 1) {
|
||||
this.primaryKeyColumn = item;
|
||||
}
|
||||
});
|
||||
this.doExecutorSqlCommon();
|
||||
// this.vueQueryParam = to.query;
|
||||
// let newName = {key: this.$route.fullPath, val: '数据-'+this.vueQueryParam.tableName};
|
||||
@@ -267,6 +272,7 @@
|
||||
conditionSql = conditionSql || "";
|
||||
this.executeError = "";
|
||||
this.executeUseTime = "";
|
||||
this.choiceResultObj = {};
|
||||
this.executeResultList = [];
|
||||
this.tableMaxHeight = document.body.clientHeight - 420;
|
||||
this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000);
|
||||
@@ -368,14 +374,19 @@
|
||||
handleCopyCheckLineCommand(type) {
|
||||
let choiceData = this.choiceResultObj[this.executeShowTable] || [];
|
||||
if (choiceData.length > 0) {
|
||||
this.conditionDataColsChoice = [];
|
||||
let dataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||
if (type === 'update') {
|
||||
// 选择更新的条件列
|
||||
this.conditionDataCols = dataCols;
|
||||
this.exportConditionVisible = true;
|
||||
return;
|
||||
if (!!this.primaryKeyColumn.name) {
|
||||
this.conditionDataColsChoice = [this.primaryKeyColumn.name];
|
||||
} else {
|
||||
// 没有主键的时候,选择更新的条件列
|
||||
this.conditionDataCols = dataCols;
|
||||
this.exportConditionVisible = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
let copyData = copyFormatter.format(type, this.pageParam.dbType, dataCols, choiceData, '', this.pageParam.dbName, this.pageParam.tableName);
|
||||
let copyData = copyFormatter.format(type, this.pageParam.dbType, dataCols, choiceData, this.conditionDataColsChoice, this.pageParam.dbName, this.pageParam.tableName);
|
||||
this.$copyText(copyData).then(
|
||||
res => this.$message.success("内容已复制到剪切板!"),
|
||||
err => this.$message.error("抱歉,复制失败!")
|
||||
@@ -403,9 +414,15 @@
|
||||
this.downloadDataVisible = false;
|
||||
},
|
||||
downloadTableData() {
|
||||
let dataRes = this.executeResultList.find(item => item.name === this.executeShowTable);
|
||||
if (!dataRes || !dataRes.dataList || dataRes.dataList.length <= 0) {
|
||||
this.$message.warning("当前筛选条件下无数据,请重新筛选后再操作导出");
|
||||
return;
|
||||
}
|
||||
this.downloadDataParam.conditionArr = [];
|
||||
this.conditionDataCols = this.executeResultList.find(item => item.name === this.executeShowTable).dataCols;
|
||||
this.conditionDataCols = dataRes.dataCols;
|
||||
this.downloadDataVisible = true;
|
||||
|
||||
},
|
||||
dropTableFlagChange() {
|
||||
if (this.downloadDataParam.dropTableFlag === 1) {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
export default {
|
||||
insert(dataCols, choiceData, dbName, tableName) {
|
||||
let tableNameRes = (!!dbName) ? '`' + dbName + '`.`' : '';
|
||||
tableNameRes += (!!tableName) ? tableName : '`table`';
|
||||
let tableNameRes = (!!dbName) ? dbName + '.' : '';
|
||||
tableNameRes += (!!tableName) ? tableName : 'table';
|
||||
// 复制为insert语句
|
||||
let copyData = '';
|
||||
let names = '';
|
||||
@@ -31,8 +31,8 @@ export default {
|
||||
return copyData;
|
||||
},
|
||||
update(dataCols, choiceData, condition=[], dbName, tableName) {
|
||||
let tableNameRes = (!!dbName) ? '`' + dbName + '`.`' : '';
|
||||
tableNameRes += (!!tableName) ? tableName : '`table`';
|
||||
let tableNameRes = (!!dbName) ? dbName + '.' : '';
|
||||
tableNameRes += (!!tableName) ? tableName : 'table';
|
||||
// 复制为update语句
|
||||
let copyData = '';
|
||||
choiceData.forEach(item => {
|
||||
|
||||
20
zyplayer-doc-ui/db-ui/src/views/home/Er.vue
Normal file
20
zyplayer-doc-ui/db-ui/src/views/home/Er.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div style="padding: 10px;">
|
||||
<er-graph></er-graph>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import erGraph from '../../components/er/index'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
components: {erGraph},
|
||||
mounted() {
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<div style="padding: 10px;">
|
||||
<div style="max-width: 1200px;margin: 20px auto;">
|
||||
<div style="text-align: center;">欢迎使用ヾ(๑╹◡╹)ノ" - 在左上角选择一个数据源吧~</div>
|
||||
<div style="text-align: center;">欢迎使用<span @dblclick="showErGraph">ヾ(๑╹◡╹)ノ"</span> - 在左上角选择一个数据源吧~</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var app;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
app = this;
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
showErGraph() {
|
||||
// this.$router.push({path: '/home/er'});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -16,5 +16,7 @@ module.exports = {
|
||||
template: 'public/index.html',
|
||||
filename: process.env.NODE_ENV === 'production'?'doc-db.html':'index.html',
|
||||
},
|
||||
}
|
||||
},
|
||||
// 在项目配置的时候,默认 npm 包导出的是运行时构建,即 runtime 版本,不支持编译 template 模板。
|
||||
runtimeCompiler: true
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user