Compare commits
2
Commits
ad28c0ba21
...
1cac0d01f8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cac0d01f8 | ||
|
|
47281029ec |
+12
-3
@@ -871,7 +871,10 @@ const radarChartOptions = {
|
||||
class="stat-avg-ac"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:analytics-pie-2" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:analytics-pie-2"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
@@ -883,7 +886,10 @@ const radarChartOptions = {
|
||||
class="stat-median-ac"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:cursor-target-1" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:cursor-target-1"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
@@ -895,7 +901,10 @@ const radarChartOptions = {
|
||||
class="stat-total-submission"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:common-file-text" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:common-file-text"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { Exercise } from "utils/types"
|
||||
|
||||
type Segment =
|
||||
| { type: "md"; content: string }
|
||||
| { type: "exercise"; exercise: Exercise }
|
||||
{ type: "md"; content: string } | { type: "exercise"; exercise: Exercise }
|
||||
|
||||
export function parseExercises(
|
||||
content: string,
|
||||
|
||||
@@ -195,13 +195,6 @@ onMounted(() => {
|
||||
/>
|
||||
</template>
|
||||
|
||||
<IconButton
|
||||
v-if="isDesktop && userStore.isSuperAdmin"
|
||||
icon="streamline-ultimate-color:common-file-edit"
|
||||
tip="编辑题目"
|
||||
@click="goEdit"
|
||||
/>
|
||||
|
||||
<template v-if="showSyncFeature">
|
||||
<IconButton
|
||||
:icon="
|
||||
@@ -231,6 +224,13 @@ onMounted(() => {
|
||||
</n-tag>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<IconButton
|
||||
v-if="isDesktop && userStore.isSuperAdmin"
|
||||
icon="streamline-ultimate-color:common-file-edit"
|
||||
tip="编辑题目"
|
||||
@click="goEdit"
|
||||
/>
|
||||
</n-flex>
|
||||
|
||||
<n-modal
|
||||
|
||||
@@ -77,10 +77,7 @@ const columns: DataTableColumn<Submission>[] = [
|
||||
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||
},
|
||||
{
|
||||
title: renderTableTitle(
|
||||
"语言",
|
||||
"streamline-ultimate-color:earth-pin-2",
|
||||
),
|
||||
title: renderTableTitle("语言", "streamline-ultimate-color:earth-pin-2"),
|
||||
key: "language",
|
||||
width: 100,
|
||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||
|
||||
@@ -160,12 +160,18 @@ const baseColumns: DataTableColumn<ProblemFiltered>[] = [
|
||||
render: (row) => h(ProblemStatus, { status: row.status }),
|
||||
},
|
||||
{
|
||||
title: renderTableTitle("编号", "streamline-ultimate-color:board-game-dice-1"),
|
||||
title: renderTableTitle(
|
||||
"编号",
|
||||
"streamline-ultimate-color:board-game-dice-1",
|
||||
),
|
||||
key: "_id",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: renderTableTitle("题目", "streamline-ultimate-color:fruit-watermelon"),
|
||||
title: renderTableTitle(
|
||||
"题目",
|
||||
"streamline-ultimate-color:fruit-watermelon",
|
||||
),
|
||||
key: "title",
|
||||
minWidth: 200,
|
||||
render: (row) => h(ProblemListTitle, { problem: row }),
|
||||
|
||||
+31
-7
@@ -110,7 +110,11 @@ async function analyzeSingleClassWithAI() {
|
||||
if (event === "end" && !hasStarted) classDetailAiLoading.value = false
|
||||
},
|
||||
onMessage(payload) {
|
||||
const parsed = payload as { type?: string; content?: string; message?: string }
|
||||
const parsed = payload as {
|
||||
type?: string
|
||||
content?: string
|
||||
message?: string
|
||||
}
|
||||
if (parsed.type === "delta" && parsed.content) {
|
||||
if (!hasStarted) {
|
||||
hasStarted = true
|
||||
@@ -221,7 +225,10 @@ const columns: DataTableColumn<Rank>[] = [
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: renderTableTitle("提交数", "streamline-ultimate-color:space-rocket-earth"),
|
||||
title: renderTableTitle(
|
||||
"提交数",
|
||||
"streamline-ultimate-color:space-rocket-earth",
|
||||
),
|
||||
key: "submission_number",
|
||||
width: 120,
|
||||
align: "center",
|
||||
@@ -606,7 +613,10 @@ watch(
|
||||
class="stat-avg-ac"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:analytics-pie-2" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:analytics-pie-2"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
@@ -618,7 +628,10 @@ watch(
|
||||
class="stat-median-ac"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:cursor-target-1" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:cursor-target-1"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
@@ -630,7 +643,10 @@ watch(
|
||||
class="stat-total-submission"
|
||||
>
|
||||
<template #suffix>
|
||||
<Icon icon="streamline-ultimate-color:common-file-text" width="20" />
|
||||
<Icon
|
||||
icon="streamline-ultimate-color:common-file-text"
|
||||
width="20"
|
||||
/>
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
@@ -736,7 +752,12 @@ watch(
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-flex justify="center" align="center" :size="12" style="margin-top: 12px">
|
||||
<n-flex
|
||||
justify="center"
|
||||
align="center"
|
||||
:size="12"
|
||||
style="margin-top: 12px"
|
||||
>
|
||||
<n-tag type="success" size="large">
|
||||
综合分: {{ classDetailData.composite_score.toFixed(1) }}
|
||||
</n-tag>
|
||||
@@ -769,7 +790,10 @@ watch(
|
||||
>
|
||||
<n-spin :show="classDetailAiLoading" :delay="50">
|
||||
<div style="min-height: 200px">
|
||||
<MdPreview v-if="classDetailAiContent" :model-value="classDetailAiContent" />
|
||||
<MdPreview
|
||||
v-if="classDetailAiContent"
|
||||
:model-value="classDetailAiContent"
|
||||
/>
|
||||
<n-flex
|
||||
v-else-if="!classDetailAiLoading"
|
||||
align="center"
|
||||
|
||||
@@ -267,10 +267,7 @@ const columns = computed(() => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: renderTableTitle(
|
||||
"语言",
|
||||
"streamline-ultimate-color:earth-pin-2",
|
||||
),
|
||||
title: renderTableTitle("语言", "streamline-ultimate-color:earth-pin-2"),
|
||||
key: "language",
|
||||
minWidth: 120,
|
||||
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||
@@ -347,7 +344,10 @@ const flowchartColumns = computed(() => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: renderTableTitle("评分", "streamline-ultimate-color:analytics-bars-3d"),
|
||||
title: renderTableTitle(
|
||||
"评分",
|
||||
"streamline-ultimate-color:analytics-bars-3d",
|
||||
),
|
||||
key: "ai_score",
|
||||
render: (row) => h(Grade, { score: row.ai_score, grade: row.ai_grade }),
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { cpp } from "@codemirror/lang-cpp"
|
||||
import { python } from "@codemirror/lang-python"
|
||||
import { sql, SQLite } from "@codemirror/lang-sql"
|
||||
import { bracketMatching } from "@codemirror/language"
|
||||
import { Codemirror } from "vue-codemirror"
|
||||
import {
|
||||
@@ -34,6 +35,8 @@ const code = defineModel<string>("value")
|
||||
const isDark = useDark()
|
||||
|
||||
const langExtension = computed(() => {
|
||||
if (language === "SQL")
|
||||
return sql({ dialect: SQLite, upperCaseKeywords: true })
|
||||
return ["Python2", "Python3"].includes(language) ? python() : cpp()
|
||||
})
|
||||
|
||||
|
||||
@@ -7,7 +7,11 @@ interface Props {
|
||||
page: number
|
||||
}
|
||||
|
||||
const { total, limit: initialLimit = 10, page: initialPage = 1 } = defineProps<Props>()
|
||||
const {
|
||||
total,
|
||||
limit: initialLimit = 10,
|
||||
page: initialPage = 1,
|
||||
} = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits(["update:limit", "update:page"])
|
||||
|
||||
|
||||
@@ -23,27 +23,26 @@ export const SYNC_ERROR_CODES = {
|
||||
// 界面和通知文案
|
||||
export const SYNC_MESSAGES = {
|
||||
// 超管离开
|
||||
SUPER_ADMIN_LEFT: (name: string) => `👋 超管 ${name} 已离开`,
|
||||
SUPER_ADMIN_LEFT: (name: string) => `超管 ${name} 已离开`,
|
||||
|
||||
// 缺少超管
|
||||
MISSING_SUPER_ADMIN: "⚠️ 协同编辑需要超管",
|
||||
MISSING_SUPER_ADMIN: "协同编辑需要超管",
|
||||
|
||||
// 连接成功
|
||||
SYNC_ACTIVE: "✅ 协同编辑已激活!",
|
||||
SYNC_ACTIVE: "协同编辑已激活!",
|
||||
|
||||
// 连接断开
|
||||
CONNECTION_LOST: "⚠️ 协同编辑已断开",
|
||||
CONNECTION_LOST: "协同编辑已断开",
|
||||
|
||||
// 等待相关
|
||||
WAITING_STUDENT: "⏳ 正在等待学生加入...",
|
||||
WAITING_ADMIN: "⏳ 正在等待超管加入...",
|
||||
WAITING_STUDENT: "正在等待学生加入...",
|
||||
WAITING_ADMIN: "正在等待超管加入...",
|
||||
|
||||
// Form.vue 界面文案
|
||||
SYNC_ON: "断开同步",
|
||||
SYNC_OFF: "开启同步",
|
||||
SYNCING_WITH: (name: string) => `🔗 与 ${name} 同步中`,
|
||||
STUDENT_LEFT: (name?: string) =>
|
||||
name ? `💡 ${name}已离开` : "💡 可以关闭同步",
|
||||
SYNCING_WITH: (name: string) => `与 ${name} 同步中`,
|
||||
STUDENT_LEFT: (name?: string) => (name ? `${name}已离开` : "可以关闭同步"),
|
||||
} as const
|
||||
|
||||
// 类型定义
|
||||
|
||||
@@ -4,10 +4,7 @@ import { ref, onUnmounted, type Ref } from "vue"
|
||||
* WebSocket 连接状态
|
||||
*/
|
||||
export type ConnectionStatus =
|
||||
| "disconnected"
|
||||
| "connecting"
|
||||
| "connected"
|
||||
| "error"
|
||||
"disconnected" | "connecting" | "connected" | "error"
|
||||
|
||||
/**
|
||||
* WebSocket 消息类型
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { EditorView } from "@codemirror/view"
|
||||
import type { LANGUAGE } from "utils/types"
|
||||
import { c } from "./c"
|
||||
import { python } from "./python"
|
||||
import { sql } from "./sql"
|
||||
|
||||
type ChineseCompletion = Pick<
|
||||
Completion,
|
||||
@@ -18,6 +19,7 @@ type ChineseCompletion = Pick<
|
||||
const chineseAnnotations: Record<string, ChineseCompletion[]> = {
|
||||
python,
|
||||
c,
|
||||
sql,
|
||||
}
|
||||
|
||||
export function enhanceCompletion(language: LANGUAGE): CompletionSource {
|
||||
@@ -27,10 +29,12 @@ export function enhanceCompletion(language: LANGUAGE): CompletionSource {
|
||||
const word = context.matchBefore(/\w+/)
|
||||
if (!word && !context.explicit) return null
|
||||
|
||||
// SQL 没有中文注释提示,关键字补全由 @codemirror/lang-sql 提供
|
||||
if (language === "SQL") return null
|
||||
|
||||
const trulyLanguage = language.startsWith("Python") ? "python" : "c"
|
||||
const trulyLanguage =
|
||||
language === "SQL"
|
||||
? "sql"
|
||||
: language.startsWith("Python")
|
||||
? "python"
|
||||
: "c"
|
||||
const completions: Completion[] = (
|
||||
chineseAnnotations[trulyLanguage] || []
|
||||
).map((completion) => {
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
export const sql = [
|
||||
{
|
||||
label: "SELECT",
|
||||
detail: "查询数据",
|
||||
type: "keyword",
|
||||
info: "从表中查询数据,后面接要查询的列名,用 * 表示所有列。",
|
||||
boost: 100,
|
||||
apply: "SELECT ",
|
||||
},
|
||||
{
|
||||
label: "FROM",
|
||||
detail: "指定表",
|
||||
type: "keyword",
|
||||
info: "指定要查询的表,和 SELECT 搭配使用,如 SELECT * FROM 表名。",
|
||||
boost: 98,
|
||||
apply: "FROM ",
|
||||
},
|
||||
{
|
||||
label: "WHERE",
|
||||
detail: "筛选条件",
|
||||
type: "keyword",
|
||||
info: "按条件筛选行,只保留满足条件的数据,如 WHERE age > 18。",
|
||||
boost: 96,
|
||||
apply: "WHERE ",
|
||||
},
|
||||
{
|
||||
label: "ORDER BY",
|
||||
detail: "排序",
|
||||
type: "keyword",
|
||||
info: "按指定列排序,默认从小到大(ASC),加 DESC 表示从大到小。",
|
||||
boost: 90,
|
||||
apply: "ORDER BY ",
|
||||
},
|
||||
{
|
||||
label: "GROUP BY",
|
||||
detail: "分组",
|
||||
type: "keyword",
|
||||
info: "按指定列分组,常配合 COUNT、SUM 等聚合函数统计每组数据。",
|
||||
boost: 88,
|
||||
apply: "GROUP BY ",
|
||||
},
|
||||
{
|
||||
label: "HAVING",
|
||||
detail: "分组后筛选",
|
||||
type: "keyword",
|
||||
info: "对分组后的结果再筛选,WHERE 筛选行,HAVING 筛选组。",
|
||||
boost: 86,
|
||||
apply: "HAVING ",
|
||||
},
|
||||
{
|
||||
label: "LIMIT",
|
||||
detail: "限制条数",
|
||||
type: "keyword",
|
||||
info: "限制返回的行数,如 LIMIT 5 只取前 5 条,常和 ORDER BY 搭配。",
|
||||
boost: 84,
|
||||
apply: "LIMIT ",
|
||||
},
|
||||
{
|
||||
label: "DISTINCT",
|
||||
detail: "去重",
|
||||
type: "keyword",
|
||||
info: "去掉查询结果中的重复值,如 SELECT DISTINCT city FROM users。",
|
||||
boost: 82,
|
||||
apply: "DISTINCT ",
|
||||
},
|
||||
{
|
||||
label: "AS",
|
||||
detail: "起别名",
|
||||
type: "keyword",
|
||||
info: "给列或表起别名,让结果更易读,如 SELECT name AS 姓名。",
|
||||
boost: 80,
|
||||
apply: "AS ",
|
||||
},
|
||||
{
|
||||
label: "JOIN",
|
||||
detail: "连接表",
|
||||
type: "keyword",
|
||||
info: "把两张表按条件连接起来查询,需要用 ON 指定连接条件。",
|
||||
boost: 78,
|
||||
apply: "JOIN ",
|
||||
},
|
||||
{
|
||||
label: "LEFT JOIN",
|
||||
detail: "左连接",
|
||||
type: "keyword",
|
||||
info: "以左表为主连接右表,左表的行都保留,右表没匹配的补 NULL。",
|
||||
boost: 76,
|
||||
apply: "LEFT JOIN ",
|
||||
},
|
||||
{
|
||||
label: "ON",
|
||||
detail: "连接条件",
|
||||
type: "keyword",
|
||||
info: "指定两张表的连接条件,如 ON a.id = b.user_id,和 JOIN 搭配。",
|
||||
boost: 74,
|
||||
apply: "ON ",
|
||||
},
|
||||
{
|
||||
label: "INSERT INTO",
|
||||
detail: "插入数据",
|
||||
type: "keyword",
|
||||
info: "向表中插入新行,如 INSERT INTO 表名 (列1, 列2) VALUES (值1, 值2)。",
|
||||
boost: 72,
|
||||
apply: "INSERT INTO ",
|
||||
},
|
||||
{
|
||||
label: "VALUES",
|
||||
detail: "插入的值",
|
||||
type: "keyword",
|
||||
info: "和 INSERT INTO 搭配,写具体要插入的值,顺序要和列名对应。",
|
||||
boost: 70,
|
||||
apply: "VALUES ",
|
||||
},
|
||||
{
|
||||
label: "UPDATE",
|
||||
detail: "更新数据",
|
||||
type: "keyword",
|
||||
info: "修改表中已有的数据,配合 SET 设置新值,别忘了加 WHERE 限定范围。",
|
||||
boost: 68,
|
||||
apply: "UPDATE ",
|
||||
},
|
||||
{
|
||||
label: "SET",
|
||||
detail: "设置新值",
|
||||
type: "keyword",
|
||||
info: "和 UPDATE 搭配,指定要修改的列和新值,如 SET score = 90。",
|
||||
boost: 66,
|
||||
apply: "SET ",
|
||||
},
|
||||
{
|
||||
label: "DELETE FROM",
|
||||
detail: "删除数据",
|
||||
type: "keyword",
|
||||
info: "删除表中的行,一定要配合 WHERE 使用,否则会删掉整张表的数据。",
|
||||
boost: 64,
|
||||
apply: "DELETE FROM ",
|
||||
},
|
||||
{
|
||||
label: "CREATE TABLE",
|
||||
detail: "创建表",
|
||||
type: "keyword",
|
||||
info: "新建一张表,需要定义列名和类型,如 CREATE TABLE users (id INTEGER, name TEXT)。",
|
||||
boost: 62,
|
||||
apply: "CREATE TABLE ",
|
||||
},
|
||||
{
|
||||
label: "DROP TABLE",
|
||||
detail: "删除表",
|
||||
type: "keyword",
|
||||
info: "删除整张表(包括结构和数据),操作不可恢复,要谨慎使用。",
|
||||
boost: 60,
|
||||
apply: "DROP TABLE ",
|
||||
},
|
||||
{
|
||||
label: "ALTER TABLE",
|
||||
detail: "修改表结构",
|
||||
type: "keyword",
|
||||
info: "修改已有表的结构,比如添加列:ALTER TABLE 表名 ADD COLUMN 列名 类型。",
|
||||
boost: 58,
|
||||
apply: "ALTER TABLE ",
|
||||
},
|
||||
{
|
||||
label: "AND",
|
||||
detail: "并且",
|
||||
type: "keyword",
|
||||
info: "连接多个条件,全部成立才算满足,如 WHERE age > 18 AND city = '上海'。",
|
||||
boost: 56,
|
||||
apply: "AND ",
|
||||
},
|
||||
{
|
||||
label: "OR",
|
||||
detail: "或者",
|
||||
type: "keyword",
|
||||
info: "连接多个条件,任意一个成立就算满足。",
|
||||
boost: 54,
|
||||
apply: "OR ",
|
||||
},
|
||||
{
|
||||
label: "NOT",
|
||||
detail: "取反",
|
||||
type: "keyword",
|
||||
info: "对条件取反,如 NOT IN、NOT LIKE、IS NOT NULL。",
|
||||
boost: 52,
|
||||
apply: "NOT ",
|
||||
},
|
||||
{
|
||||
label: "IN",
|
||||
detail: "在列表中",
|
||||
type: "keyword",
|
||||
info: "判断值是否在给定列表中,如 WHERE city IN ('北京', '上海')。",
|
||||
boost: 50,
|
||||
apply: "IN ",
|
||||
},
|
||||
{
|
||||
label: "BETWEEN",
|
||||
detail: "在区间内",
|
||||
type: "keyword",
|
||||
info: "判断值是否在某个范围内(包含两端),如 BETWEEN 60 AND 100。",
|
||||
boost: 48,
|
||||
apply: "BETWEEN ",
|
||||
},
|
||||
{
|
||||
label: "LIKE",
|
||||
detail: "模糊匹配",
|
||||
type: "keyword",
|
||||
info: "模糊查询,% 匹配任意多个字符,_ 匹配单个字符,如 LIKE '张%'。",
|
||||
boost: 46,
|
||||
apply: "LIKE ",
|
||||
},
|
||||
{
|
||||
label: "IS NULL",
|
||||
detail: "是否为空",
|
||||
type: "keyword",
|
||||
info: "判断值是否为 NULL(空值),不能写 = NULL,要用 IS NULL。",
|
||||
boost: 44,
|
||||
},
|
||||
{
|
||||
label: "IS NOT NULL",
|
||||
detail: "是否非空",
|
||||
type: "keyword",
|
||||
info: "判断值不为 NULL,常用于过滤掉缺失数据的行。",
|
||||
boost: 42,
|
||||
},
|
||||
{
|
||||
label: "ASC",
|
||||
detail: "升序",
|
||||
type: "keyword",
|
||||
info: "排序时从小到大排列,是 ORDER BY 的默认方式,可以省略。",
|
||||
boost: 40,
|
||||
},
|
||||
{
|
||||
label: "DESC",
|
||||
detail: "降序",
|
||||
type: "keyword",
|
||||
info: "排序时从大到小排列,如 ORDER BY score DESC 按分数从高到低。",
|
||||
boost: 41,
|
||||
},
|
||||
{
|
||||
label: "UNION",
|
||||
detail: "合并结果",
|
||||
type: "keyword",
|
||||
info: "合并两个查询的结果并去重,两个查询的列数和类型要一致。",
|
||||
boost: 38,
|
||||
apply: "UNION ",
|
||||
},
|
||||
{
|
||||
label: "CASE",
|
||||
detail: "条件表达式",
|
||||
type: "keyword",
|
||||
info: "类似 if/else 的条件判断,语法 CASE WHEN 条件 THEN 值 ELSE 值 END。",
|
||||
boost: 36,
|
||||
apply: "CASE ",
|
||||
},
|
||||
{
|
||||
label: "WHEN",
|
||||
detail: "当条件成立",
|
||||
type: "keyword",
|
||||
info: "和 CASE 搭配,写判断条件,成立时返回 THEN 后面的值。",
|
||||
boost: 34,
|
||||
apply: "WHEN ",
|
||||
},
|
||||
{
|
||||
label: "THEN",
|
||||
detail: "返回值",
|
||||
type: "keyword",
|
||||
info: "和 WHEN 搭配,条件成立时返回的结果。",
|
||||
boost: 32,
|
||||
apply: "THEN ",
|
||||
},
|
||||
{
|
||||
label: "ELSE",
|
||||
detail: "否则",
|
||||
type: "keyword",
|
||||
info: "CASE 中所有 WHEN 都不成立时返回的默认值。",
|
||||
boost: 30,
|
||||
apply: "ELSE ",
|
||||
},
|
||||
{
|
||||
label: "END",
|
||||
detail: "结束 CASE",
|
||||
type: "keyword",
|
||||
info: "标记 CASE 表达式的结束,写 CASE 时不要漏掉。",
|
||||
boost: 28,
|
||||
},
|
||||
{
|
||||
label: "NULL",
|
||||
detail: "空值",
|
||||
type: "keyword",
|
||||
info: "表示没有值(缺失),判断时要用 IS NULL / IS NOT NULL。",
|
||||
boost: 26,
|
||||
},
|
||||
{
|
||||
label: "COUNT",
|
||||
detail: "统计行数",
|
||||
type: "function",
|
||||
info: "统计行数,COUNT(*) 统计所有行,COUNT(列名) 不统计 NULL。",
|
||||
boost: 92,
|
||||
apply: "COUNT()",
|
||||
},
|
||||
{
|
||||
label: "SUM",
|
||||
detail: "求和",
|
||||
type: "function",
|
||||
info: "对某一列求和,只能用于数字列,如 SUM(score)。",
|
||||
boost: 87,
|
||||
apply: "SUM()",
|
||||
},
|
||||
{
|
||||
label: "AVG",
|
||||
detail: "平均值",
|
||||
type: "function",
|
||||
info: "计算某一列的平均值,会自动忽略 NULL,如 AVG(score)。",
|
||||
boost: 85,
|
||||
apply: "AVG()",
|
||||
},
|
||||
{
|
||||
label: "MAX",
|
||||
detail: "最大值",
|
||||
type: "function",
|
||||
info: "求某一列的最大值,如 MAX(score) 找最高分。",
|
||||
boost: 83,
|
||||
apply: "MAX()",
|
||||
},
|
||||
{
|
||||
label: "MIN",
|
||||
detail: "最小值",
|
||||
type: "function",
|
||||
info: "求某一列的最小值,如 MIN(score) 找最低分。",
|
||||
boost: 81,
|
||||
apply: "MIN()",
|
||||
},
|
||||
{
|
||||
label: "LENGTH",
|
||||
detail: "字符串长度",
|
||||
type: "function",
|
||||
info: "返回字符串的字符个数,如 LENGTH(name)。",
|
||||
boost: 79,
|
||||
apply: "LENGTH()",
|
||||
},
|
||||
{
|
||||
label: "UPPER",
|
||||
detail: "转大写",
|
||||
type: "function",
|
||||
info: "把字符串中的字母转成大写,如 UPPER('abc') 得到 'ABC'。",
|
||||
boost: 77,
|
||||
apply: "UPPER()",
|
||||
},
|
||||
{
|
||||
label: "LOWER",
|
||||
detail: "转小写",
|
||||
type: "function",
|
||||
info: "把字符串中的字母转成小写,如 LOWER('ABC') 得到 'abc'。",
|
||||
boost: 75,
|
||||
apply: "LOWER()",
|
||||
},
|
||||
{
|
||||
label: "SUBSTR",
|
||||
detail: "截取子串",
|
||||
type: "function",
|
||||
info: "截取字符串的一部分,语法 SUBSTR(字符串, 起始位置, 长度),位置从 1 开始。",
|
||||
boost: 73,
|
||||
apply: "SUBSTR()",
|
||||
},
|
||||
{
|
||||
label: "REPLACE",
|
||||
detail: "替换字符串",
|
||||
type: "function",
|
||||
info: "把字符串中的内容替换成新内容,语法 REPLACE(字符串, 旧内容, 新内容)。",
|
||||
boost: 71,
|
||||
apply: "REPLACE()",
|
||||
},
|
||||
{
|
||||
label: "ROUND",
|
||||
detail: "四舍五入",
|
||||
type: "function",
|
||||
info: "按指定小数位四舍五入,如 ROUND(3.456, 2) 得到 3.46。",
|
||||
boost: 69,
|
||||
apply: "ROUND()",
|
||||
},
|
||||
{
|
||||
label: "ABS",
|
||||
detail: "绝对值",
|
||||
type: "function",
|
||||
info: "返回数字的绝对值,把负数变成正数,如 ABS(-5) 得到 5。",
|
||||
boost: 67,
|
||||
apply: "ABS()",
|
||||
},
|
||||
{
|
||||
label: "IFNULL",
|
||||
detail: "空值替代",
|
||||
type: "function",
|
||||
info: "如果第一个值是 NULL 就返回第二个值,如 IFNULL(score, 0) 把空分数当 0。",
|
||||
boost: 65,
|
||||
apply: "IFNULL()",
|
||||
},
|
||||
{
|
||||
label: "TRIM",
|
||||
detail: "去首尾空格",
|
||||
type: "function",
|
||||
info: "去掉字符串首尾的空格,常用于清理输入数据。",
|
||||
boost: 63,
|
||||
apply: "TRIM()",
|
||||
},
|
||||
]
|
||||
Reference in New Issue
Block a user