use default props
Some checks failed
Deploy / deploy (build, debian, 22, /root/OJDeploy/data/clientnext) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822, /root/OJ/data/dist) (push) Has been cancelled

This commit is contained in:
2026-06-06 05:49:02 -06:00
parent 31d7f4d274
commit 4b05086ba1
13 changed files with 63 additions and 80 deletions

View File

@@ -60,7 +60,7 @@ import { useAIStore } from "oj/store/ai"
import { parseTime } from "utils/functions"
const aiStore = useAIStore()
const containerRef = ref<HTMLElement>()
const containerRef = useTemplateRef<HTMLElement>("containerRef")
const CELL_SIZE = 12
const CELL_GAP = 3

View File

@@ -31,9 +31,7 @@ interface Props {
isConnected?: boolean // WebSocket 实际的连接状态(已建立/未建立)
}
const props = withDefaults(defineProps<Props>(), {
isConnected: false,
})
const { storageKey, isConnected = false } = defineProps<Props>()
// 注入同步状态
const syncStatus = injectSyncStatus()
@@ -102,7 +100,7 @@ const reset = () => {
problem.value!.template[codeStore.code.language] ||
SOURCES[codeStore.code.language],
)
storage.remove(props.storageKey)
storage.remove(storageKey)
message.success("代码重置成功")
}
@@ -228,7 +226,7 @@ onMounted(() => {
/>
<!-- 同步状态标签 -->
<template v-if="props.isConnected">
<template v-if="isConnected">
<n-tag v-if="syncStatus.otherUser.value" type="info">
{{ SYNC_MESSAGES.SYNCING_WITH(syncStatus.otherUser.value.name) }}
</n-tag>

View File

@@ -67,7 +67,7 @@
{{ content }}
</n-form-item>
<n-button
v-if="hasCommented && props.showStatistics"
v-if="hasCommented && showStatistics"
type="primary"
@click="getComments"
>
@@ -77,7 +77,7 @@
提交
</n-button>
</n-form>
<div v-if="props.showStatistics">
<div v-if="showStatistics">
<n-descriptions
class="list"
v-if="count"
@@ -117,9 +117,7 @@ interface Props {
showStatistics?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showStatistics: true,
})
const { showStatistics = true } = defineProps<Props>()
const userStore = useUserStore()
const problemStore = useProblemStore()

View File

@@ -40,10 +40,7 @@ interface Props {
problemSetId?: string
}
const props = withDefaults(defineProps<Props>(), {
contestID: "",
problemSetId: "",
})
const { problemID, contestID = "", problemSetId = "" } = defineProps<Props>()
const errMsg = ref("无数据")
const route = useRoute()
@@ -67,7 +64,7 @@ const tabOptions = computed(() => {
options.push("editor")
}
options.push("info")
if (!props.contestID) {
if (!contestID) {
options.push("comment")
}
if (myFlowchartStore.showing) {
@@ -110,7 +107,7 @@ watch(
async function init() {
screenModeStore.resetScreenMode()
try {
const res = await getProblem(props.problemID, props.contestID)
const res = await getProblem(problemID, contestID)
problem.value = res.data
} catch (err: any) {
problem.value = null
@@ -120,7 +117,7 @@ async function init() {
}
}
onMounted(init)
watch(() => props.problemID, init)
watch(() => problemID, init)
onBeforeUnmount(() => {
problem.value = null
errMsg.value = "无数据"
@@ -159,15 +156,15 @@ watch(isMobile, (value) => {
<n-tab-pane
name="info"
tab="题目统计"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemInfo />
</n-tab-pane>
<n-tab-pane
v-if="!props.contestID"
v-if="!contestID"
name="comment"
tab="题目点评"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemComment />
</n-tab-pane>
@@ -181,7 +178,7 @@ watch(isMobile, (value) => {
<n-tab-pane
name="submission"
tab="我的提交"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemSubmission />
</n-tab-pane>
@@ -215,15 +212,15 @@ watch(isMobile, (value) => {
<n-tab-pane
name="info"
tab="题目统计"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemInfo />
</n-tab-pane>
<n-tab-pane
v-if="!props.contestID"
v-if="!contestID"
name="comment"
tab="题目点评"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemComment />
</n-tab-pane>
@@ -237,7 +234,7 @@ watch(isMobile, (value) => {
<n-tab-pane
name="submission"
tab="我的提交"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemSubmission />
</n-tab-pane>
@@ -256,14 +253,14 @@ watch(isMobile, (value) => {
<n-tab-pane name="editor" tab="代码">
<component :is="inProblem ? ProblemEditor : ContestEditor" />
</n-tab-pane>
<n-tab-pane name="info" tab="统计" :disabled="!!props.problemSetId">
<n-tab-pane name="info" tab="统计" :disabled="!!problemSetId">
<ProblemInfo />
</n-tab-pane>
<n-tab-pane
v-if="!props.contestID"
v-if="!contestID"
name="comment"
tab="点评"
:disabled="!!props.problemSetId"
:disabled="!!problemSetId"
>
<ProblemComment />
</n-tab-pane>
@@ -274,7 +271,7 @@ watch(isMobile, (value) => {
>
<MyFlowchartTab />
</n-tab-pane>
<n-tab-pane name="submission" tab="提交" :disabled="!!props.problemSetId">
<n-tab-pane name="submission" tab="提交" :disabled="!!problemSetId">
<ProblemSubmission />
</n-tab-pane>
</n-tabs>

View File

@@ -28,7 +28,7 @@ const isDefaultAvatar = computed(
() => profile.value?.avatar.endsWith("default.png") ?? true,
)
const problemsFlexRef = ref<HTMLElement | null>(null)
const problemsFlexRef = useTemplateRef<HTMLElement>("problemsFlexRef")
const itemsPerRow = ref(8)
function updateItemsPerRow() {

View File

@@ -22,21 +22,19 @@ interface Props {
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "Python3",
fontSize: 20,
height: "100%",
readonly: false,
placeholder: "",
})
const { readonly, placeholder, height, fontSize } = toRefs(props)
const {
language = "Python3",
fontSize = 20,
height = "100%",
readonly = false,
placeholder = "",
} = defineProps<Props>()
const code = defineModel<string>("value")
const isDark = useDark()
const langExtension = computed(() => {
return ["Python2", "Python3"].includes(props.language) ? python() : cpp()
return ["Python2", "Python3"].includes(language) ? python() : cpp()
})
const extensions = computed(() => [
@@ -45,7 +43,7 @@ const extensions = computed(() => [
bracketMatching(),
closeBrackets(),
autocompletion({
override: [enhanceCompletion(props.language), completeAnyWord],
override: [enhanceCompletion(language), completeAnyWord],
}),
isDark.value ? oneDark : smoothy,
])

View File

@@ -78,7 +78,7 @@ const emit = defineEmits<Emits>()
const isHovered = ref(false)
const isEditing = ref(false)
const editText = ref("")
const editInput = ref<HTMLInputElement>()
const editInput = useTemplateRef<HTMLInputElement>("editInput")
// 定时器和事件处理器
let hideTimeout: ReturnType<typeof setTimeout> | null = null

View File

@@ -26,9 +26,7 @@ interface Props {
height?: string
}
withDefaults(defineProps<Props>(), {
height: "calc(100vh - 133px)",
})
const { height = "calc(100vh - 133px)" } = defineProps<Props>()
// Vue Flow 实例
const { addEdges, removeNodes, removeEdges } = useVueFlow()

View File

@@ -17,7 +17,7 @@ const {
loginLoading: isLoading,
loginError: msg,
} = storeToRefs(authStore)
const loginRef = ref()
const loginRef = useTemplateRef("loginRef")
const classUserOptions = ref<SelectOption[]>([])
const classUserLoading = ref(false)
const isClassLogin = computed(() => Boolean(form.value.class))

View File

@@ -7,17 +7,14 @@ interface Props {
page: number
}
const props = withDefaults(defineProps<Props>(), {
limit: 10,
page: 1,
})
const { total, limit: initialLimit = 10, page: initialPage = 1 } = defineProps<Props>()
const emit = defineEmits(["update:limit", "update:page"])
const { isDesktop } = useBreakpoints()
const limit = ref(props.limit)
const page = ref(props.page)
const limit = ref(initialLimit)
const page = ref(initialPage)
const sizes = [10, 30, 50]
watch(limit, () => emit("update:limit", limit))
@@ -26,9 +23,9 @@ watch(page, () => emit("update:page", page))
<template>
<n-pagination
v-if="props.total"
v-if="total"
class="right margin"
:item-count="props.total"
:item-count="total"
v-model:page="page"
v-model:page-size="limit"
:page-sizes="sizes"

View File

@@ -12,7 +12,7 @@ const {
signupError: msg,
captchaSrc,
} = storeToRefs(authStore)
const signupRef = ref()
const signupRef = useTemplateRef("signupRef")
const rules: FormRules = {
username: [{ required: true, message: "用户名必填", trigger: "blur" }],

View File

@@ -36,15 +36,15 @@ interface Props {
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "Python3",
fontSize: 20,
height: "100%",
readonly: false,
placeholder: "",
})
const { readonly, placeholder, height, fontSize } = toRefs(props)
const {
sync,
problem,
language = "Python3",
fontSize = 20,
height = "100%",
readonly = false,
placeholder = "",
} = defineProps<Props>()
const code = defineModel<string>("value")
const emit = defineEmits<{
@@ -57,7 +57,7 @@ const emit = defineEmits<{
const { isDesktop } = useBreakpoints()
const langExtension = computed((): Extension => {
return ["Python2", "Python3"].includes(props.language) ? python() : cpp()
return ["Python2", "Python3"].includes(language) ? python() : cpp()
})
const extensions = computed(() => [
@@ -67,7 +67,7 @@ const extensions = computed(() => [
closeBrackets(),
isDark.value ? oneDark : smoothy,
autocompletion({
override: [enhanceCompletion(props.language), completeAnyWord],
override: [enhanceCompletion(language), completeAnyWord],
}),
getInitialExtension(),
])
@@ -85,12 +85,12 @@ const cleanupSyncResources = () => {
}
const initSync = async () => {
if (!editorView.value || !props.problem || !isDesktop.value) return
if (!editorView.value || !problem || !isDesktop.value) return
cleanupSyncResources()
cleanupSync = await startSync({
problemId: props.problem,
problemId: problem,
editorView: editorView.value as EditorView,
onStatusChange: (status) => {
// 处理需要断开同步的情况
@@ -108,13 +108,13 @@ const initSync = async () => {
const handleEditorReady = (payload: EditorReadyPayload) => {
editorView.value = payload.view as EditorView
if (props.sync) {
if (sync) {
initSync()
}
}
watch(
() => props.sync,
() => sync,
(shouldSync) => {
if (shouldSync) {
initSync()
@@ -125,9 +125,9 @@ watch(
)
watch(
() => props.problem,
() => problem,
(newProblem, oldProblem) => {
if (newProblem !== oldProblem && props.sync) {
if (newProblem !== oldProblem && sync) {
initSync()
}
},

View File

@@ -17,10 +17,7 @@ interface Props {
const rawHtml = defineModel<string>("value")
type InsertFnType = (url: string, alt: string, href: string) => void
const props = withDefaults(defineProps<Props>(), {
minHeight: 0,
simple: false,
})
const { title, minHeight = 0, simple = false } = defineProps<Props>()
const message = useMessage()
@@ -112,17 +109,17 @@ async function customUpload(file: File, insertFn: InsertFnType) {
</script>
<template>
<div class="title" v-if="props.title">{{ props.title }}</div>
<div class="title" v-if="title">{{ title }}</div>
<div class="editorWrapper">
<Toolbar
class="toolbar"
:editor="toolbarEditorRef"
:defaultConfig="props.simple ? toolbarConfigSimple : toolbarConfig"
:defaultConfig="simple ? toolbarConfigSimple : toolbarConfig"
mode="simple"
/>
<Editor
@click="onClick"
:style="{ minHeight: props.minHeight + 'px' }"
:style="{ minHeight: minHeight + 'px' }"
v-model="rawHtml"
:defaultConfig="editorConfig"
mode="simple"