DPS_Manage/Component/JsonEditor.qml

181 lines
5.7 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import JsonEditor 1.0
import HuskarUI.Basic 1.0
ScrollView {
width: 600
height: 400
property var projectConfigStr: null // 初始化为空对象
property var saveFunction: function(config){}
property var errorLine: null
property var errorPosition : null
// JSON 处理器
JsonProcessor {
id: jsonProcessor
}
// 将 UTF-8 字节偏移量转换为 UTF-16 代码单元索引
function utf8OffsetToUtf16Index(text, utf8Offset) {
var utf16Index = 0;
var utf8BytesCount = 0;
for (var i = 0; i < text.length; i++) {
var charCode = text.charCodeAt(i);
var charUtf8Length = 1;
if (charCode <= 0x7F) {
charUtf8Length = 1;
} else if (charCode <= 0x7FF) {
charUtf8Length = 2;
} else if (charCode <= 0xFFFF) {
charUtf8Length = 3;
} else {
charUtf8Length = 4;
}
if (utf8BytesCount + charUtf8Length > utf8Offset) {
break;
}
utf8BytesCount += charUtf8Length;
utf16Index++;
}
return utf16Index;
}
function getErrorLine(text, offset) {
var tbuf = text.slice(0,offset);
var lines = tbuf.split('\n')
if(lines.length > 0)return lines.length
return -1
}
Rectangle{
id:header_area
anchors.fill: parent
anchors.bottomMargin: 40
color:"transparent"
radius:8
border.color: HusTheme.isDark ? "#23272e" : "#f0f4f7"
border.width: 2
ScrollView {
id: textScrollView
anchors.fill: parent
clip: true
TextArea {
id: jsonEditor
font.family: "Consolas"
font.pixelSize: 14
wrapMode: TextArea.Wrap
placeholderText: "请输入JSON内容..."
selectByMouse: true
selectionColor: "#0078d4" // 选中区域颜色Fluent 主题蓝)
text:projectConfigStr
JsonHighlighter {
document: jsonEditor.textDocument
}
onTextChanged: {
var result = jsonProcessor.validateJson(jsonEditor.text)
if (result.hasError) {
var utf16Index = utf8OffsetToUtf16Index(jsonEditor.text, result.errorOffset);
errorPosition = utf16Index
// 计算错误行号
errorLine = getErrorLine(jsonEditor.text, utf16Index)
errorLabel.text = "❌ JSON语法错误" + ` ${errorLine} ${result.errorMessage}`
errorCanvas.requestPaint()
} else {
errorLine = -1
errorPosition = -1
}
errorLabel.visible = (errorLine !== -1)
}
}
Canvas {
id: errorCanvas
anchors.fill: parent
visible: errorPosition !== -1
z: 1
renderTarget: Canvas.Image
onPaint: {
var ctx = getContext("2d")
ctx.clearRect(0, 0, width, height)
if (errorPosition === -1) return
// 获取错误位置在TextArea中的坐标
var rect = jsonEditor.positionToRectangle(errorPosition)
if (!rect || rect.width === 0) return
// 关键步骤映射到ScrollView的contentItemFlickable
var flickablePos = jsonEditor.mapToItem(textScrollView.contentItem, rect.x, rect.y)
// 计算滚动偏移后的可视坐标(减去滚动量)
var canvasX = flickablePos.x - textScrollView.contentItem.contentX
var canvasY = flickablePos.y + textScrollView.contentItem.contentY
// 调整标记到文本下方
canvasY += rect.height
// 绘制红色三角形(向下箭头)
ctx.fillStyle = "#d13438"
ctx.beginPath()
ctx.moveTo(canvasX, canvasY) // 顶点
ctx.lineTo(canvasX - 8, canvasY + 10) // 左下
ctx.lineTo(canvasX + 8, canvasY + 10) // 右下
ctx.closePath()
ctx.fill()
}
// 滚动时实时更新
Connections {
target: textScrollView.contentItem
function onContentYChanged(){
errorCanvas.requestPaint()
}
function onContentXChanged(){
errorCanvas.requestPaint()
}
}
}
}
}
// 按钮区域(底部固定高度)
RowLayout {
anchors.top:header_area.bottom
anchors.topMargin: 6
anchors.horizontalCenter: parent.horizontalCenter
spacing: 15
// 错误提示
Text {
id: errorLabel
Layout.alignment: Qt.AlignHCenter
visible: false
color: "#d13438"
font.bold: true
}
HusButton {
text: "格式化"
onClicked: {
jsonEditor.text = jsonProcessor.formatJson(jsonEditor.text)
}
}
HusButton {
text: "保存"
onClicked: saveFunction(jsonEditor.text)
}
}
}