use default props
This commit is contained in:
@@ -60,7 +60,7 @@ import { useAIStore } from "oj/store/ai"
|
|||||||
import { parseTime } from "utils/functions"
|
import { parseTime } from "utils/functions"
|
||||||
|
|
||||||
const aiStore = useAIStore()
|
const aiStore = useAIStore()
|
||||||
const containerRef = ref<HTMLElement>()
|
const containerRef = useTemplateRef<HTMLElement>("containerRef")
|
||||||
|
|
||||||
const CELL_SIZE = 12
|
const CELL_SIZE = 12
|
||||||
const CELL_GAP = 3
|
const CELL_GAP = 3
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ interface Props {
|
|||||||
isConnected?: boolean // WebSocket 实际的连接状态(已建立/未建立)
|
isConnected?: boolean // WebSocket 实际的连接状态(已建立/未建立)
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { storageKey, isConnected = false } = defineProps<Props>()
|
||||||
isConnected: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 注入同步状态
|
// 注入同步状态
|
||||||
const syncStatus = injectSyncStatus()
|
const syncStatus = injectSyncStatus()
|
||||||
@@ -102,7 +100,7 @@ const reset = () => {
|
|||||||
problem.value!.template[codeStore.code.language] ||
|
problem.value!.template[codeStore.code.language] ||
|
||||||
SOURCES[codeStore.code.language],
|
SOURCES[codeStore.code.language],
|
||||||
)
|
)
|
||||||
storage.remove(props.storageKey)
|
storage.remove(storageKey)
|
||||||
message.success("代码重置成功")
|
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">
|
<n-tag v-if="syncStatus.otherUser.value" type="info">
|
||||||
{{ SYNC_MESSAGES.SYNCING_WITH(syncStatus.otherUser.value.name) }}
|
{{ SYNC_MESSAGES.SYNCING_WITH(syncStatus.otherUser.value.name) }}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
{{ content }}
|
{{ content }}
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-button
|
<n-button
|
||||||
v-if="hasCommented && props.showStatistics"
|
v-if="hasCommented && showStatistics"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="getComments"
|
@click="getComments"
|
||||||
>
|
>
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
提交
|
提交
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-form>
|
</n-form>
|
||||||
<div v-if="props.showStatistics">
|
<div v-if="showStatistics">
|
||||||
<n-descriptions
|
<n-descriptions
|
||||||
class="list"
|
class="list"
|
||||||
v-if="count"
|
v-if="count"
|
||||||
@@ -117,9 +117,7 @@ interface Props {
|
|||||||
showStatistics?: boolean
|
showStatistics?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { showStatistics = true } = defineProps<Props>()
|
||||||
showStatistics: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const problemStore = useProblemStore()
|
const problemStore = useProblemStore()
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ interface Props {
|
|||||||
problemSetId?: string
|
problemSetId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { problemID, contestID = "", problemSetId = "" } = defineProps<Props>()
|
||||||
contestID: "",
|
|
||||||
problemSetId: "",
|
|
||||||
})
|
|
||||||
|
|
||||||
const errMsg = ref("无数据")
|
const errMsg = ref("无数据")
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -67,7 +64,7 @@ const tabOptions = computed(() => {
|
|||||||
options.push("editor")
|
options.push("editor")
|
||||||
}
|
}
|
||||||
options.push("info")
|
options.push("info")
|
||||||
if (!props.contestID) {
|
if (!contestID) {
|
||||||
options.push("comment")
|
options.push("comment")
|
||||||
}
|
}
|
||||||
if (myFlowchartStore.showing) {
|
if (myFlowchartStore.showing) {
|
||||||
@@ -110,7 +107,7 @@ watch(
|
|||||||
async function init() {
|
async function init() {
|
||||||
screenModeStore.resetScreenMode()
|
screenModeStore.resetScreenMode()
|
||||||
try {
|
try {
|
||||||
const res = await getProblem(props.problemID, props.contestID)
|
const res = await getProblem(problemID, contestID)
|
||||||
problem.value = res.data
|
problem.value = res.data
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
problem.value = null
|
problem.value = null
|
||||||
@@ -120,7 +117,7 @@ async function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMounted(init)
|
onMounted(init)
|
||||||
watch(() => props.problemID, init)
|
watch(() => problemID, init)
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
problem.value = null
|
problem.value = null
|
||||||
errMsg.value = "无数据"
|
errMsg.value = "无数据"
|
||||||
@@ -159,15 +156,15 @@ watch(isMobile, (value) => {
|
|||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
name="info"
|
name="info"
|
||||||
tab="题目统计"
|
tab="题目统计"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemInfo />
|
<ProblemInfo />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
v-if="!props.contestID"
|
v-if="!contestID"
|
||||||
name="comment"
|
name="comment"
|
||||||
tab="题目点评"
|
tab="题目点评"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemComment />
|
<ProblemComment />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
@@ -181,7 +178,7 @@ watch(isMobile, (value) => {
|
|||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
name="submission"
|
name="submission"
|
||||||
tab="我的提交"
|
tab="我的提交"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemSubmission />
|
<ProblemSubmission />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
@@ -215,15 +212,15 @@ watch(isMobile, (value) => {
|
|||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
name="info"
|
name="info"
|
||||||
tab="题目统计"
|
tab="题目统计"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemInfo />
|
<ProblemInfo />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
v-if="!props.contestID"
|
v-if="!contestID"
|
||||||
name="comment"
|
name="comment"
|
||||||
tab="题目点评"
|
tab="题目点评"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemComment />
|
<ProblemComment />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
@@ -237,7 +234,7 @@ watch(isMobile, (value) => {
|
|||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
name="submission"
|
name="submission"
|
||||||
tab="我的提交"
|
tab="我的提交"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemSubmission />
|
<ProblemSubmission />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
@@ -256,14 +253,14 @@ watch(isMobile, (value) => {
|
|||||||
<n-tab-pane name="editor" tab="代码">
|
<n-tab-pane name="editor" tab="代码">
|
||||||
<component :is="inProblem ? ProblemEditor : ContestEditor" />
|
<component :is="inProblem ? ProblemEditor : ContestEditor" />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="info" tab="统计" :disabled="!!props.problemSetId">
|
<n-tab-pane name="info" tab="统计" :disabled="!!problemSetId">
|
||||||
<ProblemInfo />
|
<ProblemInfo />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane
|
<n-tab-pane
|
||||||
v-if="!props.contestID"
|
v-if="!contestID"
|
||||||
name="comment"
|
name="comment"
|
||||||
tab="点评"
|
tab="点评"
|
||||||
:disabled="!!props.problemSetId"
|
:disabled="!!problemSetId"
|
||||||
>
|
>
|
||||||
<ProblemComment />
|
<ProblemComment />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
@@ -274,7 +271,7 @@ watch(isMobile, (value) => {
|
|||||||
>
|
>
|
||||||
<MyFlowchartTab />
|
<MyFlowchartTab />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="submission" tab="提交" :disabled="!!props.problemSetId">
|
<n-tab-pane name="submission" tab="提交" :disabled="!!problemSetId">
|
||||||
<ProblemSubmission />
|
<ProblemSubmission />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const isDefaultAvatar = computed(
|
|||||||
() => profile.value?.avatar.endsWith("default.png") ?? true,
|
() => profile.value?.avatar.endsWith("default.png") ?? true,
|
||||||
)
|
)
|
||||||
|
|
||||||
const problemsFlexRef = ref<HTMLElement | null>(null)
|
const problemsFlexRef = useTemplateRef<HTMLElement>("problemsFlexRef")
|
||||||
const itemsPerRow = ref(8)
|
const itemsPerRow = ref(8)
|
||||||
|
|
||||||
function updateItemsPerRow() {
|
function updateItemsPerRow() {
|
||||||
|
|||||||
@@ -22,21 +22,19 @@ interface Props {
|
|||||||
placeholder?: string
|
placeholder?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const {
|
||||||
language: "Python3",
|
language = "Python3",
|
||||||
fontSize: 20,
|
fontSize = 20,
|
||||||
height: "100%",
|
height = "100%",
|
||||||
readonly: false,
|
readonly = false,
|
||||||
placeholder: "",
|
placeholder = "",
|
||||||
})
|
} = defineProps<Props>()
|
||||||
|
|
||||||
const { readonly, placeholder, height, fontSize } = toRefs(props)
|
|
||||||
const code = defineModel<string>("value")
|
const code = defineModel<string>("value")
|
||||||
|
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
|
|
||||||
const langExtension = computed(() => {
|
const langExtension = computed(() => {
|
||||||
return ["Python2", "Python3"].includes(props.language) ? python() : cpp()
|
return ["Python2", "Python3"].includes(language) ? python() : cpp()
|
||||||
})
|
})
|
||||||
|
|
||||||
const extensions = computed(() => [
|
const extensions = computed(() => [
|
||||||
@@ -45,7 +43,7 @@ const extensions = computed(() => [
|
|||||||
bracketMatching(),
|
bracketMatching(),
|
||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
autocompletion({
|
autocompletion({
|
||||||
override: [enhanceCompletion(props.language), completeAnyWord],
|
override: [enhanceCompletion(language), completeAnyWord],
|
||||||
}),
|
}),
|
||||||
isDark.value ? oneDark : smoothy,
|
isDark.value ? oneDark : smoothy,
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ const emit = defineEmits<Emits>()
|
|||||||
const isHovered = ref(false)
|
const isHovered = ref(false)
|
||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
const editText = ref("")
|
const editText = ref("")
|
||||||
const editInput = ref<HTMLInputElement>()
|
const editInput = useTemplateRef<HTMLInputElement>("editInput")
|
||||||
|
|
||||||
// 定时器和事件处理器
|
// 定时器和事件处理器
|
||||||
let hideTimeout: ReturnType<typeof setTimeout> | null = null
|
let hideTimeout: ReturnType<typeof setTimeout> | null = null
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ interface Props {
|
|||||||
height?: string
|
height?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
const { height = "calc(100vh - 133px)" } = defineProps<Props>()
|
||||||
height: "calc(100vh - 133px)",
|
|
||||||
})
|
|
||||||
|
|
||||||
// Vue Flow 实例
|
// Vue Flow 实例
|
||||||
const { addEdges, removeNodes, removeEdges } = useVueFlow()
|
const { addEdges, removeNodes, removeEdges } = useVueFlow()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const {
|
|||||||
loginLoading: isLoading,
|
loginLoading: isLoading,
|
||||||
loginError: msg,
|
loginError: msg,
|
||||||
} = storeToRefs(authStore)
|
} = storeToRefs(authStore)
|
||||||
const loginRef = ref()
|
const loginRef = useTemplateRef("loginRef")
|
||||||
const classUserOptions = ref<SelectOption[]>([])
|
const classUserOptions = ref<SelectOption[]>([])
|
||||||
const classUserLoading = ref(false)
|
const classUserLoading = ref(false)
|
||||||
const isClassLogin = computed(() => Boolean(form.value.class))
|
const isClassLogin = computed(() => Boolean(form.value.class))
|
||||||
|
|||||||
@@ -7,17 +7,14 @@ interface Props {
|
|||||||
page: number
|
page: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { total, limit: initialLimit = 10, page: initialPage = 1 } = defineProps<Props>()
|
||||||
limit: 10,
|
|
||||||
page: 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:limit", "update:page"])
|
const emit = defineEmits(["update:limit", "update:page"])
|
||||||
|
|
||||||
const { isDesktop } = useBreakpoints()
|
const { isDesktop } = useBreakpoints()
|
||||||
|
|
||||||
const limit = ref(props.limit)
|
const limit = ref(initialLimit)
|
||||||
const page = ref(props.page)
|
const page = ref(initialPage)
|
||||||
const sizes = [10, 30, 50]
|
const sizes = [10, 30, 50]
|
||||||
|
|
||||||
watch(limit, () => emit("update:limit", limit))
|
watch(limit, () => emit("update:limit", limit))
|
||||||
@@ -26,9 +23,9 @@ watch(page, () => emit("update:page", page))
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-pagination
|
<n-pagination
|
||||||
v-if="props.total"
|
v-if="total"
|
||||||
class="right margin"
|
class="right margin"
|
||||||
:item-count="props.total"
|
:item-count="total"
|
||||||
v-model:page="page"
|
v-model:page="page"
|
||||||
v-model:page-size="limit"
|
v-model:page-size="limit"
|
||||||
:page-sizes="sizes"
|
:page-sizes="sizes"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const {
|
|||||||
signupError: msg,
|
signupError: msg,
|
||||||
captchaSrc,
|
captchaSrc,
|
||||||
} = storeToRefs(authStore)
|
} = storeToRefs(authStore)
|
||||||
const signupRef = ref()
|
const signupRef = useTemplateRef("signupRef")
|
||||||
|
|
||||||
const rules: FormRules = {
|
const rules: FormRules = {
|
||||||
username: [{ required: true, message: "用户名必填", trigger: "blur" }],
|
username: [{ required: true, message: "用户名必填", trigger: "blur" }],
|
||||||
|
|||||||
@@ -36,15 +36,15 @@ interface Props {
|
|||||||
placeholder?: string
|
placeholder?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const {
|
||||||
language: "Python3",
|
sync,
|
||||||
fontSize: 20,
|
problem,
|
||||||
height: "100%",
|
language = "Python3",
|
||||||
readonly: false,
|
fontSize = 20,
|
||||||
placeholder: "",
|
height = "100%",
|
||||||
})
|
readonly = false,
|
||||||
|
placeholder = "",
|
||||||
const { readonly, placeholder, height, fontSize } = toRefs(props)
|
} = defineProps<Props>()
|
||||||
const code = defineModel<string>("value")
|
const code = defineModel<string>("value")
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -57,7 +57,7 @@ const emit = defineEmits<{
|
|||||||
const { isDesktop } = useBreakpoints()
|
const { isDesktop } = useBreakpoints()
|
||||||
|
|
||||||
const langExtension = computed((): Extension => {
|
const langExtension = computed((): Extension => {
|
||||||
return ["Python2", "Python3"].includes(props.language) ? python() : cpp()
|
return ["Python2", "Python3"].includes(language) ? python() : cpp()
|
||||||
})
|
})
|
||||||
|
|
||||||
const extensions = computed(() => [
|
const extensions = computed(() => [
|
||||||
@@ -67,7 +67,7 @@ const extensions = computed(() => [
|
|||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
isDark.value ? oneDark : smoothy,
|
isDark.value ? oneDark : smoothy,
|
||||||
autocompletion({
|
autocompletion({
|
||||||
override: [enhanceCompletion(props.language), completeAnyWord],
|
override: [enhanceCompletion(language), completeAnyWord],
|
||||||
}),
|
}),
|
||||||
getInitialExtension(),
|
getInitialExtension(),
|
||||||
])
|
])
|
||||||
@@ -85,12 +85,12 @@ const cleanupSyncResources = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initSync = async () => {
|
const initSync = async () => {
|
||||||
if (!editorView.value || !props.problem || !isDesktop.value) return
|
if (!editorView.value || !problem || !isDesktop.value) return
|
||||||
|
|
||||||
cleanupSyncResources()
|
cleanupSyncResources()
|
||||||
|
|
||||||
cleanupSync = await startSync({
|
cleanupSync = await startSync({
|
||||||
problemId: props.problem,
|
problemId: problem,
|
||||||
editorView: editorView.value as EditorView,
|
editorView: editorView.value as EditorView,
|
||||||
onStatusChange: (status) => {
|
onStatusChange: (status) => {
|
||||||
// 处理需要断开同步的情况
|
// 处理需要断开同步的情况
|
||||||
@@ -108,13 +108,13 @@ const initSync = async () => {
|
|||||||
|
|
||||||
const handleEditorReady = (payload: EditorReadyPayload) => {
|
const handleEditorReady = (payload: EditorReadyPayload) => {
|
||||||
editorView.value = payload.view as EditorView
|
editorView.value = payload.view as EditorView
|
||||||
if (props.sync) {
|
if (sync) {
|
||||||
initSync()
|
initSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.sync,
|
() => sync,
|
||||||
(shouldSync) => {
|
(shouldSync) => {
|
||||||
if (shouldSync) {
|
if (shouldSync) {
|
||||||
initSync()
|
initSync()
|
||||||
@@ -125,9 +125,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.problem,
|
() => problem,
|
||||||
(newProblem, oldProblem) => {
|
(newProblem, oldProblem) => {
|
||||||
if (newProblem !== oldProblem && props.sync) {
|
if (newProblem !== oldProblem && sync) {
|
||||||
initSync()
|
initSync()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,10 +17,7 @@ interface Props {
|
|||||||
const rawHtml = defineModel<string>("value")
|
const rawHtml = defineModel<string>("value")
|
||||||
type InsertFnType = (url: string, alt: string, href: string) => void
|
type InsertFnType = (url: string, alt: string, href: string) => void
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const { title, minHeight = 0, simple = false } = defineProps<Props>()
|
||||||
minHeight: 0,
|
|
||||||
simple: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
@@ -112,17 +109,17 @@ async function customUpload(file: File, insertFn: InsertFnType) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="title" v-if="props.title">{{ props.title }}</div>
|
<div class="title" v-if="title">{{ title }}</div>
|
||||||
<div class="editorWrapper">
|
<div class="editorWrapper">
|
||||||
<Toolbar
|
<Toolbar
|
||||||
class="toolbar"
|
class="toolbar"
|
||||||
:editor="toolbarEditorRef"
|
:editor="toolbarEditorRef"
|
||||||
:defaultConfig="props.simple ? toolbarConfigSimple : toolbarConfig"
|
:defaultConfig="simple ? toolbarConfigSimple : toolbarConfig"
|
||||||
mode="simple"
|
mode="simple"
|
||||||
/>
|
/>
|
||||||
<Editor
|
<Editor
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
:style="{ minHeight: props.minHeight + 'px' }"
|
:style="{ minHeight: minHeight + 'px' }"
|
||||||
v-model="rawHtml"
|
v-model="rawHtml"
|
||||||
:defaultConfig="editorConfig"
|
:defaultConfig="editorConfig"
|
||||||
mode="simple"
|
mode="simple"
|
||||||
|
|||||||
Reference in New Issue
Block a user