Compare commits

...

2 Commits

Author SHA1 Message Date
c271bce942 opt: json错误提示 2026-02-04 15:31:14 +08:00
99deee4876 opt: 格式化json优化 2026-02-04 14:20:44 +08:00

View File

@@ -15,15 +15,45 @@
</a-col>
<a-col :span="12">
<a-form-item label="请求方法" name="apiMethod">
<a-input v-model:value="formData.apiMethod" placeholder="请输入请求方法GET, POST, PUT, DELETE" allow-clear />
<a-input
v-model:value="formData.apiMethod"
placeholder="请输入请求方法GET, POST, PUT, DELETE"
allow-clear
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-col :span="24">
<a-form-item label="返回数据:" name="responseJson">
<a-input v-model:value="formData.responseJson" placeholder="请输入返回的JSON数据" allow-clear />
<div style="position: relative">
<a-textarea
v-model:value="formData.responseJson"
placeholder="请输入返回的JSON数据"
:rows="10"
allow-clear
:status="jsonError ? 'error' : ''"
style="font-family: 'Courier New', monospace"
@blur="validateJson"
@input="onJsonInput"
/>
<a-button
type="link"
size="small"
style="position: absolute; top: 8px; right: 8px; z-index: 1"
@click="formatJson"
>
<template #icon>
<AlignLeftOutlined />
</template>
格式化
</a-button>
</div>
<div v-if="jsonError" style="color: #ff4d4f; font-size: 12px; margin-top: 4px; line-height: 1.5">
<ExclamationCircleOutlined style="margin-right: 4px" />
{{ jsonError }}
</div>
</a-form-item>
</a-col>
<a-col :span="12">
<a-col :span="24">
<a-form-item label="是否启用" name="isEnabled">
<a-radio-group
v-model:value="formData.isEnabled"
@@ -42,9 +72,10 @@
</template>
<script setup name="mockConfigForm">
import { message } from 'ant-design-vue'
import { AlignLeftOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue'
import tool from '@/utils/tool'
import { cloneDeep } from 'lodash-es'
import { required } from '@/utils/formRules'
import mockConfigApi from '@/api/mock/mockConfigApi'
// 抽屉状态
const open = ref(false)
@@ -54,10 +85,12 @@
const formData = ref({})
const submitLoading = ref(false)
const isEnabledOptions = ref([])
const jsonError = ref('')
// 打开抽屉
const onOpen = (record) => {
open.value = true
jsonError.value = ''
// 加载是否启用字典0=否1=是)
isEnabledOptions.value = tool.dictList('IS_USED')
if (record) {
@@ -68,6 +101,15 @@
} else if (recordData.isEnabled === 1 || recordData.isEnabled === 0) {
recordData.isEnabled = String(recordData.isEnabled)
}
// 如果有JSON数据尝试格式化显示
if (recordData.responseJson) {
try {
const jsonObj = JSON.parse(recordData.responseJson)
recordData.responseJson = JSON.stringify(jsonObj, null, 2)
} catch (e) {
// 如果解析失败,保持原样
}
}
formData.value = Object.assign({}, recordData)
} else {
// 新增时默认启用:'1'
@@ -79,13 +121,95 @@
const onClose = () => {
formRef.value.resetFields()
formData.value = {}
jsonError.value = ''
open.value = false
}
// 默认要校验的
const formRules = {
// 实时验证JSON输入时
const onJsonInput = () => {
// 清空之前的错误,避免输入时频繁提示
if (jsonError.value) {
jsonError.value = ''
}
}
// 验证JSON格式
const validateJson = () => {
if (!formData.value.responseJson || formData.value.responseJson.trim() === '') {
jsonError.value = ''
return true
}
try {
JSON.parse(formData.value.responseJson)
jsonError.value = ''
return true
} catch (e) {
// 解析错误信息,提取行号和列号
const errorMsg = e.message
let errorDetail = 'JSON格式错误'
// 尝试提取位置信息
const positionMatch = errorMsg.match(/position (\d+)/)
const lineMatch = errorMsg.match(/line (\d+)/)
if (positionMatch) {
const position = parseInt(positionMatch[1])
const lines = formData.value.responseJson.substring(0, position).split('\n')
const line = lines.length
const column = lines[lines.length - 1].length + 1
errorDetail = `JSON格式错误${line} 行,第 ${column} 列附近`
} else if (lineMatch) {
errorDetail = `JSON格式错误${lineMatch[1]} 行附近`
}
// 添加具体错误原因
if (errorMsg.includes('Unexpected token')) {
const tokenMatch = errorMsg.match(/Unexpected token (.+?) in JSON/)
if (tokenMatch) {
errorDetail += ` - 意外的字符 "${tokenMatch[1]}"`
}
} else if (errorMsg.includes('Expected')) {
if (errorMsg.includes('comma')) {
errorDetail += ' - 缺少逗号'
} else if (errorMsg.includes('closing brace')) {
errorDetail += ' - 缺少右花括号 }'
} else if (errorMsg.includes('closing bracket')) {
errorDetail += ' - 缺少右方括号 ]'
}
} else if (errorMsg.includes('Unterminated string')) {
errorDetail += ' - 字符串未闭合'
}
jsonError.value = errorDetail
return false
}
}
// 格式化JSON
const formatJson = () => {
if (!formData.value.responseJson) {
message.warning('请先输入JSON数据')
return
}
try {
const jsonObj = JSON.parse(formData.value.responseJson)
formData.value.responseJson = JSON.stringify(jsonObj, null, 2)
jsonError.value = ''
message.success('格式化成功')
} catch (e) {
validateJson() // 显示详细错误信息
message.error('JSON格式错误请检查输入')
}
}
// 默认要校验的
const formRules = {}
// 验证并提交数据
const onSubmit = () => {
// 先验证JSON格式
if (formData.value.responseJson && formData.value.responseJson.trim() !== '') {
if (!validateJson()) {
message.error('JSON格式错误请修正后再保存')
return
}
}
formRef.value
.validate()
.then(() => {
@@ -97,6 +221,17 @@
} else if (formDataParam.isEnabled === '0') {
formDataParam.isEnabled = 0
}
// 提交前压缩JSON去除格式化的空格和换行确保后端能正常解析
if (formDataParam.responseJson && formDataParam.responseJson.trim() !== '') {
try {
const jsonObj = JSON.parse(formDataParam.responseJson)
formDataParam.responseJson = JSON.stringify(jsonObj)
} catch (e) {
message.error('JSON格式错误无法保存')
submitLoading.value = false
return
}
}
mockConfigApi
.mockConfigSubmitForm(formDataParam, formDataParam.id)
.then(() => {