mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-11-30 10:58:14 +08:00
优化 编辑组件可能出现行错和内容错乱问题
优化 查看系统日志的多次切换内容返回错乱问题
This commit is contained in:
parent
419b31d297
commit
dfe14fd74f
@ -22,6 +22,8 @@
|
||||
5. 【server】修复 初次安装服务端初始化数据库失败问题 (感谢@lg)
|
||||
6. 【server】优化 日志显示组件(取消正则搜索),日志删除 `ansi` 颜色
|
||||
(感谢[@苏生不语](https://gitee.com/sushengbuyu) [Gitee issues I657JR](https://gitee.com/dromara/Jpom/issues/I657JR) )
|
||||
7. 【server】优化 编辑组件可能出现行错和内容错乱问题
|
||||
8. 【server】优化 查看系统日志的多次切换内容返回错乱问题
|
||||
|
||||
### ❌ 不兼容功能
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
package io.jpom.socket.handler;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.jpom.JpomApplication;
|
||||
import io.jpom.common.forward.NodeUrl;
|
||||
@ -35,7 +34,6 @@ import io.jpom.socket.ConsoleCommandOp;
|
||||
import io.jpom.socket.ProxySession;
|
||||
import io.jpom.socket.ServiceFileTailWatcher;
|
||||
import io.jpom.system.LogbackConfig;
|
||||
import io.jpom.system.WebAopLog;
|
||||
import io.jpom.util.SocketSessionUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
@ -54,57 +52,57 @@ import java.util.Map;
|
||||
@Slf4j
|
||||
public class TomcatHandler extends BaseProxyHandler {
|
||||
|
||||
public TomcatHandler() {
|
||||
super(NodeUrl.Tomcat_Socket);
|
||||
}
|
||||
public TomcatHandler() {
|
||||
super(NodeUrl.Tomcat_Socket);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object[] getParameters(Map<String, Object> attributes) {
|
||||
return new Object[]{"tomcatId", attributes.get("tomcatId")};
|
||||
}
|
||||
@Override
|
||||
protected Object[] getParameters(Map<String, Object> attributes) {
|
||||
return new Object[]{"tomcatId", attributes.get("tomcatId")};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String handleTextMessage(Map<String, Object> attributes, WebSocketSession session, JSONObject json, ConsoleCommandOp consoleCommandOp) throws IOException {
|
||||
String tomcatId = (String) attributes.get("tomcatId");
|
||||
String fileName = json.getString("fileName");
|
||||
if (!JpomApplication.SYSTEM_ID.equals(tomcatId) && consoleCommandOp == ConsoleCommandOp.heart) {
|
||||
// 服务端心跳
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
protected String handleTextMessage(Map<String, Object> attributes, WebSocketSession session, JSONObject json, ConsoleCommandOp consoleCommandOp) throws IOException {
|
||||
String tomcatId = (String) attributes.get("tomcatId");
|
||||
String fileName = json.getString("fileName");
|
||||
if (!JpomApplication.SYSTEM_ID.equals(tomcatId) && consoleCommandOp == ConsoleCommandOp.heart) {
|
||||
// 服务端心跳
|
||||
return null;
|
||||
}
|
||||
|
||||
super.logOpt(this.getClass(), attributes, json);
|
||||
super.logOpt(this.getClass(), attributes, json);
|
||||
|
||||
//
|
||||
if (consoleCommandOp == ConsoleCommandOp.showlog && JpomApplication.SYSTEM_ID.equals(tomcatId)) {
|
||||
WebAopLog webAopLog = SpringUtil.getBean(WebAopLog.class);
|
||||
// 进入管理页面后需要实时加载日志
|
||||
File file = FileUtil.file(LogbackConfig.getPath(), fileName);
|
||||
//
|
||||
File nowFile = (File) attributes.get("nowFile");
|
||||
if (nowFile != null && !nowFile.equals(file)) {
|
||||
// 离线上一个日志
|
||||
ServiceFileTailWatcher.offlineFile(file, session);
|
||||
}
|
||||
try {
|
||||
ServiceFileTailWatcher.addWatcher(file, session);
|
||||
attributes.put("nowFile", file);
|
||||
} catch (Exception io) {
|
||||
log.error("监听日志变化", io);
|
||||
SocketSessionUtil.send(session, io.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//
|
||||
if (consoleCommandOp == ConsoleCommandOp.showlog && JpomApplication.SYSTEM_ID.equals(tomcatId)) {
|
||||
|
||||
@Override
|
||||
protected String handleTextMessage(Map<String, Object> attributes, ProxySession proxySession, JSONObject json, ConsoleCommandOp consoleCommandOp) {
|
||||
proxySession.send(json.toString());
|
||||
return null;
|
||||
}
|
||||
// 进入管理页面后需要实时加载日志
|
||||
File file = FileUtil.file(LogbackConfig.getPath(), fileName);
|
||||
//
|
||||
File nowFile = (File) attributes.get("nowFile");
|
||||
if (nowFile != null && !nowFile.equals(file)) {
|
||||
// 离线上一个日志
|
||||
ServiceFileTailWatcher.offlineFile(file, session);
|
||||
}
|
||||
try {
|
||||
ServiceFileTailWatcher.addWatcher(file, session);
|
||||
attributes.put("nowFile", file);
|
||||
} catch (Exception io) {
|
||||
log.error("监听日志变化", io);
|
||||
SocketSessionUtil.send(session, io.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(WebSocketSession session) {
|
||||
super.destroy(session);
|
||||
ServiceFileTailWatcher.offline(session);
|
||||
}
|
||||
@Override
|
||||
protected String handleTextMessage(Map<String, Object> attributes, ProxySession proxySession, JSONObject json, ConsoleCommandOp consoleCommandOp) {
|
||||
proxySession.send(json.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(WebSocketSession session) {
|
||||
super.destroy(session);
|
||||
ServiceFileTailWatcher.offline(session);
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +182,13 @@ export default {
|
||||
// 自动缩进,设置是否根据上下文自动缩进(和上一行相同的缩进量)。默认为true
|
||||
smartIndent: false,
|
||||
autocorrect: true,
|
||||
dragDrop: false,
|
||||
spellcheck: true,
|
||||
// scrollbarStyle: "Addons",
|
||||
// 指定当前滚动到视图中的文档部分的上方和下方呈现的行数。默认为10 - [integer]
|
||||
// // 有点类似于虚拟滚动显示
|
||||
// Infinity - 无限制,始终显示全部内容,但是数据量大的时候会造成页面卡顿
|
||||
viewportMargin: 10,
|
||||
hintOptions: this.cmHintOptions || {},
|
||||
extraKeys: {
|
||||
"Alt-Q": "autocomplete",
|
||||
@ -257,13 +263,16 @@ export default {
|
||||
immediate: true,
|
||||
},
|
||||
code(n) {
|
||||
if (n != this.editorValue) {
|
||||
try {
|
||||
this.editorValue = this.formatStrInJson(n);
|
||||
} catch (error) {
|
||||
this.editorValue = n;
|
||||
// 啥也不做
|
||||
}
|
||||
if (n !== this.editorValue) {
|
||||
setTimeout(() => {
|
||||
// 延迟赋值,避免行号错乱
|
||||
try {
|
||||
this.editorValue = this.formatStrInJson(n);
|
||||
} catch (error) {
|
||||
this.editorValue = n;
|
||||
// 啥也不做
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -346,10 +355,9 @@ export default {
|
||||
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
},
|
||||
scrollToBottom() {
|
||||
// 获取滚动信息 注意是两个codemirror.codemirror
|
||||
const sc = this.$refs.myCm.codemirror.getScrollInfo();
|
||||
// 滚动 注意是两个codemirror.codemirror
|
||||
this.$refs.myCm.codemirror.scrollTo(sc.left, sc.height + sc.top);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.myCm.codemirror.execCommand("goDocEnd");
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -12,22 +12,20 @@
|
||||
<a-tooltip title="清空当前缓冲区内容">
|
||||
<a-button type="link" style="padding: 0" @click="clearLogCache" icon="delete"><span style="margin-left: 2px">清空</span></a-button>
|
||||
</a-tooltip>
|
||||
<a-dropdown>
|
||||
<a-tooltip title="内容超过边界自动换行">
|
||||
<a-switch v-model="temp.wordBreak" checked-children="自动换行" un-checked-children="不换行" @change="onChange" />
|
||||
</a-tooltip>
|
||||
<a-tooltip title="有新内容后是否自动滚动到底部">
|
||||
<a-switch v-model="temp.logScroll" checked-children="自动滚动" un-checked-children="不滚动" @change="onChange" />
|
||||
</a-tooltip>
|
||||
<!-- <a-dropdown>
|
||||
<a-button type="link" style="padding: 0" icon="setting"> 设置 <a-icon type="down" /></a-button>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="0">
|
||||
<a-tooltip title="内容超过边界自动换行">
|
||||
<a-switch v-model="temp.wordBreak" checked-children="自动换行" un-checked-children="不换行" @change="onChange" />
|
||||
</a-tooltip>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="0"> </a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="3">
|
||||
<a-tooltip title="有新内容后是否自动滚动到底部">
|
||||
<a-switch v-model="temp.logScroll" checked-children="自动滚动" un-checked-children="不滚动" @change="onChange" />
|
||||
</a-tooltip>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="3"> </a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</a-dropdown> -->
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -4,7 +4,7 @@
|
||||
ref="codemirror"
|
||||
:style="`height:${this.height}`"
|
||||
v-model="showContext"
|
||||
:options="{ theme: 'panda-syntax', mode: 'verilog', tabSize: 2, readOnly: true, styleActiveLine: true, lineWrapping: this.config.wordBreak }"
|
||||
:options="{ theme: 'panda-syntax', mode: 'verilog', cursorBlinkRate: -1, tabSize: 2, readOnly: true, styleActiveLine: true, lineWrapping: this.config.wordBreak }"
|
||||
></code-editor>
|
||||
</div>
|
||||
</template>
|
||||
@ -67,10 +67,13 @@ export default {
|
||||
);
|
||||
})
|
||||
.join("");
|
||||
|
||||
if (this.config.logScroll) {
|
||||
// 获取滚动
|
||||
this.$refs.codemirror.scrollToBottom();
|
||||
setTimeout(() => {
|
||||
// 延迟触发滚动
|
||||
this.$nextTick(() => {
|
||||
this.$refs.codemirror.scrollToBottom();
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -132,6 +132,12 @@ export default {
|
||||
},
|
||||
// 选择节点
|
||||
select(selectedKeys, { node }) {
|
||||
if (this.temp?.path === node.dataRef?.path) {
|
||||
return;
|
||||
}
|
||||
if (!node.dataRef.isLeaf) {
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
op: "showlog",
|
||||
tomcatId: this.tomcatId,
|
||||
@ -139,9 +145,10 @@ export default {
|
||||
};
|
||||
this.temp = node.dataRef;
|
||||
this.$refs.logView.clearLogCache();
|
||||
if (!this.socket || this.socket.readyState !== this.socket.OPEN || this.socket.readyState !== this.socket.CONNECTING) {
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
}
|
||||
|
||||
this.socket?.close();
|
||||
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
// 连接成功后
|
||||
this.socket.onopen = () => {
|
||||
this.socket.send(JSON.stringify(data));
|
||||
|
@ -134,6 +134,9 @@ export default {
|
||||
if (this.temp?.path === node.dataRef?.path) {
|
||||
return;
|
||||
}
|
||||
if (!node.dataRef.isLeaf) {
|
||||
return;
|
||||
}
|
||||
const data = {
|
||||
op: "showlog",
|
||||
tomcatId: this.tomcatId,
|
||||
@ -141,9 +144,10 @@ export default {
|
||||
};
|
||||
this.temp = node.dataRef;
|
||||
this.$refs.logView.clearLogCache();
|
||||
if (!this.socket || this.socket.readyState !== this.socket.OPEN || this.socket.readyState !== this.socket.CONNECTING) {
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
}
|
||||
|
||||
this.socket?.close();
|
||||
|
||||
this.socket = new WebSocket(this.socketUrl);
|
||||
// 连接成功后
|
||||
this.socket.onopen = () => {
|
||||
this.socket.send(JSON.stringify(data));
|
||||
|
Loading…
Reference in New Issue
Block a user