This commit is contained in:
liwen
2020-10-28 16:36:50 +08:00
commit 5b8021007c
262 changed files with 32530 additions and 0 deletions

65
.gitignore vendored Normal file
View File

@@ -0,0 +1,65 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
# OS generated files #
######################
.DS_Store*
ehthumbs.db
Thumbs.db
# Editor Files #
################
*~
*.swp
# Build output directies
/target
**/test-output
**/target
**/bin
build
*/build
.m2
# IntelliJ specific files/directories
out
.idea
*.ipr
*.iws
*.iml
atlassian-ide-plugin.xml
# Eclipse specific files/directories
.classpath
.project
.settings
.metadata
.factorypath
.generated
#font
*.ttc

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,2 @@
#Sat Jul 11 23:56:44 CST 2020
gradle.version=6.4.1

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

6
README.md Normal file
View File

@@ -0,0 +1,6 @@
<<<<<<< HEAD
#ipsm-sced
=======
# fx-falsework
基于javafx、spring boot 开发的客户端与服务端系统开发脚手架
>>>>>>> 81a2173cfca6f001994b84cf6f6997432fea415d

16
build.gradle Normal file
View File

@@ -0,0 +1,16 @@
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}

50
client/build.gradle Normal file
View File

@@ -0,0 +1,50 @@
plugins {
id 'java'
}
group 'org.epri.fx.client'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation project(':server')
// implementation 'com.jfoenix:jfoenix:8.0.10'
// compile 'com.airhacks:afterburner.fx:1.7.0'
compile 'de.jensd:fontawesomefx:8.9'
compile 'org.apache.lucene:lucene-core:7.4.0'
compile 'org.apache.lucene:lucene-grouping:7.4.0'
compile 'org.apache.lucene:lucene-queryparser:7.4.0'
compile 'dom4j:dom4j:1.6.1'
compile 'org.controlsfx:controlsfx:8.40.17'
compile group: 'org.javassist', name: 'javassist', version: '3.18.1-GA'
compile group: 'com.guigarage', name: 'observable-toogles', version: '0.1'
compile group: 'javax.inject', name: 'javax.inject', version: '1'
compile files('libs/datafx-injection-8.0.2-SNAPSHOT.jar')
compile files('libs/datafx-eventsystem-8.0.2-SNAPSHOT.jar')
compile files('libs/datafx-core-8.0.2-SNAPSHOT.jar')
compile files('libs/datafx-flow-8.0.2-SNAPSHOT.jar')
compile files('libs/jfoenix-8.0.10.jar')
compile files('libs/pinyin4j-2.5.0.jar')
compile files('libs/tilesfx-1.6.8.jar')
compile 'org.kordamp.ikonli:ikonli-javafx:2.4.0'
compile 'org.kordamp.ikonli:ikonli-fontawesome5-pack:2.4.0'
compile 'io.github.openfeign:feign-core:10.9'
compile 'io.github.openfeign:feign-okhttp:10.9'
compile 'io.github.openfeign:feign-jackson:10.9'
compile 'io.github.openfeign:feign-hystrix:10.9'
compile 'io.github.openfeign:feign-ribbon:10.9'
compile 'io.github.openfeign:feign-slf4j:10.9'
compile 'com.netflix.ribbon:ribbon-httpclient:2.2.0'
testCompile group: 'junit', name: 'junit', version: '4.12'
implementation 'org.apache.commons:commons-lang3:3.4'
}

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,99 @@
package com.epri.fx.client;
import com.epri.fx.client.gui.uicomponents.control.LFXDecorator;
import com.epri.fx.client.gui.uicomponents.login.LoginController;
import com.epri.fx.client.store.ApplicatonStore;
import com.jfoenix.assets.JFoenixResources;
import com.jfoenix.svg.SVGGlyph;
import com.jfoenix.svg.SVGGlyphLoader;
import com.netflix.config.ConfigurationManager;
import io.datafx.controller.context.ApplicationContext;
import io.datafx.controller.flow.Flow;
import io.datafx.controller.flow.FlowHandler;
import io.datafx.controller.flow.container.AnimatedFlowContainer;
import io.datafx.controller.flow.container.ContainerAnimations;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
import java.io.InputStream;
/**
* @description:
* @className: AppStartup
* @author: liwen
* @date: 2019-08-26 16:24
*/
public class AppStartup extends Application {
@Override
public void init() throws Exception {
InputStream in = AppStartup.class.getClassLoader().getResourceAsStream("fonts/msyh.ttf");
Font font1 = Font.loadFont(in, 12);
System.err.println(font1.getName()+"\t"+font1.getFamily());
ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
//
}
@Override
public void start(Stage stage) throws Exception {
String keyPrefix = "";
// //全局样式
// setUserAgentStylesheet(null);
// StyleManager.getInstance().addUserAgentStylesheet("css/app.css");
new Thread(() -> {
try {
SVGGlyphLoader.loadGlyphsFont(AppStartup.class.getResourceAsStream("/fonts/icon_font/iconfont.svg"),
ApplicatonStore.ICON_FONT_KEY);
// SVGGlyphLoader.loadGlyphsFont(AppStartup.class.getResourceAsStream("/fonts/icon_font/icon-font-solid.svg"),
// "IconFontSolid.svg");
} catch (IOException ioExc) {
ioExc.printStackTrace();
}
}).start();
ApplicationContext.getInstance().register(stage, Stage.class);
Flow flow = new Flow(LoginController.class);
FlowHandler flowHandler = flow.createHandler();
StackPane rootPane = flowHandler.start(new AnimatedFlowContainer(Duration.millis(320), ContainerAnimations.SWIPE_LEFT));
ApplicationContext.getInstance().register("mainFlowHandler", flowHandler);
ApplicationContext.getInstance().register(rootPane, StackPane.class);
LFXDecorator wfxDecorator = new LFXDecorator(stage, rootPane, false, true, true);
wfxDecorator.setCustomMaximize(true);
wfxDecorator.setGraphic(new SVGGlyph(""));
Scene scene = new Scene(wfxDecorator, 1000, 700);
stage.setTitle("JavaFX Welcome");
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.show();
scene.getStylesheets().addAll(JFoenixResources.load("/css/app-fonts.css").toExternalForm(),AppStartup.class.getResource("/css/app.css").toExternalForm());
}
@Override
public void stop() throws Exception {
System.err.println(Font.getFontNames());
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2017 by Gerrit Grunwald
*
* 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.epri.fx.client.bean;
import javafx.scene.control.Tooltip;
import javafx.scene.shape.SVGPath;
import java.util.Locale;
/**
* Created by hansolo on 21.12.16.
*/
public class CountryPath extends SVGPath {
private String name;
private Locale locale;
private Tooltip tooltip;
// ******************** Constructors **************************************
public CountryPath() {
this("", null);
}
public CountryPath(final String NAME) {
this(NAME, null);
}
public CountryPath(final String NAME, final String CONTENT) {
super();
name = NAME;
locale = new Locale("", NAME);
tooltip = new Tooltip(locale.getDisplayCountry());
Tooltip.install(this, tooltip);
if (null == CONTENT) return;
setContent(CONTENT);
}
// ******************** Methods *******************************************
public String getName() {
return name;
}
public void setName(final String NAME) {
this.name = NAME;
}
public Locale getLocale() {
return locale;
}
public void setLocale(final Locale LOCALE) {
locale = LOCALE;
}
public Tooltip getTooltip() {
return tooltip;
}
public void setTooltip(final Tooltip TOOLTIP) {
tooltip = TOOLTIP;
Tooltip.install(this, tooltip);
}
@Override
public String toString() {
return new StringBuilder("{\n").append(" name :\"").append(name).append("\"\n")
.append(" locale :\"").append(locale).append("\"\n")
.append(" tooltip:\"").append(tooltip.getText()).append("\"\n")
.append(" content:\"").append(getContent()).append("\"\n")
.append("}\n")
.toString();
}
}

View File

@@ -0,0 +1,50 @@
package com.epri.fx.client.bean;
import com.epri.fx.server.entity.Menu;
import com.epri.fx.server.vo.MenuVO;
import javafx.beans.property.ListProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
/**
* @description:
* @className: MenuVoCell
* @author: liwen
* @date: 2020/8/17 20:08
*/
public class MenuVoCell {
private ObjectProperty<MenuVO> menuVO;
private ObservableList<MenuVO> childrenMenus;
public MenuVoCell(MenuVO menuVO, List<MenuVO> childrenMenus) {
this.menuVO = new SimpleObjectProperty<>(menuVO);
if (childrenMenus != null) {
getChildrenMenus().addAll(childrenMenus);
}
}
public MenuVO getMenuVO() {
return menuVO.get();
}
public ObjectProperty<MenuVO> menuVOProperty() {
return menuVO;
}
public ObservableList<MenuVO> getChildrenMenus() {
if (childrenMenus == null) {
ObservableList<MenuVO> innerList = FXCollections.observableArrayList();
childrenMenus = new SimpleListProperty<>(innerList);
}
return childrenMenus;
}
}

View File

@@ -0,0 +1,43 @@
package com.epri.fx.client.exception;
import javafx.application.Platform;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @description:
* @className: AppRunException
* @author: liwen
* @date: 2020/8/5 23:58
*/
public class AppRunException {
public static void showError(Thread t, Throwable e) {
System.err.println("***Default exception handler***");
if (Platform.isFxApplicationThread()) {
showErrorDialog(e);
} else {
System.err.println("An unexpected error occurred in " + t);
}
}
private static void showErrorDialog(Throwable e) {
StringWriter errorMsg = new StringWriter();
e.printStackTrace();
// e.printStackTrace(new PrintWriter(errorMsg));
// Stage dialog = new Stage();
// dialog.initModality(Modality.APPLICATION_MODAL);
// FXMLLoader loader = new FXMLLoader(Main.class.getResource("Error.fxml"));
// try {
// Parent root = loader.load();
// ((ErrorController)loader.getController()).setErrorText(errorMsg.toString());
// dialog.setScene(new Scene(root, 250, 400));
// dialog.show();
// } catch (IOException exc) {
// exc.printStackTrace();
// }
}
}

View File

@@ -0,0 +1,12 @@
package com.epri.fx.client.gui.feature;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DisabledByFeature {
String value();
}

View File

@@ -0,0 +1,37 @@
package com.epri.fx.client.gui.feature;
import com.epri.fx.client.store.ApplicatonStore;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Node;
import java.util.Map;
public class FeatureHandler {
private static FeatureHandler instance;
private Map<String, String> permissionInfoMap;
private FeatureHandler() {
}
public static synchronized FeatureHandler getInstance() {
if (instance == null) {
instance = new FeatureHandler();
}
return instance;
}
public void hideByFeature(Node node, String featureName) {
node.visibleProperty().bind(new SimpleBooleanProperty(ApplicatonStore.getFeatureMap().get(featureName)!=null));
node.managedProperty().bind(node.visibleProperty());
}
public void disableByFeature(Node node, String featureName) {
node.disableProperty().bind(new SimpleBooleanProperty(ApplicatonStore.getFeatureMap().get(featureName)!=null));
}
}

View File

@@ -0,0 +1,37 @@
package com.epri.fx.client.gui.feature;
import io.datafx.controller.ViewNode;
import io.datafx.controller.injection.scopes.ApplicationScoped;
import io.datafx.core.DataFXUtils;
import javafx.fxml.FXML;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
@ApplicationScoped
public class FeatureResourceConsumer {
public void consumeResource(Object object) {
Class<? extends Object> cls = object.getClass();
for (final Field field : DataFXUtils.getInheritedDeclaredFields(cls)) {
if (field.getAnnotation(FXML.class) != null || field.getAnnotation(ViewNode.class) != null) {
List<Annotation> fieldAnnotations = Arrays.asList(field.getAnnotations());
for (Annotation annotation : fieldAnnotations) {
if (annotation instanceof DisabledByFeature) {
FeatureHandler.getInstance().disableByFeature(DataFXUtils.getPrivileged(field, object), ((DisabledByFeature) annotation).value());
} else if (annotation instanceof HideByFeature) {
FeatureHandler.getInstance().hideByFeature(DataFXUtils.getPrivileged(field, object), ((HideByFeature) annotation).value());
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
package com.epri.fx.client.gui.feature;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HideByFeature {
String value();
}

View File

@@ -0,0 +1,81 @@
package com.epri.fx.client.gui.uicomponents.admin.group;
import com.epri.fx.client.gui.uicomponents.admin.group.components.GroupDetailController;
import com.epri.fx.client.model.GroupDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.GroupTypeFeign;
import com.epri.fx.server.vo.GroupTypeVO;
import com.jfoenix.controls.JFXTabPane;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.Flow;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.context.ViewFlowContext;
import io.datafx.core.concurrent.ProcessChain;
import io.datafx.eventsystem.Event;
import io.datafx.eventsystem.OnEvent;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
/**
* @description:
* @className: GroupManagementController
* @author: liwen
* @date: 2020/7/22 15:09
*/
@ViewController(value = "/fxml/admin/group/group_management.fxml", title = "角色权限管理")
public class GroupManagementController {
@FXML
private JFXTabPane tabPane;
@FXML
private StackPane rootPane;
@Inject
private GroupDataModel groupDataModel;
@PostConstruct
private void init() {
TextField textField = new TextField();
textField.setStyle("");
tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
@Override
public void changed(ObservableValue<? extends Tab> observable, Tab oldValue, Tab newValue) {
// groupDataModel.setSelectedGroupType(newValue.);
}
});
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).getAllGroupTypes())
.addConsumerInPlatformThread(rel -> {
for (GroupTypeVO groupType : rel) {
Tab tab = new Tab(groupType.getName());
Flow flow = new Flow(GroupDetailController.class);
ViewFlowContext viewFlowContext = new ViewFlowContext();
viewFlowContext.register("groupType", groupType.getId());
viewFlowContext.register("rootPane", rootPane);
try {
tab.setContent(flow.createHandler(viewFlowContext).start());
} catch (FlowException e) {
e.printStackTrace();
}
tabPane.getTabs().add(tab);
}
}).onException(e -> e.printStackTrace())
.run();
}
@OnEvent("test-message")
private void onNewChatMessage(Event<String> e) {
System.err.println(this.getClass() + "\t" + e.getContent());
}
}

View File

@@ -0,0 +1,703 @@
package com.epri.fx.client.gui.uicomponents.admin.group.components;
import com.epri.fx.client.gui.uicomponents.control.FilterableCheckBoxTreeItem;
import com.epri.fx.client.gui.uicomponents.control.FilterableTreeItem;
import com.epri.fx.client.gui.uicomponents.control.TreeItemPredicate;
import com.epri.fx.client.model.GroupDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.GroupFeign;
import com.epri.fx.client.request.feign.admin.MenuFeign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.utils.Pinyin4jUtil;
import com.epri.fx.server.entity.User;
import com.epri.fx.server.vo.ElementVO;
import com.epri.fx.server.vo.GroupVO;
import com.epri.fx.server.vo.MenuVO;
import com.jfoenix.controls.*;
import com.jfoenix.svg.SVGGlyphLoader;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.context.FXMLViewFlowContext;
import io.datafx.controller.flow.context.ViewFlowContext;
import io.datafx.core.concurrent.ProcessChain;
import io.datafx.eventsystem.Event;
import io.datafx.eventsystem.OnEvent;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.*;
import java.util.stream.Collectors;
/**
* @description:
* @className: GroupDetail
* @author: liwen
* @date: 2020/7/22 16:17
*/
@ViewController(value = "/fxml/admin/group/components/group_detail.fxml", title = "test")
public class GroupDetailController {
@FXML
private VBox contentPane;
@FXML
private JFXChipView<User> leaderChipView;
@FXML
private JFXChipView<User> memberChipView;
@FXML
private JFXDialog groupAuthorityDialog;
@FXML
private JFXDialog groupUserDialog;
@FXML
private JFXProgressBar progressBar;
@FXML
@ActionTrigger("saveAuthority")
private JFXButton saveAuthorityButton;
@FXML
@ActionTrigger("selectAllElement")
private JFXCheckBox selectAllCheckBox;
@FXML
@ActionTrigger("handlerAuthority")
private ToggleButton handlerAuthorityButton;
@FXML
@ActionTrigger("handlerUser")
private ToggleButton handlerUserButton;
@FXML
@ActionTrigger("addGroup")
private ToggleButton addButton;
@FXML
@ActionTrigger("editGroup")
private ToggleButton editButton;
@FXML
@ActionTrigger("deleteGroup")
private ToggleButton deleteButton;
@FXML
@ActionTrigger("cancelGroup")
private JFXButton cancelButton;
@FXML
@ActionTrigger("createGroup")
private JFXButton defineButton;
@FXML
@ActionTrigger("updateGroup")
private JFXButton updateButton;
@FXML
@ActionTrigger("cancelAuthority")
private JFXButton cancelAuthorityButton;
@FXML
@ActionTrigger("cancelUser")
private JFXButton cancelUserButton;
@FXML
@ActionTrigger("modifiyUsers")
private JFXButton saveUserButton;
@FXML
private JFXTextField treeSearchTextField;
@FXML
private JFXTextField nameTextField;
@FXML
private JFXTextField codeTextField;
@FXML
private JFXTextArea descTextArea;
@FXML
private ButtonBar buttonBar;
@FXML
private JFXTreeView treeView;
@Inject
private GroupDataModel groupDataModel;
@FXMLViewFlowContext
private ViewFlowContext viewFlowContext;
@FXML
private JFXTextField menuTreeSearchTextField;
@FXML
private JFXTreeView menuTreeView;
@FXML
private TableView elementTableView;
@FXML
private TableColumn<ElementVO, Boolean> selColumn;
@FXML
private TableColumn<ElementVO, String> serialNumberColumn;
@FXML
private TableColumn<ElementVO, String> codeColumn;
@FXML
private TableColumn<ElementVO, String> typeColumn;
@FXML
private TableColumn<ElementVO, String> nameColumn;
@FXML
private TableColumn<ElementVO, String> addressColumn;
@FXML
private TableColumn<ElementVO, String> requestTypeColumn;
private Integer groupType;
private Integer groupId = -1;
@PostConstruct
private void init() {
final ToggleGroup group = new ToggleGroup();
addButton.setToggleGroup(group);
editButton.setToggleGroup(group);
deleteButton.setToggleGroup(group);
handlerAuthorityButton.setToggleGroup(group);
handlerUserButton.setToggleGroup(group);
try {
addButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".add-circle-outline"));
editButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".create-outline"));
deleteButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".trash-outline"));
handlerAuthorityButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".quanxianfenpei"));
handlerUserButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".yonghugl"));
} catch (Exception e) {
e.printStackTrace();
}
buttonBar.managedProperty().bind(buttonBar.visibleProperty());
contentPane.disableProperty().bind(buttonBar.visibleProperty().not());
defineButton.managedProperty().bind(defineButton.visibleProperty());
updateButton.visibleProperty().bind(defineButton.visibleProperty().not());
updateButton.managedProperty().bind(updateButton.visibleProperty());
progressBar.visibleProperty().bind(buttonBar.disableProperty().and(buttonBar.visibleProperty()));
progressBar.managedProperty().bind(progressBar.visibleProperty());
groupType = (Integer) viewFlowContext.getRegisteredObject("groupType");
serialNumberColumn.setCellFactory((col) -> {
TableCell<ElementVO, String> cell = new TableCell<ElementVO, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int rowIndex = this.getIndex() + 1;
this.setText(String.valueOf(rowIndex));
}
}
};
return cell;
});
selColumn.setCellValueFactory(new PropertyValueFactory<>("sel"));
selColumn.setCellFactory(new Callback<TableColumn<ElementVO, Boolean>, //
TableCell<ElementVO, Boolean>>() {
@Override
public TableCell<ElementVO, Boolean> call(TableColumn<ElementVO, Boolean> p) {
CheckBoxTableCell<ElementVO, Boolean> cell = new CheckBoxTableCell<ElementVO, Boolean>() {
@Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
CheckBox cb = (CheckBox) getGraphic();
JFXCheckBox checkBox = new JFXCheckBox();
checkBox.indeterminateProperty().bindBidirectional(cb.indeterminateProperty());
checkBox.selectedProperty().bindBidirectional(cb.selectedProperty());
setGraphic(checkBox);
}
}
};
cell.setAlignment(Pos.CENTER);
return cell;
}
});
codeColumn.setCellValueFactory(cellData -> cellData.getValue().codeProperty());
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
typeColumn.setCellValueFactory(new PropertyValueFactory<>("type"));
addressColumn.setCellValueFactory(new PropertyValueFactory<>("uri"));
requestTypeColumn.setCellValueFactory(new PropertyValueFactory<>("method"));
treeView.setCellFactory(new Callback<TreeView, TreeCell>() {
@Override
public TreeCell<GroupVO> call(TreeView param) {
return new TreeCell<GroupVO>() {
@Override
protected void updateItem(GroupVO menu, boolean empty) {
super.updateItem(menu, empty);
if (!empty && menu != null) {
setText(menu.getName());
} else {
setText(null);
}
}
};
}
});
menuTreeView.setCellFactory(new Callback<TreeView, CheckBoxTreeCell>() {
@Override
public CheckBoxTreeCell<MenuVO> call(TreeView param) {
return new CheckBoxTreeCell<MenuVO>() {
@Override
public void updateItem(MenuVO item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
setText(item.getTitle());
CheckBox cb = (CheckBox) getGraphic();
JFXCheckBox checkBox = new JFXCheckBox();
checkBox.indeterminateProperty().bindBidirectional(cb.indeterminateProperty());
checkBox.selectedProperty().bindBidirectional(cb.selectedProperty());
setGraphic(checkBox);
} else {
setText(null);
}
}
};
}
});
menuTreeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<MenuVO>>() {
@Override
public void changed(ObservableValue<? extends TreeItem<MenuVO>> observable, TreeItem<MenuVO> oldValue, TreeItem<MenuVO> newValue) {
if (newValue.isLeaf()) {
MenuVO menuVO = newValue.getValue();
groupDataModel.setSelectedMenuVO(menuVO);
elementTableView.setItems(groupDataModel.getElementVOS());
} else {
groupDataModel.getElementVOS().clear();
}
int sel = 0;
if (groupDataModel.getElementVOS().isEmpty()) {
sel=-1;
}
for (ElementVO elementVO : groupDataModel.getElementVOS()) {
if (elementVO.isSel() == false) {
sel = -1;
break;
} else {
sel += 1;
}
}
selectAllCheckBox.setSelected(sel==groupDataModel.getElementVOS().size());
}
});
treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<GroupVO>>() {
@Override
public void changed(ObservableValue<? extends TreeItem<GroupVO>> observable, TreeItem<GroupVO> oldValue, TreeItem<GroupVO> newValue) {
updateMenuInfo(newValue);
}
});
leaderChipView.setChipFactory((emailJFXChipView, email) -> new JFXDefaultChip<User>(emailJFXChipView, email) {
{
if (getItem() != null) {
try {
Node image = SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".user-tie");
image.getStyleClass().add("chip-icon");
root.getChildren().add(0, image);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
leaderChipView.setPredicate((user, val) -> {
val = Pinyin4jUtil.toPinYinLowercase(val);
return Pinyin4jUtil.toPinYinLowercase(user.getName()).contains(val);
});
memberChipView.setPredicate((user, val) -> {
val = Pinyin4jUtil.toPinYinLowercase(val);
return Pinyin4jUtil.toPinYinLowercase(user.getName()).contains(val);
});
memberChipView.setChipFactory((emailJFXChipView, email) -> new JFXDefaultChip<User>(emailJFXChipView, email) {
{
if (getItem() != null) {
try {
Node image = SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".user");
image.getStyleClass().add("chip-icon");
root.getChildren().add(0, image);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
leaderChipView.setSuggestionsCellFactory(param -> new JFXListCell<>());
memberChipView.setSuggestionsCellFactory(param -> new JFXListCell<>());
initLoadData();
}
private void initLoadData() {
loadingTreeData();
}
private void loadingTreeData() {
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getGroupList(groupType))
.addConsumerInPlatformThread(rel -> buildGroupTree(rel)).onException(e -> e.printStackTrace()).run();
}
private void updateMenuInfo(TreeItem<GroupVO> newValue) {
buttonBar.setVisible(false);
if (newValue == null) {
groupId = -1;
groupDataModel.setSelectedGroup(null);
return;
}
GroupVO groupVO = newValue.getValue();
groupDataModel.setSelectedGroup(groupVO);
groupId = groupVO.getId();
codeTextField.textProperty().unbind();
codeTextField.textProperty().bind(groupVO.codeProperty());
nameTextField.textProperty().unbind();
nameTextField.textProperty().bind(groupVO.nameProperty());
descTextArea.textProperty().unbind();
descTextArea.textProperty().bind(groupVO.descriptionProperty());
}
private void buildMenuTree(List<MenuVO> menuVOList) {
if (menuVOList.isEmpty()) {
menuTreeView.setRoot(null);
return;
}
groupDataModel.getMenuVOS().clear();
for (MenuVO menuVO : menuVOList) {
groupDataModel.getMenuVOS().add(menuVO);
}
MenuVO root = menuVOList.stream().min(Comparator.comparing(MenuVO::getParentId)).get();
Map<Integer, List<MenuVO>> map = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId));
map.remove(root.getParentId());
FilterableCheckBoxTreeItem<MenuVO> rootNode = new FilterableCheckBoxTreeItem<MenuVO>(root);
groupDataModel.setSelectedMenuVO(root);
menuTreeView.setRoot(rootNode);
menuTreeView.setShowRoot(false);
addMenuChildrenNode(rootNode, map);
rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> {
if (menuTreeSearchTextField.getText() == null || menuTreeSearchTextField.getText().isEmpty()) {
return null;
}
return TreeItemPredicate.create(actor -> {
String searchText = Pinyin4jUtil.toPinYinLowercase(menuTreeSearchTextField.getText());
String itemText = Pinyin4jUtil.toPinYinLowercase(actor.getTitle());
return itemText.contains(searchText);
});
}, menuTreeSearchTextField.textProperty()));
menuTreeView.getSelectionModel().select(1);
rootNode.setExpanded(true);
}
private void addMenuChildrenNode(FilterableCheckBoxTreeItem<MenuVO> parentNode, Map<Integer, List<MenuVO>> map) {
List<MenuVO> childrenList = map.get(parentNode.getValue().getId());
if (childrenList != null) {
for (MenuVO menu : childrenList) {
FilterableCheckBoxTreeItem<MenuVO> clildrenNode = new FilterableCheckBoxTreeItem<>(menu);
clildrenNode.selectedProperty().bindBidirectional(menu.selProperty());
parentNode.getInternalChildren().add(clildrenNode);
addMenuChildrenNode(clildrenNode, map);
}
parentNode.setExpanded(true);
}
}
private void buildGroupTree(List<GroupVO> groupVOList) {
if (groupVOList.isEmpty()) {
treeView.setRoot(null);
return;
}
Map<Integer, List<GroupVO>> map = groupVOList.stream().collect(Collectors.groupingBy(GroupVO::getParentId));
GroupVO root = new GroupVO();
root.setId(-1);
FilterableTreeItem<GroupVO> rootNode = new FilterableTreeItem<GroupVO>(root);
treeView.setRoot(rootNode);
treeView.setShowRoot(false);
addChildrenNode(rootNode, map);
rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> {
if (treeSearchTextField.getText() == null || treeSearchTextField.getText().isEmpty()) {
return null;
}
return TreeItemPredicate.create(actor -> {
String searchText = Pinyin4jUtil.toPinYinLowercase(treeSearchTextField.getText());
String itemText = Pinyin4jUtil.toPinYinLowercase(actor.getName());
return itemText.contains(searchText);
});
}, treeSearchTextField.textProperty()));
rootNode.setExpanded(true);
treeView.getSelectionModel().select(rootNode);
}
private void addChildrenNode(FilterableTreeItem<GroupVO> parentNode, Map<Integer, List<GroupVO>> map) {
List<GroupVO> childrenList = map.get(parentNode.getValue().getId());
if (childrenList != null) {
for (GroupVO menu : childrenList) {
FilterableTreeItem<GroupVO> clildrenNode = new FilterableTreeItem<>(menu);
parentNode.getInternalChildren().add(clildrenNode);
parentNode.setExpanded(true);
addChildrenNode(clildrenNode, map);
}
}
}
@ActionMethod("addGroup")
private void addGroup() {
codeTextField.textProperty().unbind();
codeTextField.setText("");
nameTextField.textProperty().unbind();
nameTextField.setText("");
descTextArea.textProperty().unbind();
descTextArea.setText("");
buttonBar.setVisible(true);
defineButton.setVisible(true);
}
@ActionMethod("editGroup")
private void editGroup() {
codeTextField.textProperty().unbind();
nameTextField.textProperty().unbind();
descTextArea.textProperty().unbind();
buttonBar.setVisible(true);
defineButton.setVisible(false);
}
@ActionMethod("cancelGroup")
private void cancelGroup() {
buttonBar.setVisible(false);
}
@ActionMethod("createGroup")
private void createGroup() {
GroupVO groupVO = new GroupVO();
groupVO.setParentId(groupId);
groupVO.setGroupType(groupType);
groupVO.setCode(codeTextField.getText());
groupVO.setName(nameTextField.getText());
groupVO.setDescription(descTextArea.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> buttonBar.setDisable(true)).addSupplierInExecutor(() -> Request.connector(GroupFeign.class).addGroup(groupVO))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
loadingTreeData();
}
})
.withFinal(() -> {
buttonBar.setDisable(false);
buttonBar.setVisible(false);
})
.run();
}
@ActionMethod("updateGroup")
private void updateGroup() {
GroupVO groupVO = new GroupVO();
groupVO.setId(groupDataModel.getSelectedGroup().getId());
groupVO.setParentId(groupDataModel.getSelectedGroup().getParentId());
groupVO.setGroupType(groupType);
groupVO.setCode(codeTextField.getText());
groupVO.setName(nameTextField.getText());
groupVO.setDescription(descTextArea.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> buttonBar.setDisable(true)).addSupplierInExecutor(() -> Request.connector(GroupFeign.class).updateGroup(groupVO))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
loadingTreeData();
}
})
.withFinal(() -> {
buttonBar.setDisable(false);
buttonBar.setVisible(false);
})
.run();
}
@ActionMethod("deleteGroup")
private void deleteGroup() {
GroupVO groupVO = groupDataModel.getSelectedGroup();
JFXAlert alert = new JFXAlert((Stage) contentPane.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("消息提示"));
layout.setBody(new Label("确实删除【" + groupVO.getName() + "】吗?"));
JFXButton closeButton = new JFXButton("取消");
closeButton.setOnAction(event -> alert.hideWithAnimation());
JFXButton determineButton = new JFXButton("确定");
determineButton.setOnAction(event -> {
alert.hideWithAnimation();
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).deleteGroup(groupVO))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
loadingTreeData();
}
}).onException(e -> e.printStackTrace())
.run();
});
layout.setActions(closeButton, determineButton);
alert.setContent(layout);
alert.show();
}
@ActionMethod("saveAuthority")
private void saveAuthority() {
List<MenuVO> saveMenuList = new ArrayList<>();
for (MenuVO menuVO : groupDataModel.getMenuVOS()) {
if (menuVO.isSel()) {
saveMenuList.add(menuVO);
List<ElementVO> elementList = menuVO.getElementVOS().stream().filter(elementVO -> elementVO.isSel()).collect(Collectors.toList());
menuVO.getElementVOS().clear();
menuVO.getElementVOS().addAll(elementList);
}
}
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).modifyMenuAuthority(groupId, saveMenuList))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
groupDataModel.setSelectedMenuVO(new MenuVO());
}
}).onException(e -> e.printStackTrace())
.withFinal(() -> groupAuthorityDialog.close())
.run();
}
@ActionMethod("cancelAuthority")
private void cancelAuthorityButton() {
groupAuthorityDialog.close();
}
@ActionMethod("selectAllElement")
private void selectAllElement() {
List<ElementVO> elementVOS = groupDataModel.getElementVOS();
for (ElementVO elementVO : elementVOS) {
elementVO.setSel(selectAllCheckBox.isSelected());
}
}
@ActionMethod("handlerAuthority")
private void handlerAuthority() throws FlowException {
groupAuthorityDialog.show((StackPane) viewFlowContext.getRegisteredObject("rootPane"));
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getAuthorityMenuElementAll(groupId))
.addConsumerInPlatformThread(rel -> buildMenuTree(rel)).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("cancelUser")
private void cancelUser() throws FlowException {
groupUserDialog.close();
}
@ActionMethod("modifiyUsers")
private void modifiyUsers() throws FlowException {
Set<Integer> ls = new HashSet<>();
Set<Integer> ms = new HashSet<>();
for (User user : memberChipView.getChips()) {
ms.add(user.getId());
}
for (User user : leaderChipView.getChips()) {
ls.add(user.getId());
}
Map<String, String> parmMap = new HashMap<>();
parmMap.put("members", ms.toString());
parmMap.put("leaders", ls.toString());
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).modifiyUsers(groupId, parmMap))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
groupUserDialog.close();
}
}).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("handlerUser")
private void handlerUser() {
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
leaderChipView.getChips().clear();
leaderChipView.getSuggestions().clear();
memberChipView.getChips().clear();
memberChipView.getSuggestions().clear();
})
.addSupplierInExecutor(() -> Request.connector(GroupFeign.class).getUsers(groupId))
.addConsumerInPlatformThread(rel -> {
leaderChipView.getChips().addAll(rel.getLeaders());
leaderChipView.getSuggestions().addAll(rel.getUsers());
memberChipView.getChips().addAll(rel.getMembers());
memberChipView.getSuggestions().addAll(rel.getUsers());
}).withFinal(() -> groupUserDialog.show((StackPane) viewFlowContext.getRegisteredObject("rootPane")))
.onException(e -> e.printStackTrace()).run();
}
@OnEvent("test-message")
private void onNewChatMessage(Event<String> e) {
System.err.println(this.getClass() + "\t" + e.getContent());
}
}

View File

@@ -0,0 +1,309 @@
package com.epri.fx.client.gui.uicomponents.admin.grouptype;
import com.epri.fx.client.model.GroupTypeDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.GroupTypeFeign;
import com.epri.fx.client.request.feign.admin.UserFeign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.utils.Pinyin4jUtil;
import com.epri.fx.server.vo.GroupTypeVO;
import com.jfoenix.controls.*;
import com.jfoenix.svg.SVGGlyphLoader;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.context.FXMLViewFlowContext;
import io.datafx.controller.flow.context.ViewFlowContext;
import io.datafx.core.concurrent.ProcessChain;
import javafx.collections.transformation.FilteredList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.Date;
/**
* @description:
* @className: RoleRightsManagement
* @author: liwen
* @date: 2020/7/12 01:23
*/
@ViewController(value = "/fxml/admin/groupType/group_type_management.fxml", title = "角色类型管理")
public class GroupTypeManagementController {
@FXMLViewFlowContext
private ViewFlowContext viewFlowContext;
@FXML
private StackPane rootPane;
@FXML
private JFXProgressBar progressBar;
@FXML
private JFXDialog dialog;
@FXML
private Label title;
@FXML
private JFXButton searchButton;
@FXML
@ActionTrigger("createDialog")
private JFXButton addButton;
@FXML
@ActionTrigger("closeDialog")
private JFXButton cancelButton;
@FXML
@ActionTrigger("createGroupType")
private JFXButton saveButton;
@FXML
@ActionTrigger("updateGroupType")
private JFXButton updateButton;
@FXML
private JFXTextField searchField;
@FXML
private JFXTextField nameTextField;
@FXML
private JFXTextField codeTextField;
@FXML
private JFXTextArea descriptionTextArea;
@FXML
private TableView<GroupTypeVO> tableView;
@FXML
private TableColumn<GroupTypeVO, String> serialNumberColumn;
@FXML
private TableColumn<GroupTypeVO, String> codeColumn;
@FXML
private TableColumn<GroupTypeVO, String> nameColumn;
@FXML
private TableColumn<GroupTypeVO, String> descriptionColumn;
@FXML
private TableColumn<GroupTypeVO, Date> updTimeColumn;
@FXML
private TableColumn<GroupTypeVO, String> updHostColumn;
@FXML
private TableColumn<GroupTypeVO, String> operatingColumn;
@Inject
private GroupTypeDataModel groupTypeDataModel;
@PostConstruct
private void init() {
progressBar.visibleProperty().bind(dialog.disableProperty());
progressBar.managedProperty().bind(progressBar.visibleProperty());
updateButton.visibleProperty().bind(saveButton.visibleProperty().not());
updateButton.managedProperty().bind(updateButton.visibleProperty());
cancelButton.disableProperty().bind(saveButton.disableProperty().or(updateButton.disableProperty()));
serialNumberColumn.setCellFactory((col) -> {
TableCell<GroupTypeVO, String> cell = new TableCell<GroupTypeVO, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int rowIndex = this.getIndex() + 1;
this.setText(String.valueOf(rowIndex));
}
}
};
return cell;
});
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
codeColumn.setCellValueFactory(new PropertyValueFactory<>("code"));
descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description"));
updTimeColumn.setCellValueFactory(new PropertyValueFactory<>("updTime"));
updHostColumn.setCellValueFactory(new PropertyValueFactory<>("updHost"));
Callback<TableColumn<GroupTypeVO, String>, TableCell<GroupTypeVO, String>> cellFactory = new Callback<TableColumn<GroupTypeVO, String>, TableCell<GroupTypeVO, String>>() {
@Override
public TableCell<GroupTypeVO, String> call(TableColumn param) {
final TableCell<GroupTypeVO, String> cell = new TableCell<GroupTypeVO, String>() {
private final ToggleButton editBut = new ToggleButton();
private final ToggleButton delBut = new ToggleButton();
{
editBut.getStyleClass().add("left-pill");
delBut.getStyleClass().add("right-pill");
try {
editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline"));
delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline"));
} catch (Exception e) {
e.printStackTrace();
}
editBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
updateDialog();
});
delBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
delete();
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
HBox hBox = new HBox(editBut, delBut);
hBox.setAlignment(Pos.CENTER);
hBox.setSpacing(0);
setGraphic(hBox);
}
}
};
return cell;
}
};
operatingColumn.setCellFactory(cellFactory);
FilteredList<GroupTypeVO> filteredData = new FilteredList<>(groupTypeDataModel.getGroupTypes(), p -> true);
tableView.setItems(filteredData);
searchField.textProperty().addListener((o, oldVal, newVal) -> {
filteredData.setPredicate(elementProp -> {
if (newVal == null || newVal.isEmpty()) {
return true;
}
String val = Pinyin4jUtil.toPinYinLowercase(newVal);
return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val)
|| Pinyin4jUtil.toPinYinLowercase(elementProp.getCode()).contains(val);
});
});
groupTypeDataModel.selectedIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty());
initData();
}
private void initData() {
loadingTableData();
}
private void loadingTableData() {
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).getAllGroupTypes())
.addConsumerInPlatformThread(rel -> {
groupTypeDataModel.getGroupTypes().clear();
groupTypeDataModel.getGroupTypes().addAll(rel);})
.run();
}
@ActionMethod("closeDialog")
private void closeDialog() {
dialog.close();
}
@ActionMethod("createDialog")
private void createDialog() {
title.setText("新建");
codeTextField.setText("");
nameTextField.setText("");
descriptionTextArea.setText("");
saveButton.setVisible(true);
dialog.show(rootPane);
}
@ActionMethod("createGroupType")
private void createGroupType() {
GroupTypeVO groupTypeVO = new GroupTypeVO();
groupTypeVO.setCode(codeTextField.getText());
groupTypeVO.setName(nameTextField.getText());
groupTypeVO.setDescription(descriptionTextArea.getText());
ProcessChain.create().addRunnableInPlatformThread(() -> dialog.setDisable(true))
.addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).addGroupType(groupTypeVO))
.addConsumerInPlatformThread(rel -> {
if (rel >=0) {
loadingTableData();
}
}).withFinal(() -> {
dialog.setDisable(false);
dialog.close();
})
.run();
}
@ActionMethod("updateGroupType")
private void updateGroupType() {
GroupTypeVO groupTypeVO = new GroupTypeVO();
groupTypeVO.setId((groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex())).getId());
groupTypeVO.setCode(codeTextField.getText());
groupTypeVO.setName(nameTextField.getText());
groupTypeVO.setDescription(descriptionTextArea.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> dialog.setDisable(true))
.addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).updateGroupType(groupTypeVO))
.addConsumerInPlatformThread(rel -> {
if (rel > -0) {
loadingTableData();
}
}).withFinal(() -> {
dialog.setDisable(false);
dialog.close();
})
.run();
}
private void delete() {
GroupTypeVO groupTypeVO = groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex());
JFXAlert alert = new JFXAlert((Stage) rootPane.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("消息提示"));
layout.setBody(new Label("确实删除【" + groupTypeVO.getName() + "】吗?"));
JFXButton closeButton = new JFXButton("取消");
closeButton.setOnAction(event -> alert.hideWithAnimation());
JFXButton determineButton = new JFXButton("确定");
determineButton.setOnAction(event -> {
alert.hideWithAnimation();
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(GroupTypeFeign.class).deleteGroupTypes(groupTypeVO.getId()))
.addConsumerInPlatformThread(result -> {
if (result >= 0) {
groupTypeDataModel.getGroupTypes().remove(groupTypeDataModel.getSelectedIndex());
}
}).onException(e -> e.printStackTrace()).run();
});
layout.setActions(closeButton, determineButton);
alert.setContent(layout);
alert.show();
}
private void updateDialog() {
title.setText("编辑");
saveButton.setVisible(false);
GroupTypeVO groupTypeVO = groupTypeDataModel.getGroupTypes().get(groupTypeDataModel.getSelectedIndex());
codeTextField.setText(groupTypeVO.getCode());
nameTextField.setText(groupTypeVO.getName());
descriptionTextArea.setText(groupTypeVO.getDescription());
dialog.show(rootPane);
}
}

View File

@@ -0,0 +1,693 @@
package com.epri.fx.client.gui.uicomponents.admin.menu;
import com.epri.fx.client.gui.uicomponents.control.FilterableTreeItem;
import com.epri.fx.client.gui.uicomponents.control.TreeItemPredicate;
import com.epri.fx.client.model.MenuDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.ElementFeign;
import com.epri.fx.client.request.feign.admin.MenuFeign;
import com.epri.fx.client.request.feign.admin.UserFeign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.utils.Pinyin4jUtil;
import com.epri.fx.server.entity.Element;
import com.epri.fx.server.msg.TableResultResponse;
import com.epri.fx.server.vo.ElementVO;
import com.epri.fx.server.vo.MenuVO;
import com.jfoenix.controls.*;
import com.jfoenix.svg.SVGGlyphLoader;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.core.concurrent.ProcessChain;
import io.datafx.eventsystem.Event;
import io.datafx.eventsystem.OnEvent;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.transformation.FilteredList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @description:
* @className: UserManagement
* @author: liwen
* @date: 2020/6/30 22:37
*/
@ViewController(value = "/fxml/admin/menu/menu_management.fxml", title = "菜单管理")
public class MenuManagementController {
private static final String[] METHOD_OPTIONS = {"GET", "POST", "PUT", "DELETE"};
private static final String[] TYPE_OPTIONS = {"uri", "button"};
@FXML
private StackPane rootPane;
@FXML
private VBox infoPane;
@FXML
private TableView<ElementVO> tableView;
@FXML
private TreeView treeView;
@FXML
private VBox treePane;
@FXML
private JFXSpinner treeViewSpinner;
@FXML
private JFXTextField treeSearchTextField;
@FXML
private JFXProgressBar elementProgressBar;
//menu
@FXML
private JFXTextField titleTextField;
@FXML
private JFXTextField codeTextField;
@FXML
private JFXTextField orderNumTextField;
@FXML
private JFXTextField parentIdTextField;
@FXML
private JFXTextField iconTextField;
@FXML
private JFXTextArea descriptionTextAre;
@FXML
private JFXTextField hrefTextFeild;
//element
@FXML
private VBox elementPane;
@FXML
private JFXTextField elementCodeTextField;
@FXML
private JFXComboBox<String> elementTypeComboBox;
@FXML
private JFXTextField elementNameTextField;
@FXML
private JFXTextField elementUriTextField;
@FXML
private JFXComboBox<String> elementMethodComBox;
@FXML
private JFXTextArea elementDesTextAre;
@FXML
@ActionTrigger("updateMenu")
private JFXButton updateButton;
@FXML
@ActionTrigger("saveMenu")
private JFXButton saveButton;
@FXML
private JFXButton cancelButton;
@FXML
@ActionTrigger("addElement")
private JFXButton addElement;
@FXML
@ActionTrigger("addMenu")
private ToggleButton addButton;
@FXML
@ActionTrigger("editMenu")
private ToggleButton editButton;
@FXML
@ActionTrigger("deleteMenu")
private ToggleButton deleteButton;
@FXML
private ButtonBar buttonBar;
@FXML
private GridPane gridPane;
@FXML
@ActionTrigger("cancelElementDialog")
private JFXButton cancelElementButton;
@FXML
@ActionTrigger("upeateElement")
private JFXButton updateElementButton;
@FXML
@ActionTrigger("createElement")
private JFXButton saveElementButton;
@FXML
private JFXTextField elementfilterField;
@FXML
private TableColumn<ElementVO, String> serialNumberColumn;
@FXML
private TableColumn<ElementVO, String> codeColumn;
@FXML
private TableColumn<ElementVO, String> typeColumn;
@FXML
private TableColumn<ElementVO, String> nameColumn;
@FXML
private TableColumn<ElementVO, String> addressColumn;
@FXML
private TableColumn<ElementVO, String> requestTypeColumn;
@FXML
private TableColumn<ElementVO, String> descriptionColumn;
@FXML
private TableColumn<ElementVO, String> operateColumn;
@FXML
private JFXDialog dialog;
@Inject
private MenuDataModel menuDataModel;
@PostConstruct
private void init() {
final ToggleGroup group = new ToggleGroup();
addButton.setToggleGroup(group);
editButton.setToggleGroup(group);
deleteButton.setToggleGroup(group);
try {
addButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".add-circle-outline"));
editButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".create-outline"));
deleteButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY+".trash-outline"));
} catch (Exception e) {
e.printStackTrace();
}
elementTypeComboBox.getItems().addAll(TYPE_OPTIONS);
elementMethodComBox.getItems().addAll(METHOD_OPTIONS);
elementProgressBar.visibleProperty().bind(updateElementButton.disableProperty().or(saveElementButton.disableProperty()));
elementProgressBar.managedProperty().bind(elementProgressBar.visibleProperty());
updateElementButton.visibleProperty().bind(saveElementButton.visibleProperty().not());
updateElementButton.managedProperty().bind(updateElementButton.visibleProperty());
cancelElementButton.disableProperty().bind(saveElementButton.disableProperty().or(updateElementButton.disableProperty()));
buttonBar.visibleProperty().bind(infoPane.disableProperty().not());
buttonBar.managedProperty().bind(buttonBar.visibleProperty());
saveButton.managedProperty().bind(saveButton.visibleProperty());
updateButton.visibleProperty().bind(saveButton.visibleProperty().not());
updateButton.managedProperty().bind(updateButton.visibleProperty());
serialNumberColumn.setCellFactory((col) -> {
TableCell<ElementVO, String> cell = new TableCell<ElementVO, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int rowIndex = this.getIndex() + 1;
this.setText(String.valueOf(rowIndex));
}
}
};
return cell;
});
codeColumn.setCellValueFactory(new PropertyValueFactory<>("code"));
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
typeColumn.setCellValueFactory(new PropertyValueFactory<>("type"));
addressColumn.setCellValueFactory(new PropertyValueFactory<>("uri"));
requestTypeColumn.setCellValueFactory(new PropertyValueFactory<>("method"));
descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description"));
addOperateButtonToTable();
menuDataModel.selectedElementIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty());
FilteredList<ElementVO> filteredData = new FilteredList<>(menuDataModel.getElementVOS(), p -> true);
tableView.setItems(filteredData);
elementfilterField.textProperty().addListener((o, oldVal, newVal) -> {
filteredData.setPredicate(elementProp -> {
if (newVal == null || newVal.isEmpty()) {
return true;
}
String val = Pinyin4jUtil.toPinYinLowercase(newVal);
return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val)
|| elementProp.getMethod().toLowerCase().contains(val)
|| elementProp.getType().toLowerCase().contains(val);
});
});
treeViewSpinner.visibleProperty().bind(treePane.disableProperty());
gridPane.disableProperty().bind(buttonBar.visibleProperty().not());
treeView.setCellFactory(new Callback<TreeView, TreeCell>() {
@Override
public TreeCell<MenuVO> call(TreeView param) {
return new TreeCell<MenuVO>() {
@Override
protected void updateItem(MenuVO menu, boolean empty) {
super.updateItem(menu, empty);
if (!empty && menu != null) {
setText(menu.getTitle());
} else {
setText(null);
}
}
};
}
});
parentIdTextField.setDisable(true);
cancelButton.setOnAction(event -> {
infoPane.setDisable(true);
});
treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<MenuVO>>() {
@Override
public void changed(ObservableValue<? extends TreeItem<MenuVO>> observable, TreeItem<MenuVO> oldValue, TreeItem<MenuVO> newValue) {
updateMenuInfo(newValue);
}
});
initTreeData();
}
private void updateMenuInfo(TreeItem<MenuVO> newValue) {
infoPane.setDisable(true);
if (newValue == null) {
return;
}
MenuVO menuVO = newValue.getValue();
menuDataModel.setSelectMenuVO(menuVO);
if (newValue.isLeaf()) {
elementPane.setVisible(true);
elementPane.setManaged(true);
updateMenuElement();
} else {
elementPane.setVisible(false);
elementPane.setManaged(false);
menuDataModel.getElementVOS().clear();
}
codeTextField.setText(menuVO.getCode());
orderNumTextField.setText(menuVO.getOrderNum() + "");
titleTextField.setText(menuVO.getTitle());
parentIdTextField.setText(menuVO.getParentId() + "");
iconTextField.setText(menuVO.getIcon());
hrefTextFeild.setText(menuVO.getHref());
descriptionTextAre.setText(menuVO.getDescription());
}
private void updateMenuElement() {
MenuVO menuVO = menuDataModel.getSelectMenuVO();
ProcessChain.create()
.addSupplierInExecutor(() -> {
TableResultResponse<Element> tableResultResponse = Request.connector(ElementFeign.class).getMenuElementList(menuVO.getId());
List<Element> elementList = tableResultResponse.getDatas();
List<ElementVO> elementVOList = new ArrayList<>();
elementList.forEach(element -> {
elementVOList.add(new ElementVO(element.getId(), element.getCode(), element.getType(), element.getName(), element.getUri(), element.getMenuId(), element.getParentId(), element.getPath(), element.getMethod(), element.getDescription()));
});
return elementVOList;
})
.addConsumerInPlatformThread(rel -> {
menuVO.getElementVOS().clear();
menuVO.getElementVOS().addAll(rel);
menuDataModel.getElementVOS().clear();
menuDataModel.getElementVOS().addAll(rel);
}).onException(e -> e.printStackTrace())
.run();
}
private <T> void setupCellValueFactory(JFXTreeTableColumn<ElementVO, T> column, Function<ElementVO, ObservableValue<T>> mapper) {
column.setCellValueFactory((TreeTableColumn.CellDataFeatures<ElementVO, T> param) -> {
if (column.validateValue(param)) {
return mapper.apply(param.getValue().getValue());
} else {
return column.getComputedValue(param);
}
});
}
private void initTreeData() {
ProcessChain.create().addRunnableInPlatformThread(() -> treePane.setDisable(true))
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).getMenuAll())
.addConsumerInPlatformThread(rel -> {
buildMenuTree(rel);
}).onException(e -> e.printStackTrace()).withFinal(() -> treePane.setDisable(false)).run();
}
private void buildMenuTree(List<MenuVO> menuList) {
MenuVO rootMenu = menuList.stream().min(Comparator.comparing(MenuVO::getParentId)).get();
Map<Integer, List<MenuVO>> map = menuList.stream().collect(Collectors.groupingBy(MenuVO::getParentId));
map.remove(rootMenu.getParentId());
FilterableTreeItem<MenuVO> rootNode = new FilterableTreeItem<MenuVO>(rootMenu);
treeView.setRoot(rootNode);
treeView.setShowRoot(false);
addChildrenNode(rootNode, map);
rootNode.predicateProperty().bind(Bindings.createObjectBinding(() -> {
if (treeSearchTextField.getText() == null || treeSearchTextField.getText().isEmpty()) {
return null;
}
return TreeItemPredicate.create(actor -> {
String searchText = Pinyin4jUtil.toPinYinLowercase(treeSearchTextField.getText());
String itemText = Pinyin4jUtil.toPinYinLowercase(actor.toString());
return itemText.contains(searchText);
});
}, treeSearchTextField.textProperty()));
rootNode.setExpanded(true);
treeView.getSelectionModel().select(rootNode);
}
private void addChildrenNode(FilterableTreeItem<MenuVO> parentNode, Map<Integer, List<MenuVO>> map) {
List<MenuVO> childrenList = map.get(parentNode.getValue().getId());
if (childrenList != null) {
for (MenuVO menu : childrenList) {
FilterableTreeItem<MenuVO> clildrenNode = new FilterableTreeItem<>(menu);
parentNode.getInternalChildren().add(clildrenNode);
addChildrenNode(clildrenNode, map);
}
}
}
private void addOperateButtonToTable() {
Callback<TableColumn<ElementVO, String>, TableCell<ElementVO, String>> cellFactory = new Callback<TableColumn<ElementVO, String>, TableCell<ElementVO, String>>() {
@Override
public TableCell<ElementVO, String> call(TableColumn param) {
final TableCell<ElementVO, String> cell = new TableCell<ElementVO, String>() {
private final ToggleButton editBut = new ToggleButton();
private final ToggleButton delBut = new ToggleButton();
{
editBut.getStyleClass().add("left-pill");
delBut.getStyleClass().add("right-pill");
try {
editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline"));
delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline"));
} catch (Exception e) {
e.printStackTrace();
}
editBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
editElement();
});
delBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
deleteElement();
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
HBox hBox = new HBox(editBut, delBut);
hBox.setAlignment(Pos.CENTER);
hBox.setSpacing(0);
setGraphic(hBox);
}
}
};
return cell;
}
};
operateColumn.setCellFactory(cellFactory);
}
@ActionMethod("addMenu")
private void addMenu() {
infoPane.setDisable(false);
saveButton.setVisible(true);
codeTextField.setText("");
orderNumTextField.setText("");
titleTextField.setText("");
parentIdTextField.setText(menuDataModel.getSelectMenuVO().getId() + "");
iconTextField.setText("");
hrefTextFeild.setText("");
descriptionTextAre.setText("");
}
@ActionMethod("saveMenu")
private void saveMenu() {
MenuVO menuVO = new MenuVO();
menuVO.setTitle(titleTextField.getText());
menuVO.setCode(codeTextField.getText());
menuVO.setIcon(iconTextField.getText());
menuVO.setHref(hrefTextFeild.getText());
menuVO.setOrderNum(Integer.parseInt(orderNumTextField.getText()));
menuVO.setParentId(Integer.parseInt(parentIdTextField.getText()));
menuVO.setDescription(descriptionTextAre.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> infoPane.setDisable(true))
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).addMenu(menuVO))
.addConsumerInPlatformThread(rel -> {
if (rel == 1) {
initTreeData();
}
})
.withFinal(() -> {
infoPane.setDisable(false);
treeView.getRoot().setExpanded(true);
}).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("editMenu")
private void editMenu() {
infoPane.setDisable(false);
saveButton.setVisible(false);
}
@ActionMethod("updateMenu")
private void updateMenu() {
MenuVO menuVO = menuDataModel.getSelectMenuVO();
menuVO.setTitle(titleTextField.getText());
menuVO.setCode(codeTextField.getText());
menuVO.setIcon(iconTextField.getText());
menuVO.setHref(hrefTextFeild.getText());
menuVO.setOrderNum(Integer.parseInt(orderNumTextField.getText()));
menuVO.setParentId(Integer.parseInt(parentIdTextField.getText()));
menuVO.setDescription(descriptionTextAre.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> infoPane.setDisable(true))
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).updateMenu(menuVO))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
initTreeData();
}
}).withFinal(() -> {
infoPane.setDisable(false);
treeView.getRoot().setExpanded(true);
}).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("deleteMenu")
private void deleteMenu() {
JFXAlert alert = new JFXAlert((Stage) rootPane.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("消息提示"));
layout.setBody(new Label("确实删除【" + menuDataModel.getSelectMenuVO().getTitle() + "】吗?"));
JFXButton closeButton = new JFXButton("取消");
closeButton.setOnAction(event -> alert.hideWithAnimation());
JFXButton determineButton = new JFXButton("确定");
determineButton.setOnAction(event -> {
alert.hideWithAnimation();
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).deleteMenu(menuDataModel.getSelectMenuVO()))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
initTreeData();
}
}).withFinal(() -> {
treeView.getRoot().setExpanded(true);
}).onException(e -> e.printStackTrace())
.run();
});
layout.setActions(closeButton, determineButton);
alert.setContent(layout);
alert.show();
}
@ActionMethod("addElement")
private void addElement() {
elementCodeTextField.setText("");
elementTypeComboBox.getSelectionModel().select(null);
elementMethodComBox.getSelectionModel().select(null);
elementNameTextField.setText("");
elementUriTextField.setText("");
elementCodeTextField.setText("");
elementDesTextAre.setText("");
saveElementButton.setManaged(true);
saveElementButton.setVisible(true);
dialog.setTransitionType(JFXDialog.DialogTransition.TOP);
dialog.show(rootPane);
}
@ActionMethod("createElement")
private void createElement() {
MenuVO menuVO = menuDataModel.getSelectMenuVO();
Element newElect = new Element();
newElect.setCode(elementCodeTextField.getText());
newElect.setMenuId(menuVO.getId() + "");
newElect.setName(elementNameTextField.getText());
newElect.setUri(elementUriTextField.getText());
newElect.setType(elementTypeComboBox.getSelectionModel().getSelectedItem());
newElect.setMethod(elementMethodComBox.getSelectionModel().getSelectedItem());
newElect.setDescription(elementDesTextAre.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
saveElementButton.setDisable(true);
})
.addSupplierInExecutor(() -> Request.connector(ElementFeign.class).addElement(newElect))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
updateMenuElement();
}
})
.withFinal(() -> {
saveElementButton.setDisable(false);
dialog.close();
}).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("upeateElement")
private void updateElement() {
MenuVO menuVO = menuDataModel.getSelectMenuVO();
Element newElect = new Element();
newElect.setId(menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex()).getId());
newElect.setCode(elementCodeTextField.getText());
newElect.setMenuId(menuVO.getId() + "");
newElect.setName(elementNameTextField.getText());
newElect.setUri(elementUriTextField.getText());
newElect.setType(elementTypeComboBox.getSelectionModel().getSelectedItem());
newElect.setMethod(elementMethodComBox.getSelectionModel().getSelectedItem());
newElect.setDescription(elementDesTextAre.getText());
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
updateElementButton.setDisable(true);
})
.addSupplierInExecutor(() -> Request.connector(ElementFeign.class).updateElement(newElect))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
updateMenuElement();
}
})
.withFinal(() -> {
updateElementButton.setDisable(false);
dialog.close();
}).onException(e -> e.printStackTrace())
.run();
}
private void editElement() {
ElementVO elementVO = menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex());
elementCodeTextField.setText(elementVO.getCode());
elementTypeComboBox.getSelectionModel().select(elementVO.getType());
elementMethodComBox.getSelectionModel().select(elementVO.getMethod());
elementNameTextField.setText(elementVO.getName());
elementUriTextField.setText(elementVO.getUri());
elementDesTextAre.setText(elementVO.getDescription());
saveElementButton.setManaged(false);
saveElementButton.setVisible(false);
dialog.setTransitionType(JFXDialog.DialogTransition.TOP);
dialog.show(rootPane);
}
private void deleteElement() {
ElementVO elementVO = menuDataModel.getElementVOS().get(menuDataModel.getSelectedElementIndex());
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
})
.addSupplierInExecutor(() -> Request.connector(ElementFeign.class).deleteElement(elementVO.getId()))
.addConsumerInPlatformThread(rel -> {
if (rel >= 0) {
updateMenuElement();
}
})
.withFinal(() -> {
}).onException(e -> e.printStackTrace())
.run();
}
@ActionMethod("cancelElementDialog")
private void cancelElementDialog() {
dialog.close();
}
@OnEvent("test-message")
private void onNewChatMessage(Event<String> e) {
System.err.println(this.getClass() + "\t" + e.getContent());
}
}

View File

@@ -0,0 +1,380 @@
package com.epri.fx.client.gui.uicomponents.admin.user;
import com.epri.fx.client.gui.feature.FeatureResourceConsumer;
import com.epri.fx.client.gui.feature.HideByFeature;
import com.epri.fx.client.gui.uicomponents.admin.user.components.UserAddController;
import com.epri.fx.client.gui.uicomponents.admin.user.components.UserEditController;
import com.epri.fx.client.model.UserDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.UserFeign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.utils.Pinyin4jUtil;
import com.epri.fx.server.entity.User;
import com.epri.fx.server.util.DateUtils;
import com.epri.fx.server.vo.UserVO;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.svg.SVGGlyph;
import com.jfoenix.svg.SVGGlyphLoader;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.util.VetoException;
import io.datafx.core.concurrent.ProcessChain;
import javafx.collections.transformation.FilteredList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @description:
* @className: UserManagementController
* @author: liwen
* @date: 2020/3/4 21:05
*/
@ViewController(value = "/fxml/admin/user/user_management.fxml", title = "用户管理")
public class UserManagementController {
public static final String CONTENT_PANE = "ContentPane";
@FXML
private StackPane root;
@FXML
private VBox centPane;
@FXML
private StackPane spinnerPane;
@FXML
private TextField searchField;
@FXML
private TextField userNameTextField;
@FXML
private TextField accountTextField;
@FXML
private TextField pwdTextField;
@FXML
private TextArea descTextArea;
@FXML
private ComboBox genderCombobox;
@FXML
@ActionTrigger("createUser")
@HideByFeature("userManager:btn_add")
private Button addBut;
@FXML
@ActionTrigger("accept")
private Button acceptButton;
@FXML
@ActionTrigger("cancel")
private Button cancelButton;
@FXML
@ActionTrigger("search")
private Button searchBut;
@FXML
private Pagination pagination;
@FXML
private TableView<UserVO> tableView;
@FXML
private TableColumn<UserVO, String> serialNumberColumn;
@FXML
private TableColumn<UserVO, String> nameColumn;
@FXML
private TableColumn<UserVO, String> accountColumn;
@FXML
private TableColumn<UserVO, String> remarksColumn;
@FXML
private TableColumn<UserVO, String> lastUpdateTimeColumn;
@FXML
private TableColumn<UserVO, String> lastUpdatedByColumn;
@FXML
private TableColumn<UserVO, String> operateColumn;
@ActionHandler
private FlowActionHandler actionHandler;
@Inject
private UserDataModel dataModel;
@Inject
private FeatureResourceConsumer featureResourceConsumer;
@PostConstruct
public void init() {
featureResourceConsumer.consumeResource(this);
spinnerPane.setVisible(false);
serialNumberColumn.setCellFactory((col) -> {
TableCell<UserVO, String> cell = new TableCell<UserVO, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
this.setText(null);
this.setGraphic(null);
if (!empty) {
int rowIndex = this.getIndex() + 1;
this.setText(String.valueOf(rowIndex));
}
}
};
return cell;
});
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
accountColumn.setCellValueFactory(new PropertyValueFactory<>("userName"));
remarksColumn.setCellValueFactory(new PropertyValueFactory<>("description"));
lastUpdateTimeColumn.setCellValueFactory(new PropertyValueFactory<>("updTime"));
lastUpdatedByColumn.setCellValueFactory(new PropertyValueFactory<>("updUser"));
Callback<TableColumn<UserVO, String>, TableCell<UserVO, String>> cellFactory = new Callback<TableColumn<UserVO, String>, TableCell<UserVO, String>>() {
@Override
public TableCell<UserVO, String> call(TableColumn param) {
final TableCell<UserVO, String> cell = new TableCell<UserVO, String>() {
private final ToggleButton resetBut = new ToggleButton();
private final ToggleButton editBut = new ToggleButton();
private final ToggleButton delBut = new ToggleButton();
{
resetBut.setTooltip(new Tooltip("重置密码"));
resetBut.getStyleClass().add("left-pill");
editBut.getStyleClass().add("center-pill");
delBut.getStyleClass().add("right-pill");
try {
editBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".create-outline"));
resetBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".history"));
delBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".trash-outline"));
} catch (Exception e) {
e.printStackTrace();
}
editBut.setOnMouseClicked(event -> {
try {
tableView.getSelectionModel().select(getIndex());
actionHandler.navigate(UserEditController.class);
} catch (VetoException e) {
e.printStackTrace();
} catch (FlowException e) {
e.printStackTrace();
}
});
delBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
delete();
});
resetBut.setOnMouseClicked(event -> {
tableView.getSelectionModel().select(getIndex());
restPassword();
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
HBox hBox = new HBox(resetBut, editBut, delBut);
hBox.setSpacing(0);
hBox.setAlignment(Pos.CENTER);
setGraphic(hBox);
}
}
};
return cell;
}
};
operateColumn.setCellFactory(cellFactory);
FilteredList<UserVO> filteredData = new FilteredList<>(dataModel.getUsers(), p -> true);
tableView.setItems(filteredData);
searchField.textProperty().addListener((o, oldVal, newVal) -> {
filteredData.setPredicate(elementProp -> {
if (newVal == null || newVal.isEmpty()) {
return true;
}
String val = Pinyin4jUtil.toPinYinLowercase(newVal);
return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val)
|| elementProp.getName().toLowerCase().contains(val)
|| elementProp.getUserName().toLowerCase().contains(val);
});
});
dataModel.selectedPersonIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty());
pagination.pageCountProperty().bind(dataModel.pageCountProperty());
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer param) {
showPage(param + 1);
return tableView;
}
});
}
@ActionMethod("createUser")
private void createUser() {
try {
actionHandler.navigate(UserAddController.class);
} catch (VetoException e) {
e.printStackTrace();
} catch (FlowException e) {
e.printStackTrace();
}
}
@ActionMethod("cancel")
private void cancel() {
}
@ActionMethod("accept")
private void accept() {
JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setBody(new Label(userNameTextField.getText() + "\t" + accountTextField.getText() + "\t" + genderCombobox.getSelectionModel().getSelectedItem() + "\t" + descTextArea.getText()));
alert.setContent(layout);
alert.show();
}
private void restPassword() {
UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("消息提示"));
layout.setBody(new Label("确定要重置【" + userVO.getUserName() + "】登录密码吗?"));
JFXButton closeButton = new JFXButton("取消");
closeButton.setOnAction(event -> alert.hideWithAnimation());
JFXButton determineButton = new JFXButton("确定");
determineButton.setOnAction(event -> {
alert.hideWithAnimation();
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(UserFeign.class).restPassword(userVO.getId()))
.addConsumerInPlatformThread(result -> {
}).onException(e -> e.printStackTrace()).run();
});
layout.setActions(closeButton, determineButton);
alert.setContent(layout);
alert.show();
}
private void delete() {
UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow());
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("消息提示"));
layout.setBody(new Label("确实删除【" + userVO.getUserName() + "】吗?"));
JFXButton closeButton = new JFXButton("取消");
closeButton.setOnAction(event -> alert.hideWithAnimation());
JFXButton determineButton = new JFXButton("确定");
determineButton.setOnAction(event -> {
alert.hideWithAnimation();
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(UserFeign.class).delete(userVO.getId()))
.addConsumerInPlatformThread(result -> {
if (result.isRel()) {
dataModel.getUsers().remove(dataModel.getSelectedPersonIndex());
}
}).onException(e -> e.printStackTrace()).run();
});
layout.setActions(closeButton, determineButton);
alert.setContent(layout);
alert.show();
}
private void showPage(Integer page) {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("keyId", searchField.getText());
queryMap.put("page", page);
query(queryMap);
}
@ActionMethod("search")
private void search() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("keyId", searchField.getText());
query(queryMap);
}
private void query(Map<String, Object> queryMap) {
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
spinnerPane.setVisible(true);
centPane.setDisable(true);
})
.addSupplierInExecutor(() -> Request.connector(UserFeign.class).getPageList(queryMap)
)
.addConsumerInPlatformThread(result -> {
dataModel.getUsers().clear();
List<User> userList = result.getDatas();
dataModel.setPageCount((int) result.getTotal());
for (User user : userList) {
dataModel.getUsers().add(new UserVO(user.getId(), user.getName(), user.getUsername(), DateUtils.format(user.getUpdTime(), DateUtils.DATE_TIME_PATTERN), user.getUpdUser(), user.getSex(), user.getDescription()));
}
})
.withFinal(() -> {
spinnerPane.setVisible(false);
centPane.setDisable(false);
})
.onException(e -> e.printStackTrace())
.run();
}
@PreDestroy
private void destroy() {
System.err.println("destroy " + this);
}
@FXML
private void test() {
System.err.println();
}
}

View File

@@ -0,0 +1,96 @@
package com.epri.fx.client.gui.uicomponents.admin.user.components;
import com.epri.fx.client.gui.uicomponents.admin.user.UserManagementController;
import com.epri.fx.client.model.UserDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.UserFeign;
import com.epri.fx.server.entity.User;
import com.jfoenix.controls.*;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.action.BackAction;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.util.VetoException;
import io.datafx.core.concurrent.ProcessChain;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
/**
* @description:
* @className: UserAddController
* @author: liwen
* @date: 2020/7/3 17:04
*/
@ViewController(value = "/fxml/admin/user/user_detailed.fxml", title = "添加用户")
public class UserAddController {
@ActionHandler
private FlowActionHandler actionHandler;
@FXML
@BackAction
private JFXButton cancelBut;
@FXML
private Label title;
@FXML
@ActionTrigger("save")
private JFXButton saveBut;
@FXML
@ActionTrigger("update")
private JFXButton updateBut;
@FXML
private JFXTextField nameTextField;
@FXML
private JFXTextField userNameTextField;
@FXML
private JFXPasswordField pwdTextField;
@FXML
private JFXTextArea descTextArea;
@FXML
private JFXComboBox genderCombobox;
@Inject
private UserDataModel dataModel;
@PostConstruct
private void init() {
title.setText("添加用户");
updateBut.setVisible(false);
updateBut.managedProperty().bind(updateBut.visibleProperty());
}
@ActionMethod("save")
private void save() {
User user = new User();
user.setName(nameTextField.getText());
user.setDescription(descTextArea.getText());
user.setUsername(userNameTextField.getText());
user.setPassword(pwdTextField.getText());
user.setSex(genderCombobox.getSelectionModel().getSelectedIndex() == 0 ? "" : "");
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(UserFeign.class).add(user))
.addConsumerInPlatformThread(rel -> {
if (rel.isRel()) {
try {
actionHandler.navigate(UserManagementController.class);
} catch (VetoException e) {
e.printStackTrace();
} catch (FlowException e) {
e.printStackTrace();
}
}
}).run();
}
}

View File

@@ -0,0 +1,115 @@
package com.epri.fx.client.gui.uicomponents.admin.user.components;
import com.epri.fx.client.gui.uicomponents.admin.user.UserManagementController;
import com.epri.fx.client.model.UserDataModel;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.request.feign.admin.UserFeign;
import com.epri.fx.server.entity.User;
import com.epri.fx.server.vo.UserVO;
import com.jfoenix.controls.*;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.action.BackAction;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.util.VetoException;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
/**
* @description:
* @className: UserAddController
* @author: liwen
* @date: 2020/7/3 17:04
*/
@ViewController(value = "/fxml/admin/user/user_detailed.fxml", title = "编辑用户")
public class UserEditController {
@ActionHandler
private FlowActionHandler actionHandler;
@FXML
@BackAction
private JFXButton cancelBut;
@FXML
private Label title;
@FXML
private JFXButton saveBut;
@FXML
@ActionTrigger("update")
private JFXButton updateBut;
@FXML
private JFXTextField nameTextField;
@FXML
private JFXTextField userNameTextField;
@FXML
private JFXPasswordField pwdTextField;
@FXML
private JFXTextArea descTextArea;
@FXML
private JFXComboBox genderCombobox;
@Inject
private UserDataModel dataModel;
@PostConstruct
private void init() {
title.setText("编辑用户");
saveBut.managedProperty().bind(saveBut.visibleProperty());
pwdTextField.setDisable(true);
saveBut.setVisible(false);
genderCombobox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
userVO.setSex(newValue.intValue() == 0 ? "" : "");
}
});
UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
nameTextField.textProperty().bindBidirectional(userVO.nameProperty());
userNameTextField.textProperty().bindBidirectional(userVO.userNameProperty());
pwdTextField.textProperty().bindBidirectional(userVO.userNameProperty());
descTextArea.textProperty().bindBidirectional(userVO.descriptionProperty());
String sex = userVO.sexProperty().getValue();
genderCombobox.getSelectionModel().select("".equals(sex) ? 0 : 1);
}
@ActionMethod("update")
private void update() {
UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
User user = new User();
user.setId(userVO.getId());
user.setName(userVO.getName());
user.setDescription(userVO.getDescription());
user.setUsername(userVO.getUserName());
user.setSex(userVO.getSex());
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(UserFeign.class).update(user.getId(), user))
.addConsumerInPlatformThread((rel) -> {
if (rel.isRel()) {
try {
actionHandler.navigate(UserManagementController.class);
} catch (VetoException e) {
e.printStackTrace();
} catch (FlowException e) {
e.printStackTrace();
}
}
})
.run();
}
}

View File

@@ -0,0 +1,13 @@
package com.epri.fx.client.gui.uicomponents.basicInfo;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: BasicDataSetController
* @author: liwen
* @date: 2020/10/14 16:55
*/
@ViewController(value = "/fxml/basicInfo/basic_data_set.fxml", title = "基础数据", iconPath = "")
public class BasicDataSetController {
}

View File

@@ -0,0 +1,13 @@
package com.epri.fx.client.gui.uicomponents.basicInfo;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: BasicDataSetController
* @author: liwen
* @date: 2020/10/14 16:55
*/
@ViewController(value = "/fxml/basicInfo/coal_price_difference.fxml", title = "煤价差", iconPath = "")
public class CoalPriceDiffController {
}

View File

@@ -0,0 +1,13 @@
package com.epri.fx.client.gui.uicomponents.basicInfo;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: BasicDataSetController
* @author: liwen
* @date: 2020/10/14 16:55
*/
@ViewController(value = "/fxml/basicInfo/current_freight.fxml", title = "现行运价", iconPath = "")
public class CurrentFreightController {
}

View File

@@ -0,0 +1,13 @@
package com.epri.fx.client.gui.uicomponents.basicInfo;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: BasicDataSetController
* @author: liwen
* @date: 2020/10/14 16:55
*/
@ViewController(value = "/fxml/basicInfo/main_conclusion.fxml", title = "主要结论", iconPath = "")
public class MainConclusionController {
}

View File

@@ -0,0 +1,13 @@
package com.epri.fx.client.gui.uicomponents.basicInfo;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: BasicDataSetController
* @author: liwen
* @date: 2020/10/14 16:55
*/
@ViewController(value = "/fxml/basicInfo/railway_cost.fxml", title = "铁路成本", iconPath = "")
public class RailwayCostController {
}

View File

@@ -0,0 +1,73 @@
package com.epri.fx.client.gui.uicomponents.container;
import com.jfoenix.controls.JFXTabPane;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView;
import io.datafx.controller.context.ViewContext;
import io.datafx.controller.flow.FlowContainer;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
/**
* @description:
* @className: TabPaneFlowContainer
* @author: liwen
* @date: 2020/6/24 18:09
*/
public class TabPaneFlowContainer implements FlowContainer<JFXTabPane> {
private final JFXTabPane tabPane;
private final HashMap<String, Tab> tabsMap = new HashMap<>();
public TabPaneFlowContainer() {
this(new JFXTabPane());
}
public TabPaneFlowContainer(JFXTabPane tabPane) {
this.tabPane = tabPane;
this.tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);
}
@Override
public <U> void setViewContext(ViewContext<U> context) {
String title = context.getMetadata().getTitle();
Class controller = context.getController().getClass();
Tab tab = tabsMap.get(controller.getName());
if (tab == null ) {
tab = new Tab(title);
tab.setUserData(context.getController());
tab.setContent(context.getRootNode());
tabPane.getTabs().add(tab);
tabsMap.put(controller.getName(), tab);
tab.setGraphic(new MaterialDesignIconView(MaterialDesignIcon.HOME));
tab.setOnClosed(event -> {
tabsMap.remove(controller.getName());
try {
context.destroy();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
}
tabPane.getSelectionModel().select(tab);
}
@Override
public JFXTabPane getView() {
return tabPane;
}
}

View File

@@ -0,0 +1,76 @@
package com.epri.fx.client.gui.uicomponents.control;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeItem;
import java.lang.reflect.Field;
public class FilterableCheckBoxTreeItem<T> extends CheckBoxTreeItem<T> {
final private ObservableList<TreeItem<T>> sourceList;
private FilteredList<TreeItem<T>> filteredList;
private ObjectProperty<TreeItemPredicate<T>> predicate = new SimpleObjectProperty<>();
public FilterableCheckBoxTreeItem(T value) {
super(value);
this.sourceList = FXCollections.observableArrayList();
this.filteredList = new FilteredList<>(this.sourceList);
this.filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> {
return child -> {
// Set the predicate of child items to force filtering
if (child instanceof FilterableCheckBoxTreeItem) {
FilterableCheckBoxTreeItem<T> filterableChild = (FilterableCheckBoxTreeItem<T>) child;
filterableChild.setPredicate(this.predicate.get());
}
// If there is no predicate, keep this tree item
if (this.predicate.get() == null) {
return true;
}
// If there are children, keep this tree item
if (child.getChildren().size() > 0) {
return true;
}
// Otherwise ask the TreeItemPredicate
return this.predicate.get().test(this, child.getValue());
};
}, this.predicate));
setHiddenFieldChildren(this.filteredList);
}
protected void setHiddenFieldChildren(ObservableList<TreeItem<T>> list) {
try {
Field childrenField = TreeItem.class.getDeclaredField("children"); //$NON-NLS-1$
childrenField.setAccessible(true);
childrenField.set(this, list);
Field declaredField = TreeItem.class.getDeclaredField("childrenListener"); //$NON-NLS-1$
declaredField.setAccessible(true);
list.addListener((ListChangeListener<? super TreeItem<T>>) declaredField.get(this));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Could not set TreeItem.children", e); //$NON-NLS-1$
}
}
public ObservableList<TreeItem<T>> getInternalChildren() {
return this.sourceList;
}
public void setPredicate(TreeItemPredicate<T> predicate) {
this.predicate.set(predicate);
}
public TreeItemPredicate getPredicate() {
return predicate.get();
}
public ObjectProperty<TreeItemPredicate<T>> predicateProperty() {
return predicate;
}
}

View File

@@ -0,0 +1,75 @@
package com.epri.fx.client.gui.uicomponents.control;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.control.TreeItem;
import java.lang.reflect.Field;
public class FilterableTreeItem<T> extends TreeItem<T> {
final private ObservableList<TreeItem<T>> sourceList;
private FilteredList<TreeItem<T>> filteredList;
private ObjectProperty<TreeItemPredicate<T>> predicate = new SimpleObjectProperty<>();
public FilterableTreeItem(T value) {
super(value);
this.sourceList = FXCollections.observableArrayList();
this.filteredList = new FilteredList<>(this.sourceList);
this.filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> {
return child -> {
// Set the predicate of child items to force filtering
if (child instanceof FilterableTreeItem) {
FilterableTreeItem<T> filterableChild = (FilterableTreeItem<T>) child;
filterableChild.setPredicate(this.predicate.get());
}
// If there is no predicate, keep this tree item
if (this.predicate.get() == null) {
return true;
}
// If there are children, keep this tree item
if (child.getChildren().size() > 0) {
return true;
}
// Otherwise ask the TreeItemPredicate
return this.predicate.get().test(this, child.getValue());
};
}, this.predicate));
setHiddenFieldChildren(this.filteredList);
}
protected void setHiddenFieldChildren(ObservableList<TreeItem<T>> list) {
try {
Field childrenField = TreeItem.class.getDeclaredField("children"); //$NON-NLS-1$
childrenField.setAccessible(true);
childrenField.set(this, list);
Field declaredField = TreeItem.class.getDeclaredField("childrenListener"); //$NON-NLS-1$
declaredField.setAccessible(true);
list.addListener((ListChangeListener<? super TreeItem<T>>) declaredField.get(this));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Could not set TreeItem.children", e); //$NON-NLS-1$
}
}
public ObservableList<TreeItem<T>> getInternalChildren() {
return this.sourceList;
}
public void setPredicate(TreeItemPredicate<T> predicate) {
this.predicate.set(predicate);
}
public TreeItemPredicate getPredicate() {
return predicate.get();
}
public ObjectProperty<TreeItemPredicate<T>> predicateProperty() {
return predicate;
}
}

View File

@@ -0,0 +1,653 @@
package com.epri.fx.client.gui.uicomponents.control;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.svg.SVGGlyph;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.BoundingBox;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Shadow;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.List;
/**
* Window Decorator allow to resize/move its content Note: the default close button will call stage.close() which will
* only close the current stage. it will not close the java application, however it can be customized by calling {@link
* #setOnCloseButtonAction(Runnable)}
*
* @author Shadi Shaheen
* @version 1.0
* @since 2016-03-09
*/
public class LFXDecorator extends StackPane {
private Stage primaryStage;
private VBox contentPane = new VBox();
private double snapped_inset = 6;
private double xOffset = 0;
private double yOffset = 0;
private double newX, newY, initX, initY, initWidth = -1, initHeight = -1,
initStageX = -1, initStageY = -1;
private boolean allowMove = false;
private boolean isDragging = false;
private Timeline windowDecoratorAnimation;
private StackPane contentPlaceHolder = new StackPane();
private HBox buttonsContainer;
private ObjectProperty<Runnable> onCloseButtonAction = new SimpleObjectProperty<>(() ->
primaryStage.fireEvent(new WindowEvent(primaryStage, WindowEvent.WINDOW_CLOSE_REQUEST)));
private BooleanProperty customMaximize = new SimpleBooleanProperty(false);
private boolean maximized = false;
private BoundingBox originalBox;
private BoundingBox maximizedBox;
protected JFXButton btnMax;
protected JFXButton btnFull;
protected JFXButton btnClose;
protected JFXButton btnMin;
protected StringProperty title = new SimpleStringProperty();
protected Text text;
protected Node graphic;
protected HBox graphicContainer;
/**
* Create a window decorator for the specified node with the options:
* - full screen
* - maximize
* - minimize
*
* @param stage the primary stage used by the application
* @param node the node to be decorated
*/
public LFXDecorator(Stage stage, Node node) {
this(stage, node, true, true, true);
}
/**
* Create a window decorator for the specified node with the options:
* - full screen
* - maximize
* - minimize
*
* @param stage the primary stage used by the application
* @param node the node to be decorated
* @param fullScreen indicates whether to show full screen option or not
* @param max indicates whether to show maximize option or not
* @param min indicates whether to show minimize option or not
*/
public LFXDecorator(Stage stage, Node node, boolean fullScreen, boolean max, boolean min) {
primaryStage = stage;
// Note that setting the style to TRANSPARENT is causing performance
// degradation, as an alternative we set it to UNDECORATED instead.
primaryStage.initStyle(StageStyle.TRANSPARENT);
setPickOnBounds(false);
getStyleClass().add("lfx-decorator");
initializeButtons();
initializeContainers(node, fullScreen, max, min);
primaryStage.fullScreenProperty().addListener((o, oldVal, newVal) -> {
if (newVal) {
// remove border
contentPlaceHolder.getStyleClass().remove("resize-border");
/*
* note the border property MUST NOT be bound to another property
* when going full screen mode, thus the binding will be lost if exisited
*/
contentPlaceHolder.borderProperty().unbind();
contentPlaceHolder.setBorder(Border.EMPTY);
if (windowDecoratorAnimation != null) {
windowDecoratorAnimation.stop();
}
windowDecoratorAnimation = new Timeline(new KeyFrame(Duration.millis(320),
new KeyValue(this.translateYProperty(),
-buttonsContainer.getHeight(),
Interpolator.EASE_BOTH)));
windowDecoratorAnimation.setOnFinished((finish) -> {
this.getChildren().remove(buttonsContainer);
this.setTranslateY(0);
});
windowDecoratorAnimation.play();
} else {
// add border
if (windowDecoratorAnimation != null) {
if (windowDecoratorAnimation.getStatus() == Animation.Status.RUNNING) {
windowDecoratorAnimation.stop();
} else {
this.getChildren().add(0, buttonsContainer);
}
}
this.setTranslateY(-buttonsContainer.getHeight());
windowDecoratorAnimation = new Timeline(new KeyFrame(Duration.millis(320),
new KeyValue(this.translateYProperty(),
0,
Interpolator.EASE_BOTH)));
windowDecoratorAnimation.setOnFinished((finish) -> {
contentPlaceHolder.setBorder(new Border(new BorderStroke(Color.BLACK,
BorderStrokeStyle.SOLID,
CornerRadii.EMPTY,
new BorderWidths(0, 4, 4, 4))));
contentPlaceHolder.getStyleClass().add("resize-border");
});
windowDecoratorAnimation.play();
}
});
this.addEventHandler(MouseEvent.MOUSE_PRESSED, (mouseEvent) ->
updateInitMouseValues(mouseEvent));
this.addEventHandler(MouseEvent.MOUSE_PRESSED, (mouseEvent) ->
updateInitMouseValues(mouseEvent));
// show the drag cursor on the borders
addEventFilter(MouseEvent.MOUSE_MOVED, (mouseEvent) -> showDragCursorOnBorders(mouseEvent));
// handle drag events on the decorator pane
addEventFilter(MouseEvent.MOUSE_RELEASED, (mouseEvent) -> isDragging = false);
this.setOnMouseDragged((mouseEvent) -> handleDragEventOnDecoratorPane(mouseEvent));
}
private void initializeButtons() {
SVGGlyph full = new SVGGlyph(0,
"FULLSCREEN",
"M598 214h212v212h-84v-128h-128v-84zM726 726v-128h84v212h-212v-84h128zM214 426v-212h212v84h-128v128h-84zM298 598v128h128v84h-212v-212h84z",
Color.WHITE);
full.setSize(16, 16);
SVGGlyph minus = new SVGGlyph(0,
"MINUS",
"M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z",
Color.WHITE);
minus.setSize(12, 2);
minus.setTranslateY(4);
SVGGlyph resizeMax = new SVGGlyph(0,
"RESIZE_MAX",
"M726 810v-596h-428v596h428zM726 44q34 0 59 25t25 59v768q0 34-25 60t-59 26h-428q-34 0-59-26t-25-60v-768q0-34 25-60t59-26z",
Color.WHITE);
resizeMax.setSize(12, 12);
SVGGlyph resizeMin = new SVGGlyph(0,
"RESIZE_MIN",
"M80.842 943.158v-377.264h565.894v377.264h-565.894zM0 404.21v619.79h727.578v-619.79h-727.578zM377.264 161.684h565.894v377.264h-134.736v80.842h215.578v-619.79h-727.578v323.37h80.842v-161.686z",
Color.WHITE);
resizeMin.setSize(12, 12);
SVGGlyph close = new SVGGlyph(0,
"CLOSE",
"M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z",
Color.WHITE);
close.setSize(12, 12);
btnFull = new JFXButton();
btnFull.getStyleClass().add("lfx-decorator-button");
btnFull.setCursor(Cursor.HAND);
btnFull.setOnAction((action) -> primaryStage.setFullScreen(!primaryStage.isFullScreen()));
btnFull.setGraphic(full);
btnFull.setTranslateX(-30);
btnFull.setRipplerFill(Color.WHITE);
btnClose = new JFXButton();
btnClose.getStyleClass().add("lfx-decorator-button");
btnClose.setCursor(Cursor.HAND);
btnClose.setOnAction((action) -> onCloseButtonAction.get().run());
btnClose.setGraphic(close);
btnClose.setRipplerFill(Color.WHITE);
btnMin = new JFXButton();
btnMin.getStyleClass().add("lfx-decorator-button");
btnMin.setCursor(Cursor.HAND);
btnMin.setOnAction((action) -> primaryStage.setIconified(true));
btnMin.setGraphic(minus);
btnMin.setRipplerFill(Color.WHITE);
btnMax = new JFXButton();
btnMax.getStyleClass().add("lfx-decorator-button");
btnMax.setCursor(Cursor.HAND);
btnMax.setRipplerFill(Color.WHITE);
btnMax.setOnAction((action) -> maximize(resizeMin, resizeMax));
btnMax.setGraphic(resizeMax);
}
private void maximize(SVGGlyph resizeMin, SVGGlyph resizeMax) {
if (!isCustomMaximize()) {
primaryStage.setMaximized(!primaryStage.isMaximized());
maximized = primaryStage.isMaximized();
if (primaryStage.isMaximized()) {
btnMax.setGraphic(resizeMin);
btnMax.setTooltip(new Tooltip("Restore Down"));
} else {
btnMax.setGraphic(resizeMax);
btnMax.setTooltip(new Tooltip("Maximize"));
}
} else {
if (!maximized) {
// store original bounds
originalBox = new BoundingBox(primaryStage.getX(), primaryStage.getY(), primaryStage.getWidth(), primaryStage.getHeight());
// get the max stage bounds
Screen screen = Screen.getScreensForRectangle(primaryStage.getX(),
primaryStage.getY(),
primaryStage.getWidth(),
primaryStage.getHeight()).get(0);
Rectangle2D bounds = screen.getVisualBounds();
maximizedBox = new BoundingBox(bounds.getMinX(),
bounds.getMinY(),
bounds.getWidth(),
bounds.getHeight());
// maximized the stage
primaryStage.setX(maximizedBox.getMinX());
primaryStage.setY(maximizedBox.getMinY());
primaryStage.setWidth(maximizedBox.getWidth());
primaryStage.setHeight(maximizedBox.getHeight());
btnMax.setGraphic(resizeMin);
btnMax.setTooltip(new Tooltip("Restore Down"));
this.setPadding(new Insets(0,0,0,0));
} else {
// restore stage to its original size
primaryStage.setX(originalBox.getMinX());
primaryStage.setY(originalBox.getMinY());
primaryStage.setWidth(originalBox.getWidth());
primaryStage.setHeight(originalBox.getHeight());
originalBox = null;
btnMax.setGraphic(resizeMax);
btnMax.setTooltip(new Tooltip("Maximize"));
this.setPadding(new Insets(3,3,3,3));
}
maximized = !maximized;
}
}
private void initializeContainers(Node node, boolean fullScreen, boolean max, boolean min) {
buttonsContainer = new HBox();
buttonsContainer.getStyleClass().add("lfx-decorator-buttons-container");
buttonsContainer.setBackground(new Background(new BackgroundFill(Color.BLACK,
CornerRadii.EMPTY,
Insets.EMPTY)));
// BINDING
buttonsContainer.setPadding(new Insets(4));
buttonsContainer.setAlignment(Pos.CENTER_RIGHT);
// customize decorator buttons
List<JFXButton> btns = new ArrayList<>();
if (fullScreen) {
btns.add(btnFull);
}
if (min) {
btns.add(btnMin);
}
if (max) {
btns.add(btnMax);
// maximize/restore the window on header double click
buttonsContainer.addEventHandler(MouseEvent.MOUSE_CLICKED, (mouseEvent) -> {
if (mouseEvent.getClickCount() == 2) {
btnMax.fire();
}
});
}
btns.add(btnClose);
text = new Text();
text.getStyleClass().addAll("lfx-decorator-text", "title", "lfx-decorator-title");
text.setFill(Color.WHITE);
text.textProperty().bind(title); //binds the Text's text to title
title.bind(primaryStage.titleProperty()); //binds title to the primaryStage's title
graphicContainer = new HBox();
graphicContainer.setPickOnBounds(false);
graphicContainer.setAlignment(Pos.CENTER_LEFT);
graphicContainer.getChildren().setAll(text);
HBox graphicTextContainer = new HBox(graphicContainer, text);
graphicTextContainer.getStyleClass().add("lfx-decorator-title-container");
graphicTextContainer.setAlignment(Pos.CENTER_LEFT);
graphicTextContainer.setPickOnBounds(false);
HBox.setHgrow(graphicTextContainer, Priority.ALWAYS);
HBox.setMargin(graphicContainer, new Insets(0, 8, 0, 8));
buttonsContainer.getChildren().setAll(graphicTextContainer);
buttonsContainer.getChildren().addAll(btns);
buttonsContainer.addEventHandler(MouseEvent.MOUSE_ENTERED, (enter) -> allowMove = true);
buttonsContainer.addEventHandler(MouseEvent.MOUSE_EXITED, (enter) -> {
if (!isDragging) {
allowMove = false;
}
});
buttonsContainer.setMinWidth(180);
contentPlaceHolder.getStyleClass().add("lfx-decorator-content-container");
contentPlaceHolder.setMinSize(0, 0);
StackPane clippedContainer = new StackPane(node);
contentPlaceHolder.getChildren().add(clippedContainer);
((Region) node).setMinSize(0, 0);
contentPlaceHolder.getStyleClass().add("resize-border");
// BINDING
Rectangle clip = new Rectangle();
clip.setArcWidth(20);
clip.setArcHeight(20);
clip.widthProperty().bind(contentPane.widthProperty());
clip.heightProperty().bind(contentPane.heightProperty());
VBox.setVgrow(contentPlaceHolder, Priority.ALWAYS);
contentPane.getChildren().addAll(buttonsContainer, contentPlaceHolder);
contentPane.setClip(clip);
this.setPadding(new Insets(3,3,3,3));
this.getChildren().addAll(contentPane);
}
private void showDragCursorOnBorders(MouseEvent mouseEvent) {
if (primaryStage.isFullScreen() || maximized) {
this.setCursor(Cursor.DEFAULT);
return; // maximized mode does not support resize
}
if (!primaryStage.isResizable()) {
return;
}
double x = mouseEvent.getX();
double y = mouseEvent.getY();
double borderWidth = 20;
if (isRightEdge(x)) {
if (y < borderWidth) {
this.setCursor(Cursor.NE_RESIZE);
} else if (y > this.getHeight() - borderWidth) {
this.setCursor(Cursor.SE_RESIZE);
} else {
this.setCursor(Cursor.E_RESIZE);
}
} else if (isLeftEdge(x)) {
if (y < borderWidth) {
this.setCursor(Cursor.NW_RESIZE);
} else if (y > this.getHeight() - borderWidth) {
this.setCursor(Cursor.SW_RESIZE);
} else {
this.setCursor(Cursor.W_RESIZE);
}
} else if (isTopEdge(y)) {
this.setCursor(Cursor.N_RESIZE);
} else if (isBottomEdge(y)) {
this.setCursor(Cursor.S_RESIZE);
} else {
this.setCursor(Cursor.DEFAULT);
}
}
private void handleDragEventOnDecoratorPane(MouseEvent mouseEvent) {
isDragging = true;
if (!mouseEvent.isPrimaryButtonDown() || (xOffset == -1 && yOffset == -1)) {
return;
}
/*
* Long press generates drag event!
*/
if (primaryStage.isFullScreen() || maximized) {
return;
}
newX = mouseEvent.getScreenX();
newY = mouseEvent.getScreenY();
double deltax = newX - initX;
double deltay = newY - initY;
Cursor cursor = this.getCursor();
if (Cursor.E_RESIZE.equals(cursor)) {
setStageWidth(initWidth + deltax);
mouseEvent.consume();
} else if (Cursor.NE_RESIZE.equals(cursor)) {
if (setStageHeight(initHeight - deltay)) {
primaryStage.setY(initStageY + deltay);
}
setStageWidth(initWidth + deltax);
mouseEvent.consume();
} else if (Cursor.SE_RESIZE.equals(cursor)) {
setStageWidth(initWidth + deltax);
setStageHeight(initHeight + deltay);
mouseEvent.consume();
} else if (Cursor.S_RESIZE.equals(cursor)) {
setStageHeight(initHeight + deltay);
mouseEvent.consume();
} else if (Cursor.W_RESIZE.equals(cursor)) {
if (setStageWidth(initWidth - deltax)) {
primaryStage.setX(initStageX + deltax);
}
mouseEvent.consume();
} else if (Cursor.SW_RESIZE.equals(cursor)) {
if (setStageWidth(initWidth - deltax)) {
primaryStage.setX(initStageX + deltax);
}
setStageHeight(initHeight + deltay);
mouseEvent.consume();
} else if (Cursor.NW_RESIZE.equals(cursor)) {
if (setStageWidth(initWidth - deltax)) {
primaryStage.setX(initStageX + deltax);
}
if (setStageHeight(initHeight - deltay)) {
primaryStage.setY(initStageY + deltay);
}
mouseEvent.consume();
} else if (Cursor.N_RESIZE.equals(cursor)) {
if (setStageHeight(initHeight - deltay)) {
primaryStage.setY(initStageY + deltay);
}
mouseEvent.consume();
} else if (allowMove) {
primaryStage.setX(mouseEvent.getScreenX() - xOffset);
primaryStage.setY(mouseEvent.getScreenY() - yOffset);
mouseEvent.consume();
}
}
private void updateInitMouseValues(MouseEvent mouseEvent) {
initStageX = primaryStage.getX();
initStageY = primaryStage.getY();
initWidth = primaryStage.getWidth();
initHeight = primaryStage.getHeight();
initX = mouseEvent.getScreenX();
initY = mouseEvent.getScreenY();
xOffset = mouseEvent.getSceneX();
yOffset = mouseEvent.getSceneY();
}
private boolean isRightEdge(double x) {
final double width = this.getWidth();
return x < width && x > width - snapped_inset;
}
private boolean isTopEdge(double y) {
return y >= 0 && y < snapped_inset;
}
private boolean isBottomEdge(double y) {
final double height = this.getHeight();
return y < height && y > height - snapped_inset;
}
private boolean isLeftEdge(double x) {
return x >= 0 && x < snapped_inset;
}
boolean setStageWidth(double width) {
if (width >= primaryStage.getMinWidth() && width >= buttonsContainer.getMinWidth()) {
primaryStage.setWidth(width);
// initX = newX;
return true;
} else if (width >= primaryStage.getMinWidth() && width <= buttonsContainer.getMinWidth()) {
width = buttonsContainer.getMinWidth();
primaryStage.setWidth(width);
}
return false;
}
boolean setStageHeight(double height) {
if (height >= primaryStage.getMinHeight() && height >= buttonsContainer.getHeight()) {
primaryStage.setHeight(height);
// initY = newY;
return true;
} else if (height >= primaryStage.getMinHeight() && height <= buttonsContainer.getHeight()) {
height = buttonsContainer.getHeight();
primaryStage.setHeight(height);
}
return false;
}
/**
* set a speficed runnable when clicking on the close button
*
* @param onCloseButtonAction runnable to be executed
*/
public void setOnCloseButtonAction(Runnable onCloseButtonAction) {
this.onCloseButtonAction.set(onCloseButtonAction);
}
/**
* this property is used to replace JavaFX maximization
* with a custom one that prevents hiding windows taskbar when
* the JFXDecorator is maximized.
*
* @return customMaximizeProperty whether to use custom maximization or not.
*/
public final BooleanProperty customMaximizeProperty() {
return this.customMaximize;
}
/**
* @return whether customMaximizeProperty is active or not
*/
public final boolean isCustomMaximize() {
return this.customMaximizeProperty().get();
}
/**
* set customMaximize property
*
* @param customMaximize
*/
public final void setCustomMaximize(final boolean customMaximize) {
this.customMaximizeProperty().set(customMaximize);
}
/**
* @param maximized
*/
public void setMaximized(boolean maximized) {
if (this.maximized != maximized) {
Platform.runLater(() -> {
btnMax.fire();
});
}
}
/**
* will change the decorator content
*
* @param content
*/
public void setContent(Node content) {
this.contentPlaceHolder.getChildren().setAll(content);
}
/**
* will set the title
*
* @param text
* @deprecated Use {@link LFXDecorator#setTitle(String)} instead.
*/
public void setText(String text) {
setTitle(text);
}
/**
* will get the title
*
* @deprecated Use {@link LFXDecorator#setTitle(String)} instead.
*/
public String getText() {
return getTitle();
}
public String getTitle() {
return title.get();
}
/**
* By default this title property is bound to the primaryStage's title property.
* <p>
* To change it to something else, use <pre>
* {@code jfxDecorator.titleProperty().unbind();}</pre> first.
*/
public StringProperty titleProperty() {
return title;
}
/**
* If you want the {@code primaryStage}'s title and the {@code JFXDecorator}'s title to be different, then
* go ahead and use this method.
* <p>
* By default, this title property is bound to the {@code primaryStage}'s title property-so merely setting the
* {@code primaryStage}'s title, will set the {@code JFXDecorator}'s title.
*/
public void setTitle(String title) {
this.title.unbind();
this.title.set(title);
}
public void setGraphic(Node node) {
if (graphic != null) {
graphicContainer.getChildren().remove(graphic);
}
if (node != null) {
graphicContainer.getChildren().add(0, node);
}
graphic = node;
}
public Node getGraphic() {
return graphic;
}
}

View File

@@ -0,0 +1,16 @@
package com.epri.fx.client.gui.uicomponents.control;
import javafx.scene.control.TreeItem;
import java.util.function.Predicate;
@FunctionalInterface
public interface TreeItemPredicate<T> {
boolean test(TreeItem<T> parent, T value);
static <T> TreeItemPredicate<T> create(Predicate<T> predicate) {
return (parent, value) -> predicate.test(value);
}
}

View File

@@ -0,0 +1,447 @@
package com.epri.fx.client.gui.uicomponents.home;
import com.epri.fx.client.bean.CountryPath;
import eu.hansolo.tilesfx.Tile;
import eu.hansolo.tilesfx.TileBuilder;
import eu.hansolo.tilesfx.TimeSection;
import eu.hansolo.tilesfx.TimeSectionBuilder;
import eu.hansolo.tilesfx.addons.Indicator;
import eu.hansolo.tilesfx.chart.ChartData;
import eu.hansolo.tilesfx.chart.RadarChart;
import eu.hansolo.tilesfx.chart.TilesFXSeries;
import eu.hansolo.tilesfx.colors.Bright;
import eu.hansolo.tilesfx.colors.Dark;
import eu.hansolo.tilesfx.skins.BarChartItem;
import eu.hansolo.tilesfx.skins.LeaderBoardItem;
import eu.hansolo.tilesfx.tools.Country;
import eu.hansolo.tilesfx.tools.FlowGridPane;
import eu.hansolo.tilesfx.tools.Helper;
import eu.hansolo.tilesfx.tools.Location;
import eu.hansolo.tilesfx.weather.DarkSky;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import javafx.animation.AnimationTimer;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.text.TextAlignment;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static javafx.scene.layout.Region.USE_COMPUTED_SIZE;
import static javafx.scene.layout.Region.USE_PREF_SIZE;
/**
* @description:
* @className: HomeController
* @author: liwen
* @date: 2020/6/24 18:16
*/
@ViewController(value = "/fxml/home/home.fxml", title = "主页", iconPath = "")
public class HomeController {
@ActionHandler
private FlowActionHandler actionHandler;
public static final Color BACKGROUND = Color.rgb(39, 49, 66); // #2a2a2a
public static final Color BORDERCOLOR = Color.rgb(49, 61, 79); // #2a2a2a
private static final Random RND = new Random();
private int noOfNodes = 0;
private BarChartItem barChartItem1;
private BarChartItem barChartItem2;
private BarChartItem barChartItem3;
private BarChartItem barChartItem4;
private LeaderBoardItem leaderBoardItem1;
private LeaderBoardItem leaderBoardItem2;
private LeaderBoardItem leaderBoardItem3;
private LeaderBoardItem leaderBoardItem4;
private ChartData chartData1;
private ChartData chartData2;
private ChartData chartData3;
private ChartData chartData4;
private ChartData chartData5;
private ChartData chartData6;
private ChartData chartData7;
private ChartData chartData8;
private ChartData smoothChartData1;
private ChartData smoothChartData2;
private ChartData smoothChartData3;
private ChartData smoothChartData4;
private Tile radialChartTile;
private Tile donutChartTile;
private Tile circularProgressTile;
private Tile radarChartTile1;
private Tile worldTile;
private Tile ephemerisTile;
private Tile statusTile;
private Tile sparkLineTile;
private Tile areaChartTile;
private Tile lineChartTile;
private long lastTimerCall;
private AnimationTimer timer;
private DoubleProperty value;
private Map<String, List<CountryPath>> hiresCountryPaths = new ConcurrentHashMap<>();
@FXML
private GridPane centerPane;
@PostConstruct
private void init() {
long start = System.currentTimeMillis();
value = new SimpleDoubleProperty(0);
// AreaChart Data
XYChart.Series<String, Number> series1 = new XYChart.Series();
series1.setName("Whatever");
series1.getData().add(new XYChart.Data("MO", 23));
series1.getData().add(new XYChart.Data("TU", 21));
series1.getData().add(new XYChart.Data("WE", 20));
series1.getData().add(new XYChart.Data("TH", 22));
series1.getData().add(new XYChart.Data("FR", 24));
series1.getData().add(new XYChart.Data("SA", 22));
series1.getData().add(new XYChart.Data("SU", 20));
// LineChart Data
XYChart.Series<String, Number> series2 = new XYChart.Series();
series2.setName("Inside");
series2.getData().add(new XYChart.Data("MO", 8));
series2.getData().add(new XYChart.Data("TU", 5));
series2.getData().add(new XYChart.Data("WE", 0));
series2.getData().add(new XYChart.Data("TH", 2));
series2.getData().add(new XYChart.Data("FR", 4));
series2.getData().add(new XYChart.Data("SA", 3));
series2.getData().add(new XYChart.Data("SU", 5));
XYChart.Series<String, Number> series3 = new XYChart.Series();
series3.setName("Outside");
series3.getData().add(new XYChart.Data("MO", 8));
series3.getData().add(new XYChart.Data("TU", 5));
series3.getData().add(new XYChart.Data("WE", 0));
series3.getData().add(new XYChart.Data("TH", 2));
series3.getData().add(new XYChart.Data("FR", 4));
series3.getData().add(new XYChart.Data("SA", 3));
series3.getData().add(new XYChart.Data("SU", 5));
// WorldMap Data
for (int i = 0; i < Country.values().length; i++) {
double value = RND.nextInt(10);
Color color;
if (value > 8) {
color = Tile.RED;
} else if (value > 6) {
color = Tile.ORANGE;
} else if (value > 4) {
color = Tile.YELLOW_ORANGE;
} else if (value > 2) {
color = Tile.GREEN;
} else {
color = Tile.BLUE;
}
Country.values()[i].setColor(color);
}
// TimeControl Data
TimeSection timeSection = TimeSectionBuilder.create()
.start(LocalTime.now().plusSeconds(20))
.stop(LocalTime.now().plusHours(1))
//.days(DayOfWeek.MONDAY, DayOfWeek.FRIDAY)
.color(Tile.GRAY)
.highlightColor(Tile.RED)
.build();
timeSection.setOnTimeSectionEntered(e -> System.out.println("Section ACTIVE"));
timeSection.setOnTimeSectionLeft(e -> System.out.println("Section INACTIVE"));
// Weather (You can get a DarkSky API key here: https://darksky.net/dev/ )
DarkSky darkSky = new DarkSky("YOUR DARKSKY API KEY", DarkSky.Unit.CA, DarkSky.Language.ENGLISH, 51.911858, 7.632815);
//darkSky.update();
// BarChart Items
barChartItem1 = new BarChartItem("Gerrit", 47, Tile.BLUE);
barChartItem2 = new BarChartItem("Sandra", 43, Tile.RED);
barChartItem3 = new BarChartItem("Lilli", 12, Tile.GREEN);
barChartItem4 = new BarChartItem("Anton", 8, Tile.ORANGE);
barChartItem1.setFormatString("%.1f kWh");
// LeaderBoard Items
leaderBoardItem1 = new LeaderBoardItem("Gerrit", 47);
leaderBoardItem2 = new LeaderBoardItem("Sandra", 43);
leaderBoardItem3 = new LeaderBoardItem("Lilli", 12);
leaderBoardItem4 = new LeaderBoardItem("Anton", 8);
// Chart Data
chartData1 = new ChartData("Item 1", 24.0, Tile.GREEN);
chartData2 = new ChartData("Item 2", 10.0, Tile.BLUE);
chartData3 = new ChartData("Item 3", 12.0, Tile.RED);
chartData4 = new ChartData("Item 4", 13.0, Tile.YELLOW_ORANGE);
chartData5 = new ChartData("Item 5", 13.0, Tile.BLUE);
chartData6 = new ChartData("Item 6", 13.0, Tile.BLUE);
chartData7 = new ChartData("Item 7", 13.0, Tile.BLUE);
chartData8 = new ChartData("Item 8", 13.0, Tile.BLUE);
//ChartData.animated = false;
smoothChartData1 = new ChartData("Item 1", RND.nextDouble() * 25, Tile.BLUE);
smoothChartData2 = new ChartData("Item 2", RND.nextDouble() * 25, Tile.BLUE);
smoothChartData3 = new ChartData("Item 3", RND.nextDouble() * 25, Tile.BLUE);
smoothChartData4 = new ChartData("Item 4", RND.nextDouble() * 25, Tile.BLUE);
sparkLineTile = TileBuilder.create()
.skinType(Tile.SkinType.SPARK_LINE)
.title("SparkLine Tile")
.unit("mb").borderRadius(14)
.gradientStops(new Stop(0, Tile.GREEN),
new Stop(0.5, Tile.YELLOW),
new Stop(1.0, Tile.RED))
.strokeWithGradient(true)
.backgroundColor(BACKGROUND).borderColor(BORDERCOLOR).borderWidth(0.8d)
//.smoothing(true)
.build();
areaChartTile = TileBuilder.create()
.skinType(Tile.SkinType.SMOOTHED_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.title("SmoothedChart Tile")
.chartType(Tile.ChartType.AREA)
//.animated(true)
.smoothing(true)
.tooltipTimeout(1000)
.tilesFxSeries(new TilesFXSeries<>(series1,
Tile.BLUE,
new LinearGradient(0, 0, 0, 1,
true, CycleMethod.NO_CYCLE,
new Stop(0, Tile.BLUE),
new Stop(1, Color.TRANSPARENT))))
.build();
lineChartTile = TileBuilder.create()
.skinType(Tile.SkinType.SMOOTHED_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.title("SmoothedChart Tile")
//.animated(true)
.smoothing(false)
.series(series2, series3)
.build();
worldTile = TileBuilder.create()
.skinType(Tile.SkinType.WORLDMAP).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.title("WorldMap Tile")
.text("Whatever text")
.textVisible(false)
.build();
radialChartTile = TileBuilder.create()
.skinType(Tile.SkinType.RADIAL_CHART).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.title("RadialChart")
.text("Some text")
.textVisible(false)
.chartData(chartData1, chartData2, chartData3, chartData4)
.build();
donutChartTile = TileBuilder.create()
.skinType(Tile.SkinType.DONUT_CHART)
.title("DonutChart").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.text("Some text")
.textVisible(false)
.chartData(chartData1, chartData2, chartData3, chartData4)
.build();
circularProgressTile = TileBuilder.create()
.skinType(Tile.SkinType.CIRCULAR_PROGRESS)
.title("CircularProgress").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.text("Some text")
.unit("\u0025")
//.graphic(new WeatherSymbol(ConditionAndIcon.CLEAR_DAY, 48, Color.WHITE))
.build();
radarChartTile1 = TileBuilder.create().skinType(Tile.SkinType.RADAR_CHART)
.minValue(0)
.maxValue(50).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.title("RadarChart Sector")
.unit("Unit")
.radarChartMode(RadarChart.Mode.SECTOR)
.gradientStops(new Stop(0.00000, Color.TRANSPARENT),
new Stop(0.00001, Color.web("#3552a0")),
new Stop(0.09090, Color.web("#456acf")),
new Stop(0.27272, Color.web("#45a1cf")),
new Stop(0.36363, Color.web("#30c8c9")),
new Stop(0.45454, Color.web("#30c9af")),
new Stop(0.50909, Color.web("#56d483")),
new Stop(0.72727, Color.web("#9adb49")),
new Stop(0.81818, Color.web("#efd750")),
new Stop(0.90909, Color.web("#ef9850")),
new Stop(1.00000, Color.web("#ef6050")))
.text("Test")
.chartData(chartData1, chartData2, chartData3, chartData4,
chartData5, chartData6, chartData7, chartData8)
.tooltipText("")
.animated(true)
.build();
ephemerisTile = TileBuilder.create().skinType(Tile.SkinType.EPHEMERIS)
.title("Ephemeris").backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.currentLocation(new Location(51.911515, 7.6340026, "Hiltrup"))
.text("Hiltrup")
.build();
Indicator leftGraphics = new Indicator(Tile.RED);
leftGraphics.setOn(true);
Indicator middleGraphics = new Indicator(Tile.YELLOW);
middleGraphics.setOn(true);
Indicator rightGraphics = new Indicator(Tile.GREEN);
rightGraphics.setOn(true);
statusTile = TileBuilder.create()
.skinType(Tile.SkinType.STATUS)
.title("Status Tile").borderWidth(0.8d).backgroundColor(BACKGROUND).borderRadius(14).borderColor(BORDERCOLOR).borderWidth(0.8d)
.description("Notifications")
.leftText("CRITICAL")
.middleText("WARNING")
.rightText("INFORMATION")
.leftGraphics(leftGraphics)
.middleGraphics(middleGraphics)
.rightGraphics(rightGraphics)
.text("Text")
.build();
lastTimerCall = System.nanoTime();
timer = new AnimationTimer() {
@Override
public void handle(long now) {
if (now > lastTimerCall + 3_500_000_000L) {
sparkLineTile.setValue(RND.nextDouble() * sparkLineTile.getRange() * 1.5 + sparkLineTile.getMinValue());
//value.set(RND.nextDouble() * sparkLineTile.getRange() * 1.5 + sparkLineTile.getMinValue());
//sparkLineTile.setValue(20);
for (XYChart.Data<String, Number> stringNumberData : series1.getData()) {
stringNumberData.setYValue(RND.nextInt(100));
}
for (XYChart.Data<String, Number> stringNumberData : series2.getData()) {
stringNumberData.setYValue(RND.nextInt(30));
}
for (XYChart.Data<String, Number> data : series3.getData()) {
data.setYValue(RND.nextInt(10));
}
chartData1.setValue(RND.nextDouble() * 50);
chartData2.setValue(RND.nextDouble() * 50);
chartData3.setValue(RND.nextDouble() * 50);
chartData4.setValue(RND.nextDouble() * 50);
chartData5.setValue(RND.nextDouble() * 50);
chartData6.setValue(RND.nextDouble() * 50);
chartData7.setValue(RND.nextDouble() * 50);
chartData8.setValue(RND.nextDouble() * 50);
circularProgressTile.setValue(RND.nextDouble() * 120);
smoothChartData1.setValue(smoothChartData2.getValue());
smoothChartData2.setValue(smoothChartData3.getValue());
smoothChartData3.setValue(smoothChartData4.getValue());
smoothChartData4.setValue(RND.nextDouble() * 25);
if (statusTile.getLeftValue() > 1000) {
statusTile.setLeftValue(0);
}
if (statusTile.getMiddleValue() > 1000) {
statusTile.setMiddleValue(0);
}
if (statusTile.getRightValue() > 1000) {
statusTile.setRightValue(0);
}
statusTile.setLeftValue(statusTile.getLeftValue() + RND.nextInt(4));
statusTile.setMiddleValue(statusTile.getMiddleValue() + RND.nextInt(3));
statusTile.setRightValue(statusTile.getRightValue() + RND.nextInt(3));
lastTimerCall = now;
}
}
};
System.out.println("Initialization: " + (System.currentTimeMillis() - start) + "ms");
centerPane.add(radialChartTile, 0, 0);
centerPane.add(donutChartTile, 1, 0);
centerPane.add(circularProgressTile, 2, 0);
centerPane.add(radarChartTile1, 3, 0);
centerPane.add(worldTile, 0, 1, 2, 1);
centerPane.add(ephemerisTile, 2, 1);
centerPane.add(statusTile, 3, 1);
centerPane.add(sparkLineTile, 0, 2);
centerPane.add(areaChartTile, 1, 2);
centerPane.add(lineChartTile, 2, 2, 2, 1);
System.out.println("Nodes in Scene: " + noOfNodes);
timer.start();
}
@PreDestroy
private void destroy() {
// useful for jpro
timer.stop();
System.err.println("destroy " + this + actionHandler.getExceptionHandler());
}
// ******************** Misc **********************************************
private void calcNoOfNodes(Node node) {
if (node instanceof Parent) {
if (((Parent) node).getChildrenUnmodifiable().size() != 0) {
ObservableList<Node> tempChildren = ((Parent) node).getChildrenUnmodifiable();
noOfNodes += tempChildren.size();
for (Node n : tempChildren) {
calcNoOfNodes(n);
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
package com.epri.fx.client.gui.uicomponents.login;
import io.datafx.controller.ViewController;
/**
* @description:
* @className: ConversationItemPresenter
* @author: liwen
* @date: 2019-09-25 16:51
*/
@ViewController("/fxml/login/loading.fxml")
public class LoadingController {
}

View File

@@ -0,0 +1,352 @@
package com.epri.fx.client.gui.uicomponents.login;
import com.epri.fx.client.bean.MenuVoCell;
import com.epri.fx.client.gui.uicomponents.main.MainController;
import com.epri.fx.client.request.feign.admin.MenuFeign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.request.feign.login.LoginFeign;
import com.epri.fx.client.request.Request;
import com.epri.fx.client.utils.AlertUtil;
import com.epri.fx.client.websocket.Session;
import com.epri.fx.server.util.DynamicEnumUtils;
import com.epri.fx.server.util.EncryptUtil;
import com.epri.fx.server.util.user.JwtAuthenticationRequest;
import com.epri.fx.server.vo.FrontUser;
import com.epri.fx.server.vo.MenuVO;
import com.epri.fx.server.vo.PermissionInfo;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXPasswordField;
import com.jfoenix.controls.JFXProgressBar;
import com.jfoenix.controls.JFXTextField;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FXMLViewFlowContext;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.flow.context.ViewFlowContext;
import io.datafx.controller.util.VetoException;
import io.datafx.core.concurrent.ProcessChain;
import javafx.animation.*;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventType;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @description:
* @className: ConversationItemPresenter
* @author: liwen
* @date: 2019-09-25 16:51
*/
@ViewController("/fxml/login/login.fxml")
public class LoginController {
@FXML
private Pane imagePane;
@FXML
private GridPane enterPane;
@FXML
private StackPane rootPane;
@FXML
private JFXTextField userNameTextField;
@FXML
private JFXPasswordField passWordTextField;
@FXML
private Label errorLabel;
@FXML
@ActionTrigger("login")
private JFXButton loginBut;
@FXML
private VBox signCredsPane;
@FXML
private JFXProgressBar lodingBar;
@ActionHandler
private FlowActionHandler actionHandler;
private SequentialTransition sequentialTransition = new SequentialTransition();
private DoubleProperty imageWidth = new SimpleDoubleProperty();
private DoubleProperty imageHeiht = new SimpleDoubleProperty();
private Stage stage;
@Inject
private Session session;
@FXMLViewFlowContext
private ViewFlowContext flowContext;
@PostConstruct
public void init() {
errorLabel.visibleProperty().bind(errorLabel.textProperty().isNotEmpty());
errorLabel.managedProperty().bind(errorLabel.visibleProperty());
lodingBar.visibleProperty().bind(enterPane.disableProperty());
lodingBar.managedProperty().bind(lodingBar.visibleProperty());
userNameTextField.focusedProperty().addListener((o, oldVal, newVal) -> {
if (!newVal) {
userNameTextField.validate();
}
});
passWordTextField.focusedProperty().addListener((o, oldVal, newVal) -> {
if (!newVal) {
passWordTextField.validate();
}
});
loginBut.disableProperty().bind(Bindings.or(
userNameTextField.textProperty().isEqualTo(""),
passWordTextField.textProperty().isEqualTo("")));
rootPane.setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.ENTER) {
if (loginBut.isDisable() == false) {
login();
}
}
});
imagePane.widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
imageWidth.setValue(newValue);
}
});
imagePane.heightProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
imageHeiht.setValue(newValue);
}
});
FadeTransition fadeTransition = new FadeTransition(Duration.millis(500), signCredsPane);
fadeTransition.setFromValue(0f);
fadeTransition.setToValue(1f);
TranslateTransition translateTransition = new TranslateTransition(Duration.millis(500), signCredsPane);
translateTransition.setInterpolator(Interpolator.EASE_BOTH);
translateTransition.setFromY(400);
translateTransition.setToY(signCredsPane.getLayoutY());
ParallelTransition parallelTransition = new ParallelTransition();
parallelTransition.setDelay(Duration.millis(1500));
parallelTransition.getChildren().addAll(
fadeTransition,
translateTransition
);
parallelTransition.setCycleCount(1);
parallelTransition.play();
ImageView logBack = new ImageView("/images/loginBack.jpg");
logBack.fitHeightProperty().bind(imageHeiht);
logBack.fitWidthProperty().bind(imageWidth);
imagePane.getChildren().add(new Label("", logBack));
List<File> files = Arrays.asList(new File(this.getClass().getResource("/images/login/").getPath()).listFiles());
sequentialTransition.setAutoReverse(true);
sequentialTransition.setCycleCount(Timeline.INDEFINITE);
ProcessChain.create().addPublishingTask(() -> imagePane.getChildren(), p -> {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
if (!file.isDirectory()) {
String url = "/images/login/" + file.getName();
ImageView imageView = new ImageView(url);
imageView.fitHeightProperty().bind(imageHeiht);
imageView.fitWidthProperty().bind(imageWidth);
Label label = new Label("", imageView);
label.setOpacity(0d);
FadeTransition fadeT = new FadeTransition(Duration.millis(500), label);
fadeT.setDelay(Duration.millis(1500));
fadeT.setFromValue(0f);
fadeT.setToValue(1f);
fadeT.setCycleCount(1);
sequentialTransition.getChildren().add(fadeT);
p.publish(label);
}
}
}).withFinal(() -> sequentialTransition.play()).run();
}
@ActionMethod("login")
private void login() {
JwtAuthenticationRequest jwtAuthenticationRequest = new JwtAuthenticationRequest();
jwtAuthenticationRequest.setUsername(userNameTextField.getText());
jwtAuthenticationRequest.setPassword(EncryptUtil.getInstance().Base64Encode(passWordTextField.getText()));
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
enterPane.setDisable(true);
loginBut.setText("正在登录...");
})
.addSupplierInExecutor(() -> Request.connector(LoginFeign.class).login(jwtAuthenticationRequest))
.addConsumerInPlatformThread(rel -> {
if (rel.getStatus() == 200) {
errorLabel.setText("");
ApplicatonStore.setToken(rel.getData());
loadApplicatonStore();
} else {
lodingBar.requestFocus();
errorLabel.setText(rel.getMessage());
}
})
.onException(e -> {
e.printStackTrace();
errorLabel.setText("无法连接服务器,请检查服务器是否启动。");
lodingBar.requestFocus();
})
.withFinal(() -> {
enterPane.setDisable(false);
loginBut.setText("登录");
}).run();
}
public void loadApplicatonStore() {
ProcessChain.create()
.addRunnableInPlatformThread(() -> {
try {
actionHandler.navigate(LoadingController.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
ApplicatonStore.setName("");
ApplicatonStore.getAllMenu().clear();
ApplicatonStore.getMenus().clear();
ApplicatonStore.getElements().clear();
ApplicatonStore.getPermissionMenus().clear();
ApplicatonStore.getRoles().clear();
})
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).getMenuAll())
.addConsumerInPlatformThread(rel -> ApplicatonStore.getAllMenu().addAll(rel))
.addSupplierInExecutor(() ->
Request.connector(LoginFeign.class).getInfo(ApplicatonStore.getToken())
)
.addConsumerInPlatformThread(rel -> {
if (rel.getStatus() == 200) {
FrontUser frontUser = rel.getData();
ApplicatonStore.setName(frontUser.name);
ApplicatonStore.getMenus().addAll(frontUser.getMenus());
ApplicatonStore.getRoles().addAll(frontUser.getRoles());
ApplicatonStore.getElements().addAll(frontUser.getElements());
ApplicatonStore.setIntroduction(frontUser.getDescription());
for (PermissionInfo permissionInfo : frontUser.getElements()) {
ApplicatonStore.getFeatureMap().put(permissionInfo.getCode(), permissionInfo.getName());
}
} else {
AlertUtil.show(rel);
}
})
.addSupplierInExecutor(() ->
Request.connector(LoginFeign.class).getMenus(ApplicatonStore.getToken())
)
.addConsumerInPlatformThread(rel -> {
ApplicatonStore.getPermissionMenus().addAll(rel);
})
.addSupplierInExecutor(() -> {
List<MenuVO> allMenuList = ApplicatonStore.getAllMenu();
Map<Integer, List<MenuVO>> allMap = allMenuList.stream().collect(Collectors.groupingBy(MenuVO::getParentId));
MenuVO rootMenu = allMenuList.stream().min(Comparator.comparing(MenuVO::getParentId)).get();
List<MenuVO> permissionInfoList = ApplicatonStore.getPermissionMenus();
Map<Integer, List<MenuVO>> permissionInfoMap = permissionInfoList.stream().collect(Collectors.groupingBy(MenuVO::getParentId));
Map<String, List<MenuVO>> permissonTitleMap = permissionInfoList.stream().collect(Collectors.groupingBy(MenuVO::getTitle));
for (MenuVO menu : allMap.get(rootMenu.getId())) {
List<MenuVO> childrenMenus = permissionInfoMap.get(menu.getId());
List<MenuVO> partMenus = permissonTitleMap.get(menu.getTitle());
if (childrenMenus == null && partMenus == null) {
continue;
}
MenuVoCell menuVoCell=new MenuVoCell(menu,childrenMenus);
ApplicatonStore.getMenuVoCells().add(menuVoCell);
}
return 0;
})
.addConsumerInPlatformThread(rel -> {
try {
actionHandler.navigate(MainController.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.onException(e -> {
e.printStackTrace();
try {
actionHandler.navigate(LoginController.class);
} catch (VetoException vetoException) {
vetoException.printStackTrace();
} catch (FlowException flowException) {
flowException.printStackTrace();
}
})
.run();
}
@PreDestroy
private void destroy() {
sequentialTransition.stop();
}
}

View File

@@ -0,0 +1,406 @@
package com.epri.fx.client.gui.uicomponents.main;
import com.epri.fx.client.bean.MenuVoCell;
import com.epri.fx.client.gui.feature.FeatureResourceConsumer;
import com.epri.fx.client.gui.uicomponents.home.HomeController;
import com.epri.fx.client.gui.uicomponents.login.LoginController;
import com.epri.fx.client.gui.uicomponents.main.components.UserInfoController;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.server.vo.MenuVO;
import com.jfoenix.controls.*;
import com.jfoenix.svg.SVGGlyphLoader;
import io.datafx.controller.ViewController;
import io.datafx.controller.context.ApplicationContext;
import io.datafx.controller.context.FXMLApplicationContext;
import io.datafx.controller.flow.Flow;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.FlowHandler;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.container.AnimatedFlowContainer;
import io.datafx.controller.flow.container.ContainerAnimations;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.util.VetoException;
import io.datafx.eventsystem.Event;
import io.datafx.eventsystem.EventProducer;
import io.datafx.eventsystem.EventTrigger;
import io.datafx.eventsystem.OnEvent;
import javafx.animation.Transition;
import javafx.beans.property.ListProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.TextAlignment;
import javafx.util.Duration;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
/**
* @description:
* @className: MainPresenter
* @author: liwen
* @date: 2019-09-02 15:33
*/
@ViewController("/fxml/main/main.fxml")
public class MainController {
@FXMLApplicationContext
private ApplicationContext context;
@ActionHandler
private FlowActionHandler actionHandler;
@FXML
private JFXToolbar toolBar; //工具栏
@FXML
private StackPane rootPane;
@FXML
private JFXListView<Object> navigationList;
@FXML
private Pane backgroundPicturePane;
@FXML
private HBox leftHbox;
@FXML
private HBox rightHbox;
//导航按钮
@FXML
private JFXHamburger navigationButton;
//主页按钮
@FXML
@ActionTrigger("goHome")
private JFXButton homeButton;
@FXML
@ActionTrigger("showSkinPane")
private JFXButton skinButton;
//刷新按钮
@FXML
@EventTrigger("test-message1")
private JFXButton refreshButton;
//内容面板tabPane
@FXML
private JFXTabPane tabPane;
private JFXPopup popOver;
@FXML
@ActionTrigger("userInfo")
private JFXButton userButton;
@FXML
private JFXButton rolesBut;
@FXML
private Label userLabel;
@FXML
private Label roleLabel;
@FXML
private JFXDrawersStack drawersStack;
@FXML
private JFXDrawer leftDrawer;
@FXML
private JFXDatePicker datePicker;
@Inject
private FeatureResourceConsumer featureResourceConsumer;
private final HashMap<String, Tab> tabsMap = new HashMap<>();
@PostConstruct
public void init() throws FlowException {
userLabel.textProperty().bind(ApplicatonStore.nameProperty());
roleLabel.textProperty().bind(ApplicatonStore.getRoles().asString());
userButton.textProperty().bind(ApplicatonStore.nameProperty());
try {
skinButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".skin"));
homeButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline"));
refreshButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".shuaxin"));
rolesBut.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".admin"));
userButton.setGraphic(SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".ChevronDownCircle"));
} catch (Exception e) {
e.printStackTrace();
}
datePicker.setEditable(false);
leftDrawer.setSidePane(navigationList);
leftDrawer.setOverLayVisible(false);
leftDrawer.setResizeContent(true);
leftDrawer.setResizableOnDrag(true);
// create and setup search popover
backgroundPicturePane.setMouseTransparent(true);
leftDrawer.setOnDrawerOpening(e -> {
final Transition animation = navigationButton.getAnimation();
animation.setRate(1);
animation.play();
});
leftDrawer.setOnDrawerClosing(e -> {
final Transition animation = navigationButton.getAnimation();
animation.setRate(-1);
animation.play();
});
navigationButton.setOnMouseClicked(e -> {
drawersStack.toggle(leftDrawer);
});
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);
drawersStack.setContent(tabPane);
drawersStack.toggle(leftDrawer);
try {
addTab("主页", SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline"), HomeController.class);
} catch (Exception e) {
e.printStackTrace();
}
featureResourceConsumer.consumeResource(this);
navigationList.setCellFactory(listView -> new JFXListCell<Object>() {
@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
if (item instanceof MenuVO) {
MenuVO menuVO = (MenuVO) item;
try {
Label label = new Label(menuVO.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVO.getIcon()));
setGraphic(label);
setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
setGraphic(null);
}
}
});
navigationList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
if (newValue instanceof MenuVO) {
try {
addTab(((MenuVO) newValue).getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + ((MenuVO) newValue).getIcon()), Class.forName(((MenuVO) newValue).getHref()));
} catch (Exception e) {
e.printStackTrace();
}
}
});
navigationList.depthProperty().setValue(1);
navigationList.expandedProperty().set(true);
initData();
}
private JFXPopup getPopOver() {
if (popOver == null) {
try {
popOver = new JFXPopup(new Flow(UserInfoController.class).start());
} catch (FlowException e) {
e.printStackTrace();
}
}
return popOver;
}
@EventProducer("test-message")
private String getMessage() {
return "--------=================-----------";
}
@EventProducer("test-message1")
private String getMessage1() {
return "--------=================-----------";
}
private void initData() {
ListProperty<MenuVoCell> listProperty = ApplicatonStore.getMenuVoCells();
listProperty.sort((o1, o2) -> o1.getMenuVO().getOrderNum().compareTo(o2.getMenuVO().getOrderNum()));
for (MenuVoCell menuVoCell : listProperty) {
if (menuVoCell.getChildrenMenus().isEmpty()) {
navigationList.getItems().add(menuVoCell.getMenuVO());
} else {
JFXListView<MenuVO> listView = new JFXListView<MenuVO>();
listView.getStyleClass().add("sublist");
Label label = null;
try {
label = new Label(menuVoCell.getMenuVO().getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVoCell.getMenuVO().getIcon()));
label.getStyleClass().add("sublist-label");
} catch (Exception e) {
e.printStackTrace();
}
label.setTextAlignment(TextAlignment.LEFT);
listView.setGroupnode(label);
listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
if (newValue instanceof MenuVO) {
try {
addTab(newValue.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + newValue.getIcon()), Class.forName(newValue.getHref()));
} catch (Exception e) {
e.printStackTrace();
}
}
});
listView.setCellFactory(lv -> new JFXListCell<MenuVO>() {
@Override
public void updateItem(MenuVO item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
if (item instanceof MenuVO) {
MenuVO menuVO = (MenuVO) item;
try {
Label label = new Label(menuVO.getTitle(), SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + "." + menuVO.getIcon()));
setText("");
setGraphic(label);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
setGraphic(null);
}
}
});
ObservableList<MenuVO> childrenMenus = menuVoCell.getChildrenMenus();
childrenMenus.sort((o1, o2) -> o1.getOrderNum().compareTo(o2.getOrderNum()));
for (MenuVO menuVO : childrenMenus) {
listView.getItems().add(menuVO);
}
navigationList.getItems().add(listView);
}
}
}
/**
* @Description:
* @param: [controllerClass]
* @return: void
* @auther: liwen
* @date: 2020/6/28 9:57 上午
*/
private <T> void addTab(String title, Node icon, Class<T> controllerClass) {
addTab(title, icon, new Flow(controllerClass));
}
/**
* @Description:添加tab页
* @param: [flow]
* @return: void
* @auther: liwen
* @date: 2020/6/28 9:57 上午
*/
private <T> void addTab(String title, Node icon, Flow flow) {
FlowHandler flowHandler = flow.createHandler();
Tab tab = tabsMap.get(title);
if (tab == null) {
tab = new Tab(title);
tab.setGraphic(icon);
try {
StackPane node = flowHandler.start(new AnimatedFlowContainer(Duration.millis(320), ContainerAnimations.SWIPE_LEFT));
node.getStyleClass().addAll("tab-content");
node.setPadding(new Insets(15, 20, 15, 20));
tab.setContent(node);
featureResourceConsumer.consumeResource(flowHandler.getCurrentViewContext().getController());
} catch (FlowException e) {
e.printStackTrace();
}
tabPane.getTabs().add(tab);
tabsMap.put(title, tab);
tab.setOnClosed(event -> {
tabsMap.remove(title);
try {
flowHandler.getCurrentViewContext().destroy();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
}
if ("主页".equals(title)) {
tab.setClosable(false);
}
tabPane.getSelectionModel().select(tab);
}
@ActionMethod("goHome")
private void goHome() {
try {
addTab("主页", SVGGlyphLoader.getIcoMoonGlyph(ApplicatonStore.ICON_FONT_KEY + ".home-outline"), HomeController.class);
} catch (Exception e) {
e.printStackTrace();
}
}
@ActionMethod("userInfo")
private void userInfo() throws VetoException, FlowException {
getPopOver().show(userButton, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, 0, userButton.getHeight());
}
@ActionMethod("showSkinPane")
private void showSkinPane() throws VetoException, FlowException {
getPopOver().show(skinButton);
}
@PreDestroy
public void destroy() {
}
/**
* @Description:退出登录
* @param: [event]
* @return: void
* @auther: liwen
* @date: 2020/8/20 6:33 下午
*/
@OnEvent("dropOut")
private void signOut(Event<String> event) {
getPopOver().hide();
ApplicatonStore.clearPermissionInfo();
try {
actionHandler.navigate(LoginController.class);
} catch (VetoException e) {
e.printStackTrace();
} catch (FlowException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,24 @@
package com.epri.fx.client.gui.uicomponents.main.components;
import io.datafx.controller.ViewController;
import javax.annotation.PostConstruct;
/**
* @description:
* @className: UserInfoController
* @author: liwen
* @date: 2020/8/16 10:52
*/
@ViewController("/fxml/main/components/skin_info.fxml")
public class SkinInfoController {
@PostConstruct
private void init() {
}
}

View File

@@ -0,0 +1,51 @@
package com.epri.fx.client.gui.uicomponents.main.components;
import com.epri.fx.client.store.ApplicatonStore;
import com.jfoenix.controls.JFXListView;
import io.datafx.controller.ViewController;
import io.datafx.eventsystem.EventProducer;
import io.datafx.eventsystem.EventTrigger;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javax.annotation.PostConstruct;
/**
* @description:
* @className: UserInfoController
* @author: liwen
* @date: 2020/8/16 10:52
*/
@ViewController("/fxml/main/components/user_info.fxml")
public class UserInfoController {
@FXML
private JFXListView listView;
@FXML
private Label userLabel;
@FXML
private Label personalCenterLabel;
@FXML
@EventTrigger("dropOut")
private Label dropOutLabel;
@FXML
private Label roleLabel;
@PostConstruct
private void init() {
userLabel.textProperty().bind(ApplicatonStore.nameProperty());
roleLabel.textProperty().bind(ApplicatonStore.getRoles().asString());
listView.expandedProperty().bind(listView.visibleProperty());
}
@EventProducer("dropOut")
private String listViewListener() {
return "退出";
}
}

View File

@@ -0,0 +1,65 @@
package com.epri.fx.client.model;
import com.epri.fx.server.vo.ElementVO;
import com.epri.fx.server.vo.GroupVO;
import com.epri.fx.server.vo.MenuVO;
import io.datafx.controller.FxmlLoadException;
import io.datafx.controller.injection.scopes.ViewScoped;
import javafx.beans.property.ListProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
/**
* @description:
* @className: GroupDataModel
* @author: liwen
* @date: 2020/7/22 16:42
*/
@ViewScoped
public class GroupDataModel {
private ListProperty<MenuVO> menuVOS;
private SimpleObjectProperty<GroupVO> selectedGroupVO = new SimpleObjectProperty<>(new GroupVO());
private SimpleObjectProperty<MenuVO> selectedMenuVO = new SimpleObjectProperty<>(new MenuVO());
public ObservableList<ElementVO> getElementVOS() {
return FXCollections.observableArrayList(getSelectedMenuVO().getElementVOS());
}
public ListProperty<MenuVO> getMenuVOS() {
if (menuVOS == null) {
ObservableList<MenuVO> innerList = FXCollections.observableArrayList();
menuVOS = new SimpleListProperty<>(innerList);
}
return menuVOS;
}
public GroupVO getSelectedGroup() {
return selectedGroupVO.get();
}
public ObjectProperty<GroupVO> selectedGroupProperty() {
return selectedGroupVO;
}
public void setSelectedGroup(GroupVO group) {
this.selectedGroupVO.set(group);
}
public MenuVO getSelectedMenuVO() {
return selectedMenuVO.get();
}
public SimpleObjectProperty<MenuVO> selectedMenuVOProperty() {
return selectedMenuVO;
}
public void setSelectedMenuVO(MenuVO selectedMenuVO) {
this.selectedMenuVO.set(selectedMenuVO);
}
}

View File

@@ -0,0 +1,42 @@
package com.epri.fx.client.model;
import com.epri.fx.server.vo.GroupTypeVO;
import io.datafx.controller.injection.scopes.FlowScoped;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@FlowScoped
public class GroupTypeDataModel {
private int counter = 0;
private ListProperty<GroupTypeVO> groupTypes;
private IntegerProperty selectedIndex;
public ListProperty<GroupTypeVO> getGroupTypes() {
if (groupTypes == null) {
ObservableList<GroupTypeVO> innerList = FXCollections.observableArrayList();
groupTypes = new SimpleListProperty<>(innerList);
}
return groupTypes;
}
public int getSelectedIndex() {
return selectedIndexProperty().get();
}
public void setSelectedIndex(int selectedPersonIndex) {
this.selectedIndex.set(selectedPersonIndex);
}
public IntegerProperty selectedIndexProperty() {
if (selectedIndex == null) {
selectedIndex = new SimpleIntegerProperty();
}
return selectedIndex;
}
}

View File

@@ -0,0 +1,60 @@
package com.epri.fx.client.model;
import com.epri.fx.server.vo.ElementVO;
import com.epri.fx.server.vo.MenuVO;
import io.datafx.controller.injection.scopes.ViewScoped;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@ViewScoped
public class MenuDataModel {
private ObjectProperty<MenuVO> selectMenuVOProperty;
private ListProperty<ElementVO> elementVOS;
private IntegerProperty selectedElementIndex;
public ListProperty<ElementVO> getElementVOS() {
if (elementVOS == null) {
ObservableList<ElementVO> innerList = FXCollections.observableArrayList();
elementVOS = new SimpleListProperty<>(innerList);
}
return elementVOS;
}
public MenuVO getSelectMenuVO() {
return selectMenuVOPropertyProperty().get();
}
public ObjectProperty<MenuVO> selectMenuVOPropertyProperty() {
if (selectMenuVOProperty == null) {
selectMenuVOProperty = new SimpleObjectProperty<>(new MenuVO());
}
return selectMenuVOProperty;
}
public void setSelectMenuVO(MenuVO selectMenuVOProperty) {
this.selectMenuVOPropertyProperty().set(selectMenuVOProperty);
}
public int getSelectedElementIndex() {
return selectedElementIndexProperty().get();
}
public IntegerProperty selectedElementIndexProperty() {
if (selectedElementIndex == null) {
selectedElementIndex = new SimpleIntegerProperty();
}
return selectedElementIndex;
}
}

View File

@@ -0,0 +1,58 @@
package com.epri.fx.client.model;
import com.epri.fx.server.vo.UserVO;
import io.datafx.controller.injection.scopes.FlowScoped;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@FlowScoped
public class UserDataModel {
private int counter = 0;
private ListProperty<UserVO> users;
private IntegerProperty pageCount;
private IntegerProperty selectedPersonIndex;
public ListProperty<UserVO> getUsers() {
if (users == null) {
ObservableList<UserVO> innerList = FXCollections.observableArrayList();
users = new SimpleListProperty<>(innerList);
}
return users;
}
public int getSelectedPersonIndex() {
return selectedPersonIndexProperty().get();
}
public void setSelectedPersonIndex(int selectedPersonIndex) {
this.selectedPersonIndex.set(selectedPersonIndex);
}
public IntegerProperty selectedPersonIndexProperty() {
if (selectedPersonIndex == null) {
selectedPersonIndex = new SimpleIntegerProperty();
}
return selectedPersonIndex;
}
public int getPageCount() {
return pageCount.get();
}
public IntegerProperty pageCountProperty() {
if (pageCount == null) {
pageCount = new SimpleIntegerProperty();
}
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount.set(pageCount);
}
}

View File

@@ -0,0 +1,137 @@
package com.epri.fx.client.request;
import com.epri.fx.client.request.feign.AppRequestErrorDecoder;
import com.epri.fx.client.request.feign.AppRequestInterceptor;
import com.epri.fx.client.request.feign.FeignAPI;
import com.netflix.client.ClientFactory;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.BestAvailableRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import feign.Feign;
import feign.Logger;
import feign.Retryer;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;
import feign.ribbon.LBClient;
import feign.ribbon.LBClientFactory;
import feign.ribbon.LoadBalancingTarget;
import feign.ribbon.RibbonClient;
import feign.slf4j.Slf4jLogger;
import okhttp3.ConnectionPool;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Request {
private static final Map<String, FeignAPI> CONNECTORS = new ConcurrentHashMap<>();
private static RibbonClient ribbonClient;
private static String API_URL = "http://sample-client";
private final static int CONNECT_TIME_OUT_MILLIS = 1000;
private final static int READ_TIME_OUT_MILLIS = 60000;
private static JacksonDecoder jacksonDecoder;
private static JacksonEncoder jacksonEncoder;
private static AppRequestInterceptor requestInterceptor;
private static AppRequestErrorDecoder requestErrorDecoder;
private static Slf4jLogger slf4jLogger;
/**
* @Description:
* @param: [connectorClass, readTimeOut->设置超时时间]
* @return: T
* @auther: liwen
* @date: 2019-06-05 14:33
*/
public static <T extends FeignAPI> T connector(Class<T> connectorClass, int readTimeOut) {
final String commandConfigKey = connectorClass.getSimpleName() + readTimeOut;
return (T) CONNECTORS.computeIfAbsent(commandConfigKey, k -> {
return Feign.builder()
.client(ribbonClient())
.decoder(getJacksonDecoder())
.encoder(getJacksonEncoder())
.errorDecoder(getRequestErrorDecoder())
.requestInterceptor(getRequestInterceptor())
.logger(getSlf4jLogger())
.logLevel(Logger.Level.FULL)
.retryer(Retryer.NEVER_RETRY)
.options(new feign.Request.Options(CONNECT_TIME_OUT_MILLIS, readTimeOut))
.target(connectorClass, API_URL);
});
}
public static <T extends FeignAPI> T connector(Class<T> connectorClass) {
return connector(connectorClass, READ_TIME_OUT_MILLIS);
}
private static JacksonDecoder getJacksonDecoder() {
if (jacksonDecoder == null) {
jacksonDecoder = new JacksonDecoder();
}
return jacksonDecoder;
}
private static JacksonEncoder getJacksonEncoder() {
if (jacksonEncoder == null) {
jacksonEncoder = new JacksonEncoder();
}
return jacksonEncoder;
}
private static AppRequestInterceptor getRequestInterceptor() {
if (requestInterceptor == null) {
requestInterceptor = new AppRequestInterceptor();
}
return requestInterceptor;
}
private static AppRequestErrorDecoder getRequestErrorDecoder() {
if (requestErrorDecoder == null) {
requestErrorDecoder = new AppRequestErrorDecoder();
}
return requestErrorDecoder;
}
private static Slf4jLogger getSlf4jLogger() {
if (slf4jLogger == null) {
slf4jLogger = new Slf4jLogger();
}
return slf4jLogger;
}
private static RibbonClient ribbonClient() {
if (ribbonClient == null) {
ribbonClient = RibbonClient.builder().delegate(new OkHttpClient(createOkHttpClient())).lbClientFactory(new LBClientFactory() {
@Override
public LBClient create(String clientName) {
IClientConfig config = ClientFactory.getNamedConfig(clientName);
ILoadBalancer lb = ClientFactory.getNamedLoadBalancer(clientName);
ZoneAwareLoadBalancer zb = (ZoneAwareLoadBalancer) lb;
zb.setRule(new BestAvailableRule());
LBClient lbClient = LBClient.create(lb, config);
return lbClient;
}
}).build();
}
return ribbonClient;
}
private static okhttp3.OkHttpClient createOkHttpClient() {
return new okhttp3.OkHttpClient.Builder().connectionPool(new ConnectionPool())
.build();
}
}

View File

@@ -0,0 +1,20 @@
package com.epri.fx.client.request.feign;
import com.epri.fx.client.store.ApplicatonStore;
import com.epri.fx.client.utils.AlertUtil;
import feign.Response;
import feign.codec.ErrorDecoder;
/**
* @description:
* @className: RequestErrorDecoder
* @author: liwen
* @date: 2020/8/13 09:36
*/
public class AppRequestErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
AlertUtil.show(response);
return null;
}
}

View File

@@ -0,0 +1,15 @@
package com.epri.fx.client.request.feign;
import com.epri.fx.client.store.ApplicatonStore;
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class AppRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
template.header("Authorization", ApplicatonStore.getToken());
}
}

View File

@@ -0,0 +1,9 @@
package com.epri.fx.client.request.feign;
import feign.Headers;
@Headers("Content-Type: application/json")
public interface FeignAPI {
}

View File

@@ -0,0 +1,29 @@
package com.epri.fx.client.request.feign.admin;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.entity.Element;
import com.epri.fx.server.msg.TableResultResponse;
import feign.Param;
import feign.RequestLine;
/**
* @description:
* @className: ElementFeign
* @author: liwen
* @date: 2020/7/19 18:55
*/
public interface ElementFeign extends FeignAPI {
@RequestLine("GET /element/list/{menuId}")
TableResultResponse<Element> getMenuElementList(@Param("menuId") Integer menuId);
@RequestLine("POST /element")
Integer addElement(Element element);
@RequestLine("PUT /element")
Integer updateElement(Element element);
@RequestLine("DELETE /element/{id}")
Integer deleteElement(@Param("id") Integer id);
}

View File

@@ -0,0 +1,46 @@
package com.epri.fx.client.request.feign.admin;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.vo.GroupUsers;
import com.epri.fx.server.vo.GroupVO;
import com.epri.fx.server.vo.MenuVO;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import java.util.List;
import java.util.Map;
/**
* @description:
* @className: TestFeign
* @author: liwen
* @date: 2020/4/1 17:31
*/
public interface GroupFeign extends FeignAPI {
@RequestLine("GET /group/treeList/{groupTypeId}")
List<GroupVO> getGroupList(@Param("groupTypeId") Integer groupTypeId);
@RequestLine("GET /group/{groupId}/authority/menu")
List<MenuVO> getAuthorityMenuElementAll(@Param("groupId") Integer groupId);
@RequestLine("PUT /group/{groupId}/authority/menu")
Integer modifyMenuAuthority(@Param("groupId") int id, List<MenuVO> menuVOList);
@RequestLine("POST /group")
Integer addGroup(GroupVO groupVO);
@RequestLine("PUT /group")
Integer updateGroup(GroupVO groupVO);
@RequestLine("DELETE /group")
Integer deleteGroup(GroupVO groupVO);
@RequestLine(value = "GET /group/{id}/user")
public GroupUsers getUsers(@Param("id") int id);
@RequestLine(value = "PUT /group/{id}/user")
public Integer modifiyUsers(@Param("id") int id, @QueryMap Map<String,String> map);
}

View File

@@ -0,0 +1,29 @@
package com.epri.fx.client.request.feign.admin;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.vo.GroupTypeVO;
import feign.Param;
import feign.RequestLine;
import java.util.List;
/**
* @description:
* @className: TestFeign
* @author: liwen
* @date: 2020/4/1 17:31
*/
public interface GroupTypeFeign extends FeignAPI {
@RequestLine("GET /groupType/all")
List<GroupTypeVO> getAllGroupTypes();
@RequestLine("POST /groupType")
Integer addGroupType(GroupTypeVO groupTypeVO);
@RequestLine("PUT /groupType")
Integer updateGroupType(GroupTypeVO groupTypeVO);
@RequestLine("DELETE /groupType/{groupTypeId}")
Integer deleteGroupTypes(@Param("groupTypeId") int groupTypeId);
}

View File

@@ -0,0 +1,32 @@
package com.epri.fx.client.request.feign.admin;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.vo.MenuVO;
import feign.Headers;
import feign.RequestLine;
import java.util.List;
/**
* @description:
* @className: TestFeign
* @author: liwen
* @date: 2020/4/1 17:31
*/
@Headers("Content-Type: application/json")
public interface MenuFeign extends FeignAPI {
@RequestLine("GET /menu/all")
List<MenuVO> getMenuAll();
@RequestLine("GET /menu/element/all")
List<MenuVO> getMenuElementAll();
@RequestLine("POST /menu")
Integer addMenu(MenuVO menuVO);
@RequestLine("PUT /menu")
Integer updateMenu(MenuVO menuVO);
@RequestLine("DELETE /menu")
Integer deleteMenu(MenuVO menuVO);
}

View File

@@ -0,0 +1,35 @@
package com.epri.fx.client.request.feign.admin;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.entity.User;
import com.epri.fx.server.msg.ObjectRestResponse;
import com.epri.fx.server.msg.TableResultResponse;
import com.epri.fx.server.vo.UserVO;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import java.util.Map;
/**
* @description:
* @className: TestFeign
* @author: liwen
* @date: 2020/4/1 17:31
*/
public interface UserFeign extends FeignAPI {
@RequestLine("GET /user/page")
TableResultResponse<User> getPageList(@QueryMap Map<String, Object> map);
@RequestLine("PUT /user/{id}")
ObjectRestResponse<Integer> update(@Param("id") Integer id, User user);
@RequestLine("DELETE /user/{id}")
ObjectRestResponse<Integer> delete(@Param("id") Integer id);
@RequestLine("PUT /user/password/{id}")
ObjectRestResponse<Integer> restPassword(@Param("id")Integer id);
@RequestLine("POST /user")
ObjectRestResponse<Integer> add(User user);
}

View File

@@ -0,0 +1,36 @@
package com.epri.fx.client.request.feign.login;
import com.epri.fx.client.request.feign.FeignAPI;
import com.epri.fx.server.msg.ObjectRestResponse;
import com.epri.fx.server.util.user.JwtAuthenticationRequest;
import com.epri.fx.server.vo.FrontUser;
import com.epri.fx.server.vo.MenuVO;
import feign.Param;
import feign.RequestLine;
import java.util.List;
/**
* @description:
* @className: LoginFeign
* @author: liwen
* @date: 2020/8/2 09:47
*/
public interface LoginFeign extends FeignAPI {
@RequestLine("POST /jwt/token")
ObjectRestResponse<String> login(JwtAuthenticationRequest request);
@RequestLine("GET /jwt/invalid")
ObjectRestResponse<String> logout(JwtAuthenticationRequest request);
@RequestLine("GET /user/front/info/{token}")
ObjectRestResponse<FrontUser> getInfo(@Param("token") String token);
@RequestLine("GET /user/front/menus/{token}")
List<MenuVO> getMenus(@Param("token") String token);
@RequestLine("GET /user/front/menus/all/{token}")
List<MenuVO> getMenuAll(@Param("token") String token);
}

View File

@@ -0,0 +1,187 @@
package com.epri.fx.client.store;
import com.epri.fx.client.bean.MenuVoCell;
import com.epri.fx.server.vo.GroupVO;
import com.epri.fx.server.vo.MenuVO;
import com.epri.fx.server.vo.PermissionInfo;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import java.util.HashMap;
import java.util.Map;
/**
* @description:
* @className: User
* @author: liwen
* @date: 2020/8/2 10:17
*/
public class ApplicatonStore {
public static String ICON_FONT_KEY = "icon.svg";
private static SimpleIntegerProperty status = new SimpleIntegerProperty();
private static SimpleStringProperty code = new SimpleStringProperty();
private static SimpleStringProperty token = new SimpleStringProperty();
private static SimpleStringProperty name = new SimpleStringProperty();
private static SimpleStringProperty avatar = new SimpleStringProperty();
private static SimpleStringProperty introduction = new SimpleStringProperty();
private static ListProperty<GroupVO> roles;
private static ListProperty<PermissionInfo> menus;
private static ListProperty<MenuVO> permissionMenus;
private static ListProperty<MenuVO> allMenu;
private static ListProperty<MenuVoCell> menuVoCells;
private static ListProperty<PermissionInfo> elements;
private static MapProperty<String, String> featureMap;
public static int getStatus() {
return status.get();
}
public static SimpleIntegerProperty statusProperty() {
return status;
}
public static void setStatus(int status) {
ApplicatonStore.status.set(status);
}
public static String getCode() {
return code.get();
}
public static SimpleStringProperty codeProperty() {
return code;
}
public static void setCode(String code) {
ApplicatonStore.code.set(code);
}
public static String getToken() {
return token.get();
}
public static SimpleStringProperty tokenProperty() {
return token;
}
public static void setToken(String token) {
ApplicatonStore.token.set(token);
}
public static String getName() {
return name.get();
}
public static SimpleStringProperty nameProperty() {
return name;
}
public static void setName(String name) {
ApplicatonStore.name.set(name);
}
public static String getAvatar() {
return avatar.get();
}
public static SimpleStringProperty avatarProperty() {
return avatar;
}
public static void setAvatar(String avatar) {
ApplicatonStore.avatar.set(avatar);
}
public static String getIntroduction() {
return introduction.get();
}
public static SimpleStringProperty introductionProperty() {
return introduction;
}
public static void setIntroduction(String introduction) {
ApplicatonStore.introduction.set(introduction);
}
public static ListProperty<GroupVO> getRoles() {
if (roles == null) {
ObservableList<GroupVO> innerList = FXCollections.observableArrayList();
roles = new SimpleListProperty<>(innerList);
}
return roles;
}
public static ListProperty<PermissionInfo> getMenus() {
if (menus == null) {
ObservableList<PermissionInfo> innerList = FXCollections.observableArrayList();
menus = new SimpleListProperty<>(innerList);
}
return menus;
}
public static ListProperty<MenuVO> getAllMenu() {
if (allMenu == null) {
ObservableList<MenuVO> innerList = FXCollections.observableArrayList();
allMenu = new SimpleListProperty<>(innerList);
}
return allMenu;
}
public static ListProperty<MenuVoCell> getMenuVoCells() {
if (menuVoCells == null) {
ObservableList<MenuVoCell> innerList = FXCollections.observableArrayList();
menuVoCells = new SimpleListProperty<>(innerList);
}
return menuVoCells;
}
public static ListProperty<PermissionInfo> getElements() {
if (elements == null) {
ObservableList<PermissionInfo> innerList = FXCollections.observableArrayList();
elements = new SimpleListProperty<>(innerList);
}
return elements;
}
public static MapProperty<String, String> getFeatureMap() {
if (featureMap == null) {
ObservableMap<String, String> map = FXCollections.observableMap(new HashMap<>());
featureMap = new SimpleMapProperty<>(map);
}
return featureMap;
}
public static ListProperty<MenuVO> getPermissionMenus() {
if (permissionMenus == null) {
ObservableList<MenuVO> innerList = FXCollections.observableArrayList();
permissionMenus = new SimpleListProperty<>(innerList);
}
return permissionMenus;
}
public static void clearPermissionInfo() {
setName("");
getAllMenu().clear();
getMenuVoCells().clear();
getMenus().clear();
ApplicatonStore.getElements().clear();
getPermissionMenus().clear();
getRoles().clear();
getFeatureMap().clear();
}
}

View File

@@ -0,0 +1,48 @@
package com.epri.fx.client.utils;
import com.epri.fx.server.msg.BaseResponse;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import feign.Response;
import io.datafx.controller.context.ApplicationContext;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
* @description:
* @className: AlerUtil
* @author: liwen
* @date: 2020/8/2 13:39
*/
public class AlertUtil {
public static void show(BaseResponse response) {
JFXAlert alert = new JFXAlert(ApplicationContext.getInstance().getRegisteredObject(Stage.class));
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("提示"));
layout.setBody(new Label(response.getStatus() + "\t" + response.getMessage()));
JFXButton closeButton = new JFXButton("确定");
closeButton.setOnAction(event -> alert.hideWithAnimation());
layout.setActions(closeButton);
alert.setContent(layout);
alert.show();
}
public static void show(Response response) {
JFXAlert alert = new JFXAlert(ApplicationContext.getInstance().getRegisteredObject(Stage.class));
alert.initModality(Modality.APPLICATION_MODAL);
alert.setOverlayClose(false);
JFXDialogLayout layout = new JFXDialogLayout();
layout.setHeading(new Label("提示"));
layout.setBody(new Label(response.status() + "\t" + response.reason()));
JFXButton closeButton = new JFXButton("确定");
closeButton.setOnAction(event -> alert.hideWithAnimation());
layout.setActions(closeButton);
alert.setContent(layout);
alert.show();
}
}

View File

@@ -0,0 +1,12 @@
package com.epri.fx.client.utils;
/**
* @description:
* @className: Helper
* @author: liwen
* @date: 2020/9/22 16:05
*/
public class Helper {
private static final String COUNTRY_PROPERTIES = "resources/country/中国.svg";
}

View File

@@ -0,0 +1,161 @@
package com.epri.fx.client.utils;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/**
* 汉字转换成拼音方法
*
* @author 蔡龙
*/
public class Pinyin4jUtil {
static HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
public static enum Type {
UPPERCASE, //全部大写
LOWERCASE, //全部小写
FIRSTUPPER //首字母大写
}
static {
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
}
/**
* 转换全部大写
*
* @param str 字符串
* @return str为颐和园 ,return获取到的是YHY
*/
public static String toPinYinUppercase(String str) {
return toPinYin(str, "", Type.UPPERCASE);
}
/**
* 转换全部大写
*
* @param str 字符串
* @param spera 转换字母间隔加的字符串,如果不需要为""
* @return str为颐和园 ,spera为** return获取到的是Y**H**Y
*/
public static String toPinYinUppercase(String str, String spera) {
return toPinYin(str, spera, Type.UPPERCASE);
}
/**
* 转换全部小写
*
* @param str 字符串
* @return str为颐和园 ,return获取到的是yhy
* @
*/
public static String toPinYinLowercase(String str) {
return toPinYin(str, "", Type.LOWERCASE);
}
/**
* 转换全部小写
*
* @param str 字符串
* @param spera 转换字母间隔加的字符串,如果不需要为""
* @return str为颐和园 ,spera为** return获取到的是y**h**y
* @
*/
public static String toPinYinLowercase(String str, String spera) {
return toPinYin(str, spera, Type.LOWERCASE);
}
/**
* 获取拼音首字母(大写)
*
* @param str 字符串
* @return str为颐和园 ,return获取到的是Y
* @ 异常信息
*/
public static String toPinYinUppercaseInitials(String str) {
String initials = null;
String py = toPinYinUppercase(str);
if (py.length() > 1) {
initials = py.substring(0, 1);
}
if (py.length() <= 1) {
initials = py;
}
return initials.trim();
}
/**
* 获取拼音首字母(小写)
*
* @param str 字符串
* @return str为颐和园 ,return获取到的是y
* @ 异常信息
*/
public static String toPinYinLowercaseInitials(String str) {
String initials = null;
String py = toPinYinLowercase(str);
if (py.length() > 1) {
initials = py.substring(0, 1);
}
if (py.length() <= 1) {
initials = py;
}
return initials.trim();
}
/**
* 将str转换成拼音如果不是汉字或者没有对应的拼音则不作转换
*
* @param str 字符串
* @param spera 默认,可为""
* @param type 转换格式
* @return 按照转换格式转换成字符串
*/
public static String toPinYin(String str, String spera, Type type) {
if (str == null || str.trim().length() == 0) {
return "";
}
if (type == Type.UPPERCASE) {
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
} else {
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
}
String py = "";
String temp = "";
String[] t = null;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((int) c <= 128) {
py += c;
} else {
try {
t = PinyinHelper.toHanyuPinyinStringArray(c, format);
} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
badHanyuPinyinOutputFormatCombination.printStackTrace();
}
if (t == null) {
py += c;
} else {
temp = t[0];
if (type == Type.FIRSTUPPER) {
temp = t[0].toUpperCase().charAt(0) + temp.substring(1);
}
if (temp.length() >= 1) {
temp = temp.substring(0, 1);
}
py += temp + (i == str.length() - 1 ? "" : spera);
}
}
}
return py.trim();
}
}

View File

@@ -0,0 +1,24 @@
package com.epri.fx.client.websocket;
import io.datafx.controller.injection.scopes.ApplicationScoped;
import io.datafx.controller.injection.scopes.FlowScoped;
/**
* @description:
* @className: Session
* @author: liwen
* @date: 2020/6/24 16:17
*/
@ApplicationScoped
public class Session {
private int counter = 0;
public Session() {
}
public void print(String from) {
System.out.println(from + ": counter = " + counter++);
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<datafx version="8.0">
<features>
<featureEnum>com.epri.fx.client.gui.uicomponents.feature.UserGroupFeatures</featureEnum>
</features>
</datafx>

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -0,0 +1,15 @@
@font-face {
font-family: 'Microsoft YaHei';
src: url("../fonts/msyh.ttf");
}
@font-face {
font-family: 'Microsoft YaHei Light';
src: url("../fonts/msyhl.ttf");
}
@font-face {
font-family: 'Microsoft YaHei Bold';
src: url("../fonts/msyhbd.ttf");
}

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 426 KiB

View File

@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@@ -0,0 +1,469 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2077973" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe9b0;</span>
<div class="name">home-outline</div>
<div class="code-name">&amp;#xe9b0;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe752;</span>
<div class="name">history</div>
<div class="code-name">&amp;#xe752;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9ac;</span>
<div class="name">exit-outline</div>
<div class="code-name">&amp;#xe9ac;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9ad;</span>
<div class="name">create-outline</div>
<div class="code-name">&amp;#xe9ad;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9ae;</span>
<div class="name">power-outline</div>
<div class="code-name">&amp;#xe9ae;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe9af;</span>
<div class="name">add-circle-outline</div>
<div class="code-name">&amp;#xe9af;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe65f;</span>
<div class="name">操作日志</div>
<div class="code-name">&amp;#xe65f;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6a4;</span>
<div class="name">菜单管理</div>
<div class="code-name">&amp;#xe6a4;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe666;</span>
<div class="name">角色类型</div>
<div class="code-name">&amp;#xe666;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe642;</span>
<div class="name">功能角色权限管理</div>
<div class="code-name">&amp;#xe642;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe62d;</span>
<div class="name">用户管理</div>
<div class="code-name">&amp;#xe62d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe62e;</span>
<div class="name">基础配置</div>
<div class="code-name">&amp;#xe62e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xea8d;</span>
<div class="name">trash-outline</div>
<div class="code-name">&amp;#xea8d;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-home-outline"></span>
<div class="name">
home-outline
</div>
<div class="code-name">.icon-home-outline
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-history"></span>
<div class="name">
history
</div>
<div class="code-name">.icon-history
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-exit-outline"></span>
<div class="name">
exit-outline
</div>
<div class="code-name">.icon-exit-outline
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-create-outline"></span>
<div class="name">
create-outline
</div>
<div class="code-name">.icon-create-outline
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-power-outline"></span>
<div class="name">
power-outline
</div>
<div class="code-name">.icon-power-outline
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-add-circle-outline"></span>
<div class="name">
add-circle-outline
</div>
<div class="code-name">.icon-add-circle-outline
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-caozuorizhi"></span>
<div class="name">
操作日志
</div>
<div class="code-name">.icon-caozuorizhi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-jiaoyixulie"></span>
<div class="name">
菜单管理
</div>
<div class="code-name">.icon-jiaoyixulie
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-jiaoseleixing"></span>
<div class="name">
角色类型
</div>
<div class="code-name">.icon-jiaoseleixing
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-gongnengjiaosequanxianguanli"></span>
<div class="name">
功能角色权限管理
</div>
<div class="code-name">.icon-gongnengjiaosequanxianguanli
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-yonghuguanli_huaban"></span>
<div class="name">
用户管理
</div>
<div class="code-name">.icon-yonghuguanli_huaban
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-jichupeizhi"></span>
<div class="name">
基础配置
</div>
<div class="code-name">.icon-jichupeizhi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-trash-outline"></span>
<div class="name">
trash-outline
</div>
<div class="code-name">.icon-trash-outline
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-home-outline"></use>
</svg>
<div class="name">home-outline</div>
<div class="code-name">#icon-home-outline</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-history"></use>
</svg>
<div class="name">history</div>
<div class="code-name">#icon-history</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-exit-outline"></use>
</svg>
<div class="name">exit-outline</div>
<div class="code-name">#icon-exit-outline</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-create-outline"></use>
</svg>
<div class="name">create-outline</div>
<div class="code-name">#icon-create-outline</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-power-outline"></use>
</svg>
<div class="name">power-outline</div>
<div class="code-name">#icon-power-outline</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-add-circle-outline"></use>
</svg>
<div class="name">add-circle-outline</div>
<div class="code-name">#icon-add-circle-outline</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-caozuorizhi"></use>
</svg>
<div class="name">操作日志</div>
<div class="code-name">#icon-caozuorizhi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-jiaoyixulie"></use>
</svg>
<div class="name">菜单管理</div>
<div class="code-name">#icon-jiaoyixulie</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-jiaoseleixing"></use>
</svg>
<div class="name">角色类型</div>
<div class="code-name">#icon-jiaoseleixing</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-gongnengjiaosequanxianguanli"></use>
</svg>
<div class="name">功能角色权限管理</div>
<div class="code-name">#icon-gongnengjiaosequanxianguanli</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yonghuguanli_huaban"></use>
</svg>
<div class="name">用户管理</div>
<div class="code-name">#icon-yonghuguanli_huaban</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-jichupeizhi"></use>
</svg>
<div class="name">基础配置</div>
<div class="code-name">#icon-jichupeizhi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-trash-outline"></use>
</svg>
<div class="name">trash-outline</div>
<div class="code-name">#icon-trash-outline</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More