commit
415d8f738d
@ -0,0 +1,20 @@
|
|||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
/.idea
|
||||||
|
*.iml
|
||||||
|
/.settings
|
||||||
|
/bin
|
||||||
|
/gen
|
||||||
|
/build
|
||||||
|
/gradle
|
||||||
|
/classes
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
*.gradle
|
||||||
|
gradlew
|
||||||
|
local.properties
|
||||||
|
node_modules/
|
@ -0,0 +1,33 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import cn.zhouyafeng.itchat4j.controller.LoginController;
|
||||||
|
import cn.zhouyafeng.itchat4j.core.MsgCenter;
|
||||||
|
import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace;
|
||||||
|
|
||||||
|
public class Wechat {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(Wechat.class);
|
||||||
|
private IMsgHandlerFace msgHandler;
|
||||||
|
|
||||||
|
public Wechat(IMsgHandlerFace msgHandler, String qrPath) {
|
||||||
|
System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误
|
||||||
|
this.msgHandler = msgHandler;
|
||||||
|
|
||||||
|
// 登陆
|
||||||
|
LoginController login = new LoginController();
|
||||||
|
login.login(qrPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++");
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
MsgCenter.handleMsg(msgHandler);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils;
|
||||||
|
|
||||||
|
public class MsgKeywords {
|
||||||
|
public static String newFriendStr = "我通过了你的朋友验证请求";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by xiaoxiaomo on 2017/5/6.
|
||||||
|
*/
|
||||||
|
public class SleepUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 毫秒为单位
|
||||||
|
* @param time
|
||||||
|
*/
|
||||||
|
public static void sleep( long time ){
|
||||||
|
try {
|
||||||
|
Thread.sleep( time );
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回结构枚举类
|
||||||
|
* <p>
|
||||||
|
* Created by xiaoxiaomo on 2017/5/6.
|
||||||
|
*/
|
||||||
|
public enum ResultEnum {
|
||||||
|
|
||||||
|
SUCCESS("200", "成功"),
|
||||||
|
WAIT_CONFIRM("201", "请在手机上点击确认"),
|
||||||
|
WAIT_SCAN("400", "请扫描二维码");
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
ResultEnum(String code, String msg) {
|
||||||
|
this.code = code;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static MsgInfoEnum getCode(String code) {
|
||||||
|
// switch (code) {
|
||||||
|
// case "Text":
|
||||||
|
// return MsgInfoEnum.TEXT;
|
||||||
|
// default:
|
||||||
|
// return MsgInfoEnum.VIDEO;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums;
|
||||||
|
|
||||||
|
public enum RetCodeEnum {
|
||||||
|
|
||||||
|
NORMAL("0", "普通"),
|
||||||
|
LOGIN_OUT("1102", "退出"),
|
||||||
|
LOGIN_OTHERWHERE("1101", "其它地方登陆"),
|
||||||
|
MOBILE_LOGIN_OUT("1102", "移动端退出"),
|
||||||
|
UNKOWN("9999", "未知")
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
RetCodeEnum(String code, String type) {
|
||||||
|
this.code = code;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by xiaoxiaomo on 2017/5/7.
|
||||||
|
*/
|
||||||
|
public enum StorageLoginInfoEnum {
|
||||||
|
|
||||||
|
//URL
|
||||||
|
url("url",new String()),
|
||||||
|
fileUrl("fileUrl",new String()),
|
||||||
|
syncUrl("syncUrl",new String()),
|
||||||
|
|
||||||
|
deviceid("deviceid",new String()), //生成15位随机数
|
||||||
|
|
||||||
|
//baseRequest
|
||||||
|
skey("skey",new String()),
|
||||||
|
wxsid("wxsid",new String()),
|
||||||
|
wxuin("wxuin",new String()),
|
||||||
|
pass_ticket("pass_ticket",new String()),
|
||||||
|
|
||||||
|
|
||||||
|
InviteStartCount("InviteStartCount",new Integer(0)),
|
||||||
|
User("User",new JSONObject()),
|
||||||
|
SyncKey("SyncKey",new JSONObject()),
|
||||||
|
synckey("synckey",new String()),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MemberCount("MemberCount",new String()),
|
||||||
|
MemberList("MemberList",new JSONArray()),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
private Object type;
|
||||||
|
|
||||||
|
StorageLoginInfoEnum(String key, Object type) {
|
||||||
|
this.key = key;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
* Created by xiaoxiaomo on 2017/5/6.
|
||||||
|
*/
|
||||||
|
public enum URLEnum {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BASE_URL("https://login.weixin.qq.com","基本的URL"),
|
||||||
|
UUID_URL(BASE_URL.url+"/jslogin","UUIDLURL"),
|
||||||
|
QRCODE_URL(BASE_URL.url+"/qrcode/","初始化URL"),
|
||||||
|
STATUS_NOTIFY_URL(BASE_URL.url+"/webwxstatusnotify?lang=zh_CN&pass_ticket=%s","微信状态通知"),
|
||||||
|
LOGIN_URL(BASE_URL.url+"/cgi-bin/mmwebwx-bin/login","登陆URL"),
|
||||||
|
INIT_URL("%s/webwxinit?r=%s&pass_ticket=%s","初始化URL"),
|
||||||
|
SYNC_CHECK_URL("/synccheck","检查心跳URL"),
|
||||||
|
WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s","web微信消息同步URL"),
|
||||||
|
WEB_WX_GET_CONTACT("%s/webwxgetcontact","web微信获取联系人信息URL"),
|
||||||
|
WEB_WX_SEND_MSG("%s/webwxsendmsg","发送消息URL"),
|
||||||
|
WEB_WX_UPLOAD_MEDIA("%s/webwxuploadmedia?f=json", "上传文件到服务器"),
|
||||||
|
WEB_WX_GET_MSG_IMG("%s/webwxgetmsgimg", "下载图片消息"),
|
||||||
|
WEB_WX_GET_VOICE("%s/webwxgetvoice", "下载语音消息"),
|
||||||
|
WEB_WX_GET_VIEDO("%s/webwxgetvideo", "下载语音消息"),
|
||||||
|
WEB_WX_PUSH_LOGIN("%s/webwxpushloginurl", "不扫码登陆"),
|
||||||
|
WEB_WX_LOGOUT("%s/webwxlogout", "退出微信"),
|
||||||
|
WEB_WX_BATCH_GET_CONTACT("%s/webwxbatchgetcontact?type=ex&r=%s&lang=zh_CN&pass_ticket=%s", "查询群信息"),
|
||||||
|
WEB_WX_REMARKNAME("%s/webwxoplog?lang=zh_CN&pass_ticket=%s", "修改好友备注"),
|
||||||
|
WEB_WX_VERIFYUSER("%s/webwxverifyuser?r=%s&lang=zh_CN&pass_ticket=%s", "被动添加好友"),
|
||||||
|
WEB_WX_GET_MEDIA("%s/webwxgetmedia", "下载文件")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
URLEnum(String url, String msg) {
|
||||||
|
this.url = url;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums.parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 基本请求参数
|
||||||
|
* 1. webWxInit 初始化
|
||||||
|
* 2. wxStatusNotify 微信状态通知
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Created by xiaoxiaomo on 2017/5/7.
|
||||||
|
*/
|
||||||
|
public enum BaseParaEnum {
|
||||||
|
|
||||||
|
Uin("Uin", "wxuin"),
|
||||||
|
Sid("Sid", "wxsid"),
|
||||||
|
Skey("Skey", "skey"),
|
||||||
|
DeviceID("DeviceID", "pass_ticket");
|
||||||
|
|
||||||
|
private String para;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
BaseParaEnum(String para, String value) {
|
||||||
|
this.para = para;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String para() {
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums.parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登陆
|
||||||
|
* <p>
|
||||||
|
* Created by xiaoxiaomo on 2017/5/7.
|
||||||
|
*/
|
||||||
|
public enum LoginParaEnum {
|
||||||
|
|
||||||
|
LOGIN_ICON("loginicon", "true"),
|
||||||
|
UUID("uuid", ""),
|
||||||
|
TIP("tip", "0"),
|
||||||
|
R("r", ""),
|
||||||
|
_("_", "");
|
||||||
|
|
||||||
|
private String para;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
LoginParaEnum(String para, String value) {
|
||||||
|
this.para = para;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String para() {
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums.parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态通知
|
||||||
|
* <p>
|
||||||
|
* Created by xiaoxiaomo on 2017/5/7.
|
||||||
|
*/
|
||||||
|
public enum StatusNotifyParaEnum {
|
||||||
|
|
||||||
|
CODE("Code", "3"),
|
||||||
|
FROM_USERNAME("FromUserName", ""),
|
||||||
|
TO_USERNAME("ToUserName", ""),
|
||||||
|
CLIENT_MSG_ID("ClientMsgId", ""); //时间戳
|
||||||
|
|
||||||
|
private String para;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
StatusNotifyParaEnum(String para, String value) {
|
||||||
|
this.para = para;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String para() {
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package cn.zhouyafeng.itchat4j.utils.enums.parameters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUID
|
||||||
|
* <p>
|
||||||
|
* Created by xiaoxiaomo on 2017/5/7.
|
||||||
|
*/
|
||||||
|
public enum UUIDParaEnum {
|
||||||
|
|
||||||
|
APP_ID("appid", "wx782c26e4c19acffb"),
|
||||||
|
FUN("fun", "new"),
|
||||||
|
LANG("lang", "zh_CN"),
|
||||||
|
_("_", "时间戳");
|
||||||
|
|
||||||
|
private String para;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
UUIDParaEnum(String para, String value) {
|
||||||
|
this.para = para;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String para() {
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package xyz.wbsite.itchat4j;
|
||||||
|
|
||||||
|
import cn.zhouyafeng.itchat4j.beans.BaseMsg;
|
||||||
|
import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace;
|
||||||
|
|
||||||
|
public class JMsgHandler implements IMsgHandlerFace {
|
||||||
|
@Override
|
||||||
|
public String textMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return baseMsg.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String picMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String voiceMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String viedoMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String nameCardMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sysMsgHandle(BaseMsg baseMsg) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String verifyAddFriendMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String mediaMsgHandle(BaseMsg baseMsg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package xyz.wbsite.itchat4j;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.setting.dialect.Props;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首选项配置
|
||||||
|
*/
|
||||||
|
public class JProp {
|
||||||
|
|
||||||
|
private static final JProp instance = new JProp();
|
||||||
|
|
||||||
|
private final File propFile;
|
||||||
|
|
||||||
|
private final Props props;
|
||||||
|
|
||||||
|
public static JProp getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JProp() {
|
||||||
|
this.propFile = new File("prop.ini");
|
||||||
|
if (!propFile.exists()) {
|
||||||
|
FileUtil.touch(propFile.getAbsolutePath());
|
||||||
|
this.props = new Props(propFile, StandardCharsets.UTF_8);
|
||||||
|
// 做一些初始化操作
|
||||||
|
} else {
|
||||||
|
this.props = new Props(propFile, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
this.props.store(propFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(String key, String defaultValue) {
|
||||||
|
return this.props.getStr(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getStringArray(String key, String[] defaultValue) {
|
||||||
|
return this.props.getStr(key, "").split(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(String key, int defaultValue) {
|
||||||
|
return this.props.getInt(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(String key, long defaultValue) {
|
||||||
|
return this.props.getLong(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloat(String key, float defaultValue) {
|
||||||
|
return this.props.getFloat(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getDouble(String key, double defaultValue) {
|
||||||
|
return this.props.getDouble(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setString(String key, String value) {
|
||||||
|
this.props.setProperty(key, value);
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringArray(String key, String[] value) {
|
||||||
|
this.props.setProperty(key, String.join(",", value));
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInt(String key, int value) {
|
||||||
|
this.props.setProperty(key, String.valueOf(value));
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLong(String key, long value) {
|
||||||
|
this.props.setProperty(key, String.valueOf(value));
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloat(String key, float value) {
|
||||||
|
this.props.setProperty(key, String.valueOf(value));
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDouble(String key, double value) {
|
||||||
|
this.props.setProperty(key, String.valueOf(value));
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
package xyz.wbsite.itchat4j.db;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.sql.Types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xyz.wbsite.wsqlite.Client
|
||||||
|
*
|
||||||
|
* @author wangbing
|
||||||
|
*/
|
||||||
|
public class Client {
|
||||||
|
|
||||||
|
Connection connection;
|
||||||
|
ResultSet resultSet;
|
||||||
|
String dbFilePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
*
|
||||||
|
* @param dbFile 文件
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public Client(File dbFile) throws ClassNotFoundException, SQLException {
|
||||||
|
this.dbFilePath = dbFile.getAbsolutePath();
|
||||||
|
if (!dbFile.exists()) {
|
||||||
|
connection = getConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行sql语句
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public void execute(String sql) throws SQLException, ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
executeUpdate(sql);
|
||||||
|
} finally {
|
||||||
|
destroyed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行sql查询语句
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public ResultSet executeQuery(String sql, Object... args) throws SQLException, ClassNotFoundException {
|
||||||
|
PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
|
||||||
|
setArg(preparedStatement, args);
|
||||||
|
return preparedStatement.executeQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行sql语句
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
public int executeUpdate(String sql, Object... args) throws SQLException, ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
|
||||||
|
setArg(preparedStatement, args);
|
||||||
|
return preparedStatement.executeUpdate();
|
||||||
|
} finally {
|
||||||
|
destroyed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setArg(PreparedStatement ps, Object... args) throws SQLException {
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
Object arg = args[i];
|
||||||
|
|
||||||
|
if (arg == null) {
|
||||||
|
ps.setNull(i + 1, Types.NULL);
|
||||||
|
} else if (arg instanceof String) {
|
||||||
|
ps.setString(i + 1, (String) arg);
|
||||||
|
} else if (arg instanceof Date) {
|
||||||
|
ps.setDate(i + 1, (Date) arg);
|
||||||
|
} else if (arg instanceof Time) {
|
||||||
|
ps.setTime(i + 1, (Time) arg);
|
||||||
|
} else if (arg instanceof java.util.Date) {
|
||||||
|
ps.setLong(i + 1, ((java.util.Date) arg).getTime());
|
||||||
|
} else if (arg instanceof Boolean) {
|
||||||
|
ps.setBoolean(i + 1, (Boolean) arg);
|
||||||
|
} else if (arg instanceof Byte) {
|
||||||
|
ps.setByte(i + 1, (Byte) arg);
|
||||||
|
} else if (arg instanceof Short) {
|
||||||
|
ps.setShort(i + 1, (Short) arg);
|
||||||
|
} else if (arg instanceof Integer) {
|
||||||
|
ps.setInt(i + 1, (int) arg);
|
||||||
|
} else if (arg instanceof Long) {
|
||||||
|
ps.setLong(i + 1, (long) arg);
|
||||||
|
} else if (arg instanceof Float) {
|
||||||
|
ps.setFloat(i + 1, (float) arg);
|
||||||
|
} else if (arg instanceof Double) {
|
||||||
|
ps.setDouble(i + 1, (double) arg);
|
||||||
|
} else if (arg instanceof byte[]) {
|
||||||
|
ps.setBytes(i + 1, (byte[]) arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库连接
|
||||||
|
*
|
||||||
|
* @return 数据库连接
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
Connection getConnection() throws ClassNotFoundException, SQLException {
|
||||||
|
if (null == connection) {
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
connection = DriverManager.getConnection("jdbc:sqlite:" + dbFilePath);
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库资源关闭和释放
|
||||||
|
*/
|
||||||
|
public void destroyed() {
|
||||||
|
try {
|
||||||
|
if (null != resultSet) {
|
||||||
|
resultSet.close();
|
||||||
|
resultSet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != connection) {
|
||||||
|
connection.close();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package xyz.wbsite.itchat4j.db;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Where {
|
||||||
|
private String sql;
|
||||||
|
private Object[] args;
|
||||||
|
|
||||||
|
private Where() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSql() {
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSql(String sql) {
|
||||||
|
this.sql = sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArgs(Object[] args) {
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Where(String sql, Object[] args) {
|
||||||
|
this.sql = sql;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private StringBuilder sb = new StringBuilder();
|
||||||
|
private List<Object> argsList = new ArrayList<>();
|
||||||
|
|
||||||
|
public Builder eq(String name, Object value) {
|
||||||
|
return eq(true, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder like(String name, Object value) {
|
||||||
|
return like(true, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isNull(String name, Object value) {
|
||||||
|
return isNull(true, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isNotNull(String name, Object value) {
|
||||||
|
return isNotNull(true, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder eq(boolean condition, String name, Object value) {
|
||||||
|
if (condition) {
|
||||||
|
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append(" = ? ");
|
||||||
|
argsList.add(value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder like(boolean condition, String name, Object value) {
|
||||||
|
if (condition) {
|
||||||
|
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("like ?");
|
||||||
|
argsList.add(value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isNull(boolean condition, String name, Object value) {
|
||||||
|
if (condition) {
|
||||||
|
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is null");
|
||||||
|
argsList.add(value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder isNotNull(boolean condition, String name, Object value) {
|
||||||
|
if (condition) {
|
||||||
|
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is not null");
|
||||||
|
argsList.add(value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Where build() {
|
||||||
|
return new Where(sb.toString(), argsList.toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package xyz.wbsite.itchat4j.db.anonation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface TableField {
|
||||||
|
|
||||||
|
int value() default 20;
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package xyz.wbsite.itchat4j.db.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import xyz.wbsite.itchat4j.db.anonation.TableField;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class Example {
|
||||||
|
|
||||||
|
@TableField(40)
|
||||||
|
private String s;
|
||||||
|
@TableField
|
||||||
|
private boolean b;
|
||||||
|
@TableField
|
||||||
|
private byte[] bs;
|
||||||
|
@TableField
|
||||||
|
private byte b1;
|
||||||
|
@TableField
|
||||||
|
private short s1;
|
||||||
|
@TableField
|
||||||
|
private int age;
|
||||||
|
@TableField
|
||||||
|
private long id;
|
||||||
|
@TableField
|
||||||
|
private float f1;
|
||||||
|
@TableField
|
||||||
|
private double d1;
|
||||||
|
@TableField
|
||||||
|
private Date date;
|
||||||
|
|
||||||
|
public String getS() {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setS(String s) {
|
||||||
|
this.s = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isB() {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setB(boolean b) {
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getBs() {
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBs(byte[] bs) {
|
||||||
|
this.bs = bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getB1() {
|
||||||
|
return b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setB1(byte b1) {
|
||||||
|
this.b1 = b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getS1() {
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setS1(short s1) {
|
||||||
|
this.s1 = s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getF1() {
|
||||||
|
return f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setF1(float f1) {
|
||||||
|
this.f1 = f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getD1() {
|
||||||
|
return d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setD1(double d1) {
|
||||||
|
this.d1 = d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package xyz.wbsite.itchat4j.ui;
|
||||||
|
|
||||||
|
import xyz.wbsite.itchat4j.util.ResourceUtil;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FXML工具
|
||||||
|
*
|
||||||
|
* @author wangbing
|
||||||
|
* @version 0.0.1
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public class FXMLUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载FXMLLoader
|
||||||
|
*
|
||||||
|
* @param fxml 资源路径
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static FXMLLoader load(String fxml) throws IOException {
|
||||||
|
if (!fxml.startsWith("classpath:")) {
|
||||||
|
fxml = "classpath:" + fxml;
|
||||||
|
}
|
||||||
|
URL resource = ResourceUtil.getURL(fxml);
|
||||||
|
FXMLLoader fxmlLoader = new FXMLLoader(resource);
|
||||||
|
fxmlLoader.load();
|
||||||
|
return fxmlLoader;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,269 @@
|
|||||||
|
package xyz.wbsite.itchat4j.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import xyz.wbsite.itchat4j.JMainApplication;
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ButtonBar;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.ProgressIndicator;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Font;
|
||||||
|
import javafx.stage.Modality;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class DialogUtil {
|
||||||
|
|
||||||
|
private static Stage popup;
|
||||||
|
|
||||||
|
public static void toast(String msg, long time) {
|
||||||
|
Label label = new Label(msg);//默认信息
|
||||||
|
label.setStyle("-fx-background: rgba(56,56,56,0.7);-fx-border-radius: 25;-fx-background-radius: 25");//label透明,圆角
|
||||||
|
label.setTextFill(Color.rgb(225, 255, 226));//消息字体颜色
|
||||||
|
label.setPrefHeight(50);
|
||||||
|
label.setPadding(new Insets(15));
|
||||||
|
label.setAlignment(Pos.CENTER);//居中
|
||||||
|
label.setFont(new Font(20));//字体大小
|
||||||
|
Scene scene = new Scene(label);
|
||||||
|
scene.setFill(null);//场景透明
|
||||||
|
Stage stage = new Stage();
|
||||||
|
stage.initModality(Modality.WINDOW_MODAL);
|
||||||
|
stage.setAlwaysOnTop(false);
|
||||||
|
stage.setScene(scene);
|
||||||
|
label.setText(msg);
|
||||||
|
TimerTask task = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Platform.runLater(stage::close);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Timer timer = new Timer();
|
||||||
|
timer.schedule(task, time);
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showTimedDialog(final long time, String message) {
|
||||||
|
popup = new Stage();
|
||||||
|
popup.setAlwaysOnTop(true);
|
||||||
|
popup.initModality(Modality.APPLICATION_MODAL);
|
||||||
|
final Button closeBtn = new Button("知道了");
|
||||||
|
closeBtn.setOnAction(event -> popup.close());
|
||||||
|
VBox root = new VBox();
|
||||||
|
root.setPadding(new Insets(10));
|
||||||
|
root.setAlignment(Pos.BASELINE_CENTER);
|
||||||
|
root.setSpacing(10);
|
||||||
|
root.getChildren().addAll(new Label(message), closeBtn);
|
||||||
|
Scene scene = new Scene(root);
|
||||||
|
popup.setScene(scene);
|
||||||
|
popup.setTitle("提示信息");
|
||||||
|
popup.show();
|
||||||
|
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
Thread.sleep(time);
|
||||||
|
if (popup.isShowing()) {
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
popup.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception exp) {
|
||||||
|
exp.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.setDaemon(true);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void alert(String message) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
|
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
|
||||||
|
stage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
|
||||||
|
stage.setAlwaysOnTop(true);
|
||||||
|
alert.setHeaderText(null);
|
||||||
|
alert.setTitle("提示");
|
||||||
|
alert.setContentText(message);
|
||||||
|
alert.getButtonTypes().remove(ButtonType.CANCEL);
|
||||||
|
alert.setX(JMainApplication.primaryStage.getX() + JMainApplication.primaryStage.getWidth() / 2 - 213);
|
||||||
|
alert.setY(JMainApplication.primaryStage.getY() + JMainApplication.primaryStage.getHeight() / 2 - 70);
|
||||||
|
Optional<ButtonType> buttonType = alert.showAndWait();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void confirm(String message) {
|
||||||
|
confirm("提示", message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void confirm(String title, String message) {
|
||||||
|
confirm(title, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void confirm(String title, String message, ConfirmCall call) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
|
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
|
||||||
|
stage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
|
||||||
|
stage.setAlwaysOnTop(true);
|
||||||
|
alert.setHeaderText(null);
|
||||||
|
alert.setTitle(title);
|
||||||
|
alert.setContentText(message);
|
||||||
|
alert.setX(JMainApplication.primaryStage.getX() + JMainApplication.primaryStage.getWidth() / 2 - 213);
|
||||||
|
alert.setY(JMainApplication.primaryStage.getY() + JMainApplication.primaryStage.getHeight() / 2 - 70);
|
||||||
|
Optional<ButtonType> buttonType = alert.showAndWait();
|
||||||
|
if (call != null) {
|
||||||
|
if (ButtonBar.ButtonData.OK_DONE.getTypeCode().equals(buttonType.get().getButtonData().getTypeCode())) {
|
||||||
|
call.call(true);
|
||||||
|
} else {
|
||||||
|
call.call(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(String message) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
|
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
|
||||||
|
stage.setAlwaysOnTop(true);
|
||||||
|
stage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
|
||||||
|
alert.setTitle("错误");
|
||||||
|
alert.setX(JMainApplication.primaryStage.getX() + JMainApplication.primaryStage.getWidth() / 2 - 213);
|
||||||
|
alert.setY(JMainApplication.primaryStage.getY() + JMainApplication.primaryStage.getHeight() / 2 - 70);
|
||||||
|
alert.setHeaderText("");
|
||||||
|
alert.setContentText(message);
|
||||||
|
alert.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void success(String message) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||||
|
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
|
||||||
|
stage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
|
||||||
|
alert.setTitle("消息");
|
||||||
|
alert.setX(JMainApplication.primaryStage.getX() + JMainApplication.primaryStage.getWidth() / 2 - 213);
|
||||||
|
alert.setY(JMainApplication.primaryStage.getY() + JMainApplication.primaryStage.getHeight() / 2 - 70);
|
||||||
|
alert.setHeaderText("");
|
||||||
|
alert.setContentText(message);
|
||||||
|
alert.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static javafx.scene.control.Dialog dialog = null;
|
||||||
|
|
||||||
|
public static void loading(String message) {
|
||||||
|
loading(message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loading(String message, CancelCall cancelCall) {
|
||||||
|
if (dialog != null) return;
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
dialog = new javafx.scene.control.Dialog();
|
||||||
|
dialog.setTitle("提示");
|
||||||
|
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
|
||||||
|
stage.getIcons().add(new Image(ResourceUtil.getInput("icon.png")));
|
||||||
|
dialog.setResult("1");
|
||||||
|
dialog.setX(JMainApplication.primaryStage.getX() + JMainApplication.primaryStage.getWidth() / 2 - 68);
|
||||||
|
dialog.setY(JMainApplication.primaryStage.getY() + JMainApplication.primaryStage.getHeight() / 2 - 70);
|
||||||
|
GridPane gridPane = new GridPane();
|
||||||
|
gridPane.setPrefWidth(200);
|
||||||
|
gridPane.setHgap(10);
|
||||||
|
gridPane.setVgap(10);
|
||||||
|
gridPane.setAlignment(Pos.CENTER);
|
||||||
|
gridPane.setPadding(new Insets(10, 10, 10, 10));
|
||||||
|
dialog.getDialogPane().setContent(gridPane);
|
||||||
|
|
||||||
|
ProgressIndicator indicator = new ProgressIndicator();
|
||||||
|
indicator.setPrefSize(30, 30);
|
||||||
|
gridPane.add(indicator, 0, 0);
|
||||||
|
gridPane.add(new Label(message), 0, 1);
|
||||||
|
|
||||||
|
if (cancelCall != null) {
|
||||||
|
Button cancel = new Button("取消");
|
||||||
|
gridPane.add(cancel, 0, 2);
|
||||||
|
cancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handle(MouseEvent event) {
|
||||||
|
cancelCall.call();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dialog.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hideLoading() {
|
||||||
|
if (dialog == null) return;
|
||||||
|
Platform.runLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
dialog.close();
|
||||||
|
dialog = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface InputCall {
|
||||||
|
void call(String input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ConfirmCall {
|
||||||
|
void call(boolean result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface DirectoryCall {
|
||||||
|
void call(File result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CancelCall {
|
||||||
|
void call();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给组件增加鼠标悬浮提示
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
* @param tip
|
||||||
|
*/
|
||||||
|
public static void installTip(Node node, String tip) {
|
||||||
|
Tooltip tooltip = new Tooltip(tip);
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Field behavior = ClassUtil.getDeclaredField(Tooltip.class, "BEHAVIOR");
|
||||||
|
behavior.setAccessible(true);
|
||||||
|
Object o = behavior.get(tooltip);
|
||||||
|
java.lang.reflect.Field activationTimer = ClassUtil.getDeclaredField(o.getClass(), "activationTimer");
|
||||||
|
activationTimer.setAccessible(true);
|
||||||
|
Timeline timeline = (Timeline) activationTimer.get(o);
|
||||||
|
timeline.getKeyFrames().remove(0);
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(new Duration(10)));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Tooltip.install(node, tooltip);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package xyz.wbsite.itchat4j.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.lang.caller.CallerUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.log.level.Level;
|
||||||
|
import xyz.wbsite.itchat4j.JMainApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志记录器
|
||||||
|
*
|
||||||
|
* @author wangbing
|
||||||
|
* @version 0.0.1
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public class Logger {
|
||||||
|
|
||||||
|
public static void info(String format, Object... arg) {
|
||||||
|
// 获取当前时间
|
||||||
|
DateTime date = DateUtil.date();
|
||||||
|
// 获取日志级别
|
||||||
|
String level = Level.INFO.toString();
|
||||||
|
// 格式化日志信息
|
||||||
|
String log = StrUtil.format(format, arg);
|
||||||
|
// 获取调用者类名
|
||||||
|
String name = CallerUtil.getCallerCaller().getSimpleName();
|
||||||
|
// 获取当前线程的堆栈追踪
|
||||||
|
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||||
|
// 通常堆栈追踪数组的第三个元素是logMessage方法的调用者
|
||||||
|
int lineNumber = stackTrace[2].getLineNumber();
|
||||||
|
// 打印日志信息
|
||||||
|
JMainApplication.mainController.println("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(String format, Object... arg) {
|
||||||
|
// 获取当前时间
|
||||||
|
DateTime date = DateUtil.date();
|
||||||
|
// 获取日志级别
|
||||||
|
String level = Level.ERROR.toString();
|
||||||
|
// 格式化日志信息
|
||||||
|
String log = StrUtil.format(format, arg);
|
||||||
|
// 获取调用者类名
|
||||||
|
String name = CallerUtil.getCallerCaller().getSimpleName();
|
||||||
|
// 获取当前线程的堆栈追踪
|
||||||
|
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||||
|
// 通常堆栈追踪数组的第三个元素是logMessage方法的调用者
|
||||||
|
int lineNumber = stackTrace[2].getLineNumber();
|
||||||
|
// 打印日志信息
|
||||||
|
JMainApplication.mainController.println("[{}] [{}] {} [{}:{}]", date, level, log, name, lineNumber);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package xyz.wbsite.itchat4j.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.resource.ClassPathResource;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源工具
|
||||||
|
*
|
||||||
|
* @author wangbing
|
||||||
|
* @version 0.0.1
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public class ResourceUtil extends cn.hutool.core.io.resource.ResourceUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取资源输入流,以/开始
|
||||||
|
*
|
||||||
|
* @return 资源路径
|
||||||
|
*/
|
||||||
|
public static InputStream getInput(String resourceLocation) {
|
||||||
|
if (resourceLocation.startsWith("/")) {
|
||||||
|
resourceLocation = "/" + resourceLocation;
|
||||||
|
}
|
||||||
|
ClassPathResource classPathResource = new ClassPathResource(resourceLocation);
|
||||||
|
return classPathResource.getStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取资源路径
|
||||||
|
*
|
||||||
|
* @param resourceLocation 资源
|
||||||
|
*/
|
||||||
|
public static URL getURL(String resourceLocation) throws FileNotFoundException {
|
||||||
|
if (resourceLocation.startsWith("classpath:")) {
|
||||||
|
String path = resourceLocation.substring("classpath:".length());
|
||||||
|
ClassLoader cl = FXMLLoader.getDefaultClassLoader();
|
||||||
|
URL url = cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path);
|
||||||
|
if (url == null) {
|
||||||
|
String description = "class path resource [" + path + "]";
|
||||||
|
throw new FileNotFoundException(description + " cannot be resolved to URL because it does not exist");
|
||||||
|
} else {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return new URL(resourceLocation);
|
||||||
|
} catch (MalformedURLException var6) {
|
||||||
|
try {
|
||||||
|
return (new File(resourceLocation)).toURI().toURL();
|
||||||
|
} catch (MalformedURLException var5) {
|
||||||
|
throw new FileNotFoundException("Resource location [" + resourceLocation + "] is neither a URL not a well-formed file path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,12 @@
|
|||||||
|
/* styles.css */
|
||||||
|
.text-area,
|
||||||
|
.text-area:focused,
|
||||||
|
.text-area:unfocused,
|
||||||
|
.text-area:disabled {
|
||||||
|
-fx-control-inner-background: transparent;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area .content {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
Loading…
Reference in new issue