fix(ci): add file

This commit is contained in:
zhangheng
2026-03-28 16:39:27 +08:00
parent 27d47b5692
commit 76bfb30fef
5 changed files with 166 additions and 59 deletions

28
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,28 @@
stages:
- sync_github
sync_github:
stage: sync_github
tags:
- webfront
image: harbor.cowarobot.cn/softrepo/rust_build:1.94
script:
- echo "代码已合并到 main, 开始执行发布逻辑..."
- |
for i in {1..10}; do
if command -v docker >/dev/null 2>&1 && [ -S /var/run/docker.sock ]; then
echo "Docker is ready!"
break
fi
echo "Waiting for Docker..."
sleep 2
done
- docker info
- echo ${CI_PROJECT_NAME} ${CI_PROJECT_PATH} ${CI_PROJECT_DIR} ${CI_PROJECT_URL} ${CI_COMMIT_SHA}
- echo ${HARBORKEY} | docker login harbor.cowarobot.cn -u 'robot$softpro+cibuild' --password-stdin
- rm -rf ${CI_PROJECT_NAME}
- git clone https://oauth2:glpat-EdU8a_84jpSH2nOlNTkpnW86MQp1OjY1CA.01.0y1rtht99@git.cowarobot.com/${CI_PROJECT_PATH}
- cd ${CI_PROJECT_NAME}
- bash build.sh prod
rules:
- if: $CI_COMMIT_BRANCH == "main"

View File

@@ -1,6 +1,6 @@
export const BASE_LABEL_API =
process.env.NEXT_PUBLIC_ENV === "production"
? "https://label.cowarobot.com"
? "https://label.soft.cowarobot.com"
: process.env.NEXT_PUBLIC_ENV === "staging"
? "http://172.16.115.128:9110"
: "https://label.softtest.cowarobot.com"

View File

@@ -16,6 +16,12 @@ import "@mantine/tiptap/styles.css"
export const splitWord = "@1024-"
const getEditorHtml = (rawValue?: string) => {
if (!rawValue) return ""
const [html] = rawValue.split(splitWord)
return html ?? rawValue
}
interface EditorContainerProps {
value: string
onChange: (value: string) => void
@@ -41,11 +47,11 @@ const EditorContainer = ({
Image,
Placeholder.configure({ placeholder: "请输入内容..." }),
],
content: value,
content: getEditorHtml(value),
editable: !disabled && !isView,
onUpdate: ({ editor }) => {
// Preserve splitWord format
onChange(`${editor.getHTML()}${splitWord}${editor.getText()}`)
const html = getEditorHtml(editor.getHTML())
onChange(`${html}${splitWord}${editor.getText()}`)
},
onFocus: () => {
useKeyEventStore.getState().setFocusInput(true)
@@ -63,7 +69,7 @@ const EditorContainer = ({
useEffect(() => {
if (!editor) return
const incomingHtml = value ? value : "<p></p>"
const incomingHtml = getEditorHtml(value) || "<p></p>"
if (editor.getHTML() !== incomingHtml) {
// Keep editor content in sync with external state, including empty value switch.
editor.commands.setContent(incomingHtml, { emitUpdate: false })
@@ -91,7 +97,7 @@ const EditorContainer = ({
padding: "4px",
}}>
<RichTextEditor editor={editor} style={{ border: 0 }}>
<RichTextEditor.Toolbar sticky stickyOffset={60}>
<RichTextEditor.Toolbar>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />

View File

@@ -18,6 +18,7 @@ import { Task } from "../api/task/typing"
import { useBottomToolsStore } from "../useBottomToolsStore"
import { useDescToolsStore } from "../useDescToolsStore"
import { useTopToolsStore } from "../useTopToolsStore"
import { safeClone } from "../utils/clone"
import EditorContainer from "./EditorContainer"
interface ComponentProps {
@@ -40,46 +41,67 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
})
const isUpdatingFromStore = useRef(false)
const syncTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const handleFormUpdate = () => {
const setOperationField = (
labelClass: string,
field: string,
value: string | string[]
) => {
const current = ((form.values as any)[labelClass] ?? {}) as Record<
string,
any
>
form.setFieldValue(labelClass, {
...current,
[field]: value,
})
}
const handleFormUpdate = (values: any) => {
if (isUpdatingFromStore.current) return
const data = form.values as any
let dataMap = new Map()
taskDetail?.data_name.forEach((detail_name) => {
if (detail_name.name[0] !== activeImage) {
if (useDescToolsStore.getState().descData.has(detail_name.name[0])) {
dataMap.set(
detail_name.name[0],
useDescToolsStore.getState().descData.get(detail_name.name[0])
)
}
const currentDescData = safeClone(useDescToolsStore.getState().descData)
const updateMap = new Map()
Object.entries(values).forEach(([label_class, val]: any) => {
let value = { ...val }
if (value.is_correct !== undefined) {
value.is_correct = value.is_correct === "true"
}
const keys = Object.keys(value)
if (keys.includes("value")) {
updateMap.set(label_class, value)
} else {
const updateMap = new Map()
Object.entries(data).forEach(([label_class, val]: any) => {
let value = { ...val }
if (value.is_correct !== undefined) {
value.is_correct = value.is_correct === "true"
}
const keys = Object.keys(value)
if (keys.includes("value")) {
updateMap.set(label_class, value)
} else {
updateMap.set(label_class, { value: value })
}
})
dataMap.set(activeImage, updateMap)
updateMap.set(label_class, { value: value })
}
})
setDescData(dataMap)
currentDescData.set(activeImage, updateMap)
setDescData(currentDescData)
}
useEffect(() => {
handleFormUpdate()
if (isUpdatingFromStore.current) return
if (syncTimerRef.current) {
clearTimeout(syncTimerRef.current)
}
syncTimerRef.current = setTimeout(() => {
handleFormUpdate(form.values)
syncTimerRef.current = null
}, 180)
return () => {
if (syncTimerRef.current) {
clearTimeout(syncTimerRef.current)
syncTimerRef.current = null
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [form.values])
useEffect(() => {
if (syncTimerRef.current) {
clearTimeout(syncTimerRef.current)
syncTimerRef.current = null
}
isUpdatingFromStore.current = true
form.reset()
if (activeImage) {
@@ -109,6 +131,10 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
useEffect(() => {
if (updateDescDataFlag) {
if (syncTimerRef.current) {
clearTimeout(syncTimerRef.current)
syncTimerRef.current = null
}
isUpdatingFromStore.current = true
const formData = useDescToolsStore
.getState()
@@ -133,6 +159,15 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [updateDescDataFlag])
useEffect(() => {
return () => {
if (syncTimerRef.current) {
clearTimeout(syncTimerRef.current)
syncTimerRef.current = null
}
}
}, [])
return (
<Box h="100%">
<Box
@@ -156,7 +191,9 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
activeImage,
operation.label_class
)
const hasComment = currentData?.comment
const hasComment =
!!(form.values as any)?.[operation.label_class]?.comment ||
!!currentData?.comment
return (
<Box key={operation.label_class}>
@@ -171,9 +208,17 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
{operation.label_class}
</Text>
<Radio.Group
{...form.getInputProps(
`${operation.label_class}.is_correct`
)}
value={
(form.values as any)[operation.label_class]
?.is_correct || ""
}
onChange={(val) => {
setOperationField(
operation.label_class,
"is_correct",
val
)
}}
size="xs">
<Group gap="xs">
<Radio
@@ -195,8 +240,9 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
variant="subtle"
size="xs"
onClick={() => {
form.setFieldValue(
`${operation.label_class}.comment`,
setOperationField(
operation.label_class,
"comment",
"<p></p>"
)
}}>
@@ -215,9 +261,18 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
placeholder={`请输入${subDesc.chinese_name}`}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}
value={
(form.values as any)[operation.label_class]?.[
subDesc.chinese_name
] || ""
}
onChange={(event) => {
setOperationField(
operation.label_class,
subDesc.chinese_name,
event.currentTarget.value
)
}}
disabled={!!isView}
/>
) : subDesc.select_mode === 1 ? (
@@ -225,9 +280,18 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
label={subDesc.chinese_name}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}>
value={
(form.values as any)[operation.label_class]?.[
subDesc.chinese_name
] || ""
}
onChange={(val) => {
setOperationField(
operation.label_class,
subDesc.chinese_name,
val
)
}}>
<Group gap="xs" mt={4}>
{subDesc.optional_item.map((option) => (
<Radio
@@ -244,9 +308,18 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
label={subDesc.chinese_name}
size="xs"
required={!!subDesc.isrequired}
{...form.getInputProps(
`${operation.label_class}.${subDesc.chinese_name}`
)}>
value={
(form.values as any)[operation.label_class]?.[
subDesc.chinese_name
] || []
}
onChange={(val) => {
setOperationField(
operation.label_class,
subDesc.chinese_name,
val
)
}}>
<Group gap="xs" mt={4}>
{subDesc.optional_item.map((option) => (
<Checkbox
@@ -266,13 +339,11 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
<Box mb="xs">
<EditorContainer
value={
(form.values as any)[operation.label_class]?.value
(form.values as any)[operation.label_class]?.value ||
""
}
onChange={(val: any) =>
form.setFieldValue(
`${operation.label_class}.value`,
val
)
setOperationField(operation.label_class, "value", val)
}
/>
</Box>
@@ -282,14 +353,16 @@ const RightDescTools = ({ taskDetail }: ComponentProps) => {
<EditorContainer
color="border-danger"
value={
(form.values as any)[operation.label_class]?.comment
(form.values as any)[operation.label_class]
?.comment || ""
}
onChange={(val: any) =>
form.setFieldValue(
`${operation.label_class}.comment`,
onChange={(val: any) => {
setOperationField(
operation.label_class,
"comment",
val
)
}
}}
/>
</Box>
</>

View File

@@ -4,7 +4,7 @@ import { Login } from "./types"
const BASE_PATH =
process.env.NEXT_PUBLIC_ENV === "production"
? "https://label.cowarobot.com"
? "https://label.soft.cowarobot.com"
: process.env.NEXT_PUBLIC_ENV === "staging"
? "http://172.16.115.128:9110"
: "https://label.softtest.cowarobot.com"