fix(qa): bug fix
This commit is contained in:
@@ -6,9 +6,9 @@ NEXT_PUBLIC_ENV=development
|
|||||||
|
|
||||||
# redis
|
# redis
|
||||||
# NEXT_PUBLIC_REDIS_URL="172.16.115.128"
|
# NEXT_PUBLIC_REDIS_URL="172.16.115.128"
|
||||||
NEXT_PUBLIC_REDIS_URL="localhost"
|
NEXT_PUBLIC_REDIS_URL="172.30.21.213"
|
||||||
NEXT_PUBLIC_REDIS_PORT=9765
|
NEXT_PUBLIC_REDIS_PORT=9765
|
||||||
NEXT_PUBLIC_REDIS_PASSWORD=password
|
NEXT_PUBLIC_REDIS_PASSWORD=password
|
||||||
NEXT_PUBLIC_REDIS_USERNAME=default
|
NEXT_PUBLIC_REDIS_USERNAME=default
|
||||||
NEXT_PUBLIC_REDIS_DB=0
|
NEXT_PUBLIC_REDIS_DB=1
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Placeholder from "@tiptap/extension-placeholder"
|
|||||||
import { RichTextEditor } from "@mantine/tiptap"
|
import { RichTextEditor } from "@mantine/tiptap"
|
||||||
import { useTopToolsStore } from "../useTopToolsStore"
|
import { useTopToolsStore } from "../useTopToolsStore"
|
||||||
import { useKeyEventStore } from "../store"
|
import { useKeyEventStore } from "../store"
|
||||||
import { useEffect, useRef } from "react"
|
import { useEffect, useRef, type ChangeEvent } from "react"
|
||||||
import { Box } from "@mantine/core"
|
import { Box } from "@mantine/core"
|
||||||
import { IconPhoto } from "@tabler/icons-react"
|
import { IconPhoto } from "@tabler/icons-react"
|
||||||
import "@mantine/tiptap/styles.css"
|
import "@mantine/tiptap/styles.css"
|
||||||
@@ -33,6 +33,7 @@ const EditorContainer = ({
|
|||||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||||
|
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
|
immediatelyRender: false,
|
||||||
extensions: [
|
extensions: [
|
||||||
StarterKit,
|
StarterKit,
|
||||||
Underline,
|
Underline,
|
||||||
@@ -72,7 +73,7 @@ const EditorContainer = ({
|
|||||||
}
|
}
|
||||||
}, [value, editor])
|
}, [value, editor])
|
||||||
|
|
||||||
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleImageUpload = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0]
|
const file = e.target.files?.[0]
|
||||||
if (file && editor) {
|
if (file && editor) {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { IconEdit } from "@tabler/icons-react"
|
|||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
import parse from "html-react-parser"
|
import parse from "html-react-parser"
|
||||||
import { ArrowUpIcon, ArrowUpToLineIcon } from "lucide-react"
|
import { ArrowUpIcon, ArrowUpToLineIcon } from "lucide-react"
|
||||||
|
import dynamic from "next/dynamic"
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
useCallback,
|
useCallback,
|
||||||
@@ -36,7 +37,11 @@ import { useDescToolsStore } from "../useDescToolsStore"
|
|||||||
import { useTopToolsStore } from "../useTopToolsStore"
|
import { useTopToolsStore } from "../useTopToolsStore"
|
||||||
import { safeClone } from "../utils/clone"
|
import { safeClone } from "../utils/clone"
|
||||||
import CustomModal from "./CustomModal"
|
import CustomModal from "./CustomModal"
|
||||||
import EditorContainer, { splitWord } from "./EditorContainer"
|
import { splitWord } from "./EditorContainer"
|
||||||
|
|
||||||
|
const EditorContainer = dynamic(() => import("./EditorContainer"), {
|
||||||
|
ssr: false,
|
||||||
|
})
|
||||||
|
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
taskDetail?: Task.DataProps
|
taskDetail?: Task.DataProps
|
||||||
@@ -54,6 +59,25 @@ const escapeRegExp = (str: string) => {
|
|||||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getHtmlFromStoredValue = (value?: string) => {
|
||||||
|
if (!value) return ""
|
||||||
|
const [html] = value.split(splitWord)
|
||||||
|
return html ?? value
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTextFromHtml = (html: string) => {
|
||||||
|
return html
|
||||||
|
.replace(/<[^>]+>/g, "")
|
||||||
|
.replace(/ /g, " ")
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const ensureStoredValue = (value?: string) => {
|
||||||
|
if (!value) return ""
|
||||||
|
if (value.includes(splitWord)) return value
|
||||||
|
return `${value}${splitWord}${getTextFromHtml(value)}`
|
||||||
|
}
|
||||||
|
|
||||||
const RightQAContent = forwardRef(
|
const RightQAContent = forwardRef(
|
||||||
({ taskDetail }: ComponentProps, ref: React.Ref<unknown>) => {
|
({ taskDetail }: ComponentProps, ref: React.Ref<unknown>) => {
|
||||||
const { isView } = useTopToolsStore()
|
const { isView } = useTopToolsStore()
|
||||||
@@ -114,11 +138,21 @@ const RightQAContent = forwardRef(
|
|||||||
|
|
||||||
type QaObj = Record<string, any>
|
type QaObj = Record<string, any>
|
||||||
|
|
||||||
const handleFormUpdate = (changeValues: any) => {
|
const handleFormUpdate = (
|
||||||
|
changeValues: Record<string, any>,
|
||||||
|
rawEditorValue?: string
|
||||||
|
) => {
|
||||||
if (!selectedQuestion) return
|
if (!selectedQuestion) return
|
||||||
const keys = Object.keys(changeValues)
|
const keys = Object.keys(changeValues)
|
||||||
const hasTagChange = keys.includes("tag")
|
const hasTagChange = keys.includes("tag")
|
||||||
const formData = form.values
|
const formData = {
|
||||||
|
...form.values,
|
||||||
|
...changeValues,
|
||||||
|
}
|
||||||
|
const nextStoredValue =
|
||||||
|
typeof rawEditorValue === "string"
|
||||||
|
? ensureStoredValue(rawEditorValue)
|
||||||
|
: ensureStoredValue(formData.value)
|
||||||
const { label, type, category } = selectedQuestion
|
const { label, type, category } = selectedQuestion
|
||||||
const currentQaDataArr = currentQaData[category] ?? []
|
const currentQaDataArr = currentQaData[category] ?? []
|
||||||
let newArr: { [x: string]: any }[] = []
|
let newArr: { [x: string]: any }[] = []
|
||||||
@@ -127,7 +161,7 @@ const RightQAContent = forwardRef(
|
|||||||
if (question_name === label) {
|
if (question_name === label) {
|
||||||
newArr.push({
|
newArr.push({
|
||||||
[question_name]: {
|
[question_name]: {
|
||||||
value: type === "value" ? formData.value : detail.value,
|
value: type === "value" ? nextStoredValue : detail.value,
|
||||||
id: formData.round,
|
id: formData.round,
|
||||||
is_pre: detail.is_pre,
|
is_pre: detail.is_pre,
|
||||||
tag: formData.tag,
|
tag: formData.tag,
|
||||||
@@ -139,7 +173,7 @@ const RightQAContent = forwardRef(
|
|||||||
: dayjs().unix(),
|
: dayjs().unix(),
|
||||||
modify_uid: usePermissionStore.getState().user_id,
|
modify_uid: usePermissionStore.getState().user_id,
|
||||||
modify_timestamp: dayjs().unix(),
|
modify_timestamp: dayjs().unix(),
|
||||||
comment: type === "comment" ? formData.value : detail.comment,
|
comment: type === "comment" ? nextStoredValue : detail.comment,
|
||||||
flag: hasTagChange ? 0 : detail.tag === 2 ? 1 : 0,
|
flag: hasTagChange ? 0 : detail.tag === 2 ? 1 : 0,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -158,9 +192,13 @@ const RightQAContent = forwardRef(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onFieldChange = (field: string, value: any) => {
|
const onFieldChange = (
|
||||||
|
field: string,
|
||||||
|
value: any,
|
||||||
|
rawEditorValue?: string
|
||||||
|
) => {
|
||||||
form.setFieldValue(field, value)
|
form.setFieldValue(field, value)
|
||||||
handleFormUpdate({ [field]: value })
|
handleFormUpdate({ [field]: value }, rawEditorValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -170,12 +208,10 @@ const RightQAContent = forwardRef(
|
|||||||
selectedQuestion.type === "comment"
|
selectedQuestion.type === "comment"
|
||||||
) {
|
) {
|
||||||
const { value: v } = selectedQuestion
|
const { value: v } = selectedQuestion
|
||||||
let htmlText = ""
|
const htmlText =
|
||||||
if (selectedQuestion.type === "value") {
|
selectedQuestion.type === "value"
|
||||||
htmlText = v.value ? v.value.split(splitWord)[0] : ""
|
? getHtmlFromStoredValue(v.value)
|
||||||
} else {
|
: getHtmlFromStoredValue(v.comment)
|
||||||
htmlText = v.comment ? v.comment.split(splitWord)[0] : ""
|
|
||||||
}
|
|
||||||
const obj = {
|
const obj = {
|
||||||
value: htmlText,
|
value: htmlText,
|
||||||
round: v.id,
|
round: v.id,
|
||||||
@@ -183,7 +219,8 @@ const RightQAContent = forwardRef(
|
|||||||
}
|
}
|
||||||
form.setValues(obj)
|
form.setValues(obj)
|
||||||
}
|
}
|
||||||
}, [selectedQuestion, form])
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [selectedQuestion])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (updateDescDataFlag) {
|
if (updateDescDataFlag) {
|
||||||
@@ -230,9 +267,10 @@ const RightQAContent = forwardRef(
|
|||||||
const newQaData = safeClone(currentQaData)
|
const newQaData = safeClone(currentQaData)
|
||||||
|
|
||||||
const handleText = (v: string) => {
|
const handleText = (v: string) => {
|
||||||
// 提取文本内容
|
// 优先使用存储中的纯文本部分;若历史数据不规范则兜底从 HTML 中提取
|
||||||
const text = v.split(splitWord)[1]
|
const text =
|
||||||
let textContent = text.replace(/<[^>]+>/g, "")
|
v.split(splitWord)[1] ?? getTextFromHtml(getHtmlFromStoredValue(v))
|
||||||
|
let textContent = text
|
||||||
// 替换错词
|
// 替换错词
|
||||||
for (let i = 0; i < wrongWords.length; i++) {
|
for (let i = 0; i < wrongWords.length; i++) {
|
||||||
const wrong = escapeRegExp(wrongWords[i])
|
const wrong = escapeRegExp(wrongWords[i])
|
||||||
@@ -256,17 +294,20 @@ const RightQAContent = forwardRef(
|
|||||||
const { value, comment } = questionData
|
const { value, comment } = questionData
|
||||||
|
|
||||||
const update = (v: string, key: "value" | "comment") => {
|
const update = (v: string, key: "value" | "comment") => {
|
||||||
const checkValue = v.split(splitWord)[1]
|
const checkValue =
|
||||||
|
v.split(splitWord)[1] ??
|
||||||
|
getTextFromHtml(getHtmlFromStoredValue(v))
|
||||||
const updatedValue = handleText(v)
|
const updatedValue = handleText(v)
|
||||||
|
|
||||||
if (checkValue !== updatedValue) {
|
if (checkValue !== updatedValue) {
|
||||||
let newValue = `<p>${updatedValue}</p>${splitWord}${updatedValue}`
|
const htmlValue = `<p>${updatedValue}</p>`
|
||||||
|
let newValue = `${htmlValue}${splitWord}${updatedValue}`
|
||||||
questionData[key] = newValue
|
questionData[key] = newValue
|
||||||
if (
|
if (
|
||||||
selectedQuestion?.label === name &&
|
selectedQuestion?.label === name &&
|
||||||
selectedQuestion?.type === key
|
selectedQuestion?.type === key
|
||||||
)
|
)
|
||||||
form.setFieldValue("value", `<p>${updatedValue}</p>`)
|
form.setFieldValue("value", htmlValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,12 +353,10 @@ const RightQAContent = forwardRef(
|
|||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
{qaDataArr.map((qaObj, index) => {
|
{qaDataArr.map((qaObj, index) => {
|
||||||
const [question_name, detail] = Object.entries(qaObj)[0]
|
const [question_name, detail] = Object.entries(qaObj)[0]
|
||||||
const htmlText = detail.value
|
const htmlText = getHtmlFromStoredValue(detail.value)
|
||||||
? detail.value.split(splitWord)[0]
|
const commentHtmlText = getHtmlFromStoredValue(
|
||||||
: ""
|
detail.comment
|
||||||
const commentHtmlText = detail.comment
|
)
|
||||||
? detail.comment.split(splitWord)[0]
|
|
||||||
: ""
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -561,7 +600,9 @@ const RightQAContent = forwardRef(
|
|||||||
</Flex>
|
</Flex>
|
||||||
<EditorContainer
|
<EditorContainer
|
||||||
value={form.values.value}
|
value={form.values.value}
|
||||||
onChange={(val: any) => onFieldChange("value", val)}
|
onChange={(val: string) =>
|
||||||
|
onFieldChange("value", getHtmlFromStoredValue(val), val)
|
||||||
|
}
|
||||||
disabled={!selectedQuestion}
|
disabled={!selectedQuestion}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -601,7 +642,7 @@ const RightQAContent = forwardRef(
|
|||||||
const finalData = safeClone(currentQaData)
|
const finalData = safeClone(currentQaData)
|
||||||
const updateData = safeClone(currentOperation)
|
const updateData = safeClone(currentOperation)
|
||||||
let obj = {
|
let obj = {
|
||||||
value: formData.value ?? "<p></p>",
|
value: ensureStoredValue(formData.value ?? "<p></p>"),
|
||||||
id: formData.round_id,
|
id: formData.round_id,
|
||||||
is_pre: false,
|
is_pre: false,
|
||||||
tag: 0,
|
tag: 0,
|
||||||
@@ -657,7 +698,9 @@ const RightQAContent = forwardRef(
|
|||||||
</Text>
|
</Text>
|
||||||
<EditorContainer
|
<EditorContainer
|
||||||
value={textForm.values.value}
|
value={textForm.values.value}
|
||||||
onChange={(val: any) => textForm.setFieldValue("value", val)}
|
onChange={(val: string) =>
|
||||||
|
textForm.setFieldValue("value", getHtmlFromStoredValue(val))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
|
|||||||
Reference in New Issue
Block a user