优化题库代码
This commit is contained in:
parent
ff9a181c99
commit
5fddba8a30
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,6 +24,7 @@ dist
|
||||
dist-ssr
|
||||
*.local
|
||||
server/uploads
|
||||
server/conf/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="p-4">Certificate</div>
|
||||
</template>
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="p-4">Create Exam Placeholder</div>
|
||||
</template>
|
||||
@ -124,7 +124,8 @@ import '@wangeditor/editor/dist/css/style.css'
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
mode: { type: String, default: 'create' },
|
||||
model: { type: Object, default: null }
|
||||
model: { type: Object, default: null },
|
||||
bankId: { type: [Number, String], default: null }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close', 'saved'])
|
||||
@ -380,6 +381,7 @@ function handleSubmit() {
|
||||
options: showOptions.value ? form.options.map(o => ({ key: o.key, label: o.label, content: o.content })) : [],
|
||||
answer: isMultipleType.value ? [...multiAnswer.value] : form.answer
|
||||
}
|
||||
if (props.bankId) payload.bank_id = props.bankId
|
||||
emit('saved', payload)
|
||||
} catch (e) {
|
||||
ElMessage.error('保存失败')
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<!-- 顶部工具栏:返回 + 标题 -->
|
||||
<div class="topbar">
|
||||
<el-button :icon="Back" @click="emit('back')">返回</el-button>
|
||||
<div class="title">题目列表</div>
|
||||
<div class="title">{{ bankName }}</div>
|
||||
</div>
|
||||
|
||||
<el-divider />
|
||||
@ -16,36 +16,38 @@
|
||||
<el-input v-model="filters.keyword" placeholder="请输入题干关键词" clearable
|
||||
@keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
<el-form-item label="题型">
|
||||
<el-select v-model="filters.type" placeholder="请选择题型" clearable style="width: 200px;">
|
||||
<el-option v-for="opt in typeOptions" :key="opt.dict_value" :label="opt.dict_label"
|
||||
:value="opt.dict_value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
<el-divider />
|
||||
<div class="tools">
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Plus" @click="handleCreate">新建题目</el-button>
|
||||
<el-button type="primary" :icon="Plus" @click="handleSmartCreate">智能新建</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
<el-button :icon="Refresh" @click="fetchList">刷新</el-button>
|
||||
<el-button :icon="Upload" @click="handleBatchImport">批量导入</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<!-- 操作栏 -->
|
||||
<!-- <div class="header">
|
||||
<div class="toolbar">
|
||||
<el-button type="primary" :icon="Plus" @click="handleCreate">新建题目</el-button>
|
||||
<el-button type="primary" :icon="Plus" @click="handleSmartCreate">智能新建</el-button>
|
||||
<div style="flex:1" />
|
||||
<el-button :icon="Refresh" @click="fetchList">刷新</el-button>
|
||||
<el-button :icon="Upload" @click="handleBatchImport">批量导入</el-button>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list" stripe border>
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column prop="question_title" label="题目" min-width="260" show-overflow-tooltip />
|
||||
<el-table-column prop="question_title" label="题目" min-width="260" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div v-html="row.question_title"></div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="question_type" label="题型" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag>{{ getTypeLabel(row.question_type) }}</el-tag>
|
||||
@ -72,7 +74,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 弹窗:仅用于创建/编辑题目与查看详情 -->
|
||||
<EditDialog :visible="editVisible" :mode="editMode" :model="editModel" @close="editVisible = false"
|
||||
<EditDialog :visible="editVisible" :mode="editMode" :model="editModel" :bank-id="props.bankId" @close="editVisible = false"
|
||||
@saved="handleSaved" />
|
||||
<DetailDialog :visible="viewVisible" :model="viewModel" @close="viewVisible = false" />
|
||||
|
||||
@ -86,15 +88,11 @@
|
||||
</div>
|
||||
|
||||
<el-divider content-position="left">上传 Excel 文件</el-divider>
|
||||
<el-upload
|
||||
class="upload-block"
|
||||
:show-file-list="false"
|
||||
accept=".xls,.xlsx"
|
||||
:auto-upload="false"
|
||||
:on-change="handleImportFileChange"
|
||||
>
|
||||
<el-upload class="upload-block" :show-file-list="false" accept=".xls,.xlsx" :auto-upload="false"
|
||||
:on-change="handleImportFileChange">
|
||||
<el-button type="primary" :loading="importing">选择 Excel 文件</el-button>
|
||||
<span style="margin-left: 12px; color:#888; font-size:12px;">表头需包含:question_title, question_type, score, question_analysis, option_a, option_b, ... , answer</span>
|
||||
<span style="margin-left: 12px; color:#888; font-size:12px;">表头需包含:question_title, question_type, score,
|
||||
question_analysis, option_a, option_b, ... , answer</span>
|
||||
</el-upload>
|
||||
|
||||
<template #footer>
|
||||
@ -109,12 +107,8 @@
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="题型">
|
||||
<el-select v-model="smartType" placeholder="请选择题型" style="width: 260px;">
|
||||
<el-option
|
||||
v-for="opt in typeOptions"
|
||||
:key="opt.dict_value"
|
||||
:label="opt.dict_label"
|
||||
:value="String(opt.dict_value)"
|
||||
/>
|
||||
<el-option v-for="opt in typeOptions" :key="opt.dict_value" :label="opt.dict_label"
|
||||
:value="String(opt.dict_value)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -122,13 +116,8 @@
|
||||
<p style="margin: 4px 0 8px; font-size: 13px; color: #666;">
|
||||
请粘贴完整的题目文本,包含题干、选项、答案和解析,例如:
|
||||
</p>
|
||||
<el-input
|
||||
v-model="smartRawText"
|
||||
type="textarea"
|
||||
:rows="10"
|
||||
placeholder="在这里粘贴题目文本..."
|
||||
style="margin-top: 12px;"
|
||||
/>
|
||||
<el-input v-model="smartRawText" type="textarea" :rows="10" placeholder="在这里粘贴题目文本..."
|
||||
style="margin-top: 12px;" />
|
||||
|
||||
<template #footer>
|
||||
<div class="dlg-actions">
|
||||
@ -152,9 +141,6 @@ import { getExamQuestions, getExamQuestionDetail, createExamQuestion, updateExam
|
||||
import EditDialog from './edit.vue'
|
||||
import DetailDialog from './detail.vue'
|
||||
|
||||
const props = defineProps({
|
||||
bankId: { type: [Number, String], default: null },
|
||||
})
|
||||
const emit = defineEmits(['back', 'saved'])
|
||||
|
||||
const auth = useAuthStore()
|
||||
@ -173,6 +159,11 @@ const typeDictMap = computed(() => {
|
||||
return m
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
bankId: { type: [Number, String], default: null },
|
||||
bankName: { type: String, default: '' },
|
||||
})
|
||||
|
||||
// 模板
|
||||
function handleDownloadTemplate() {
|
||||
// 英文字段名(程序使用)
|
||||
@ -451,7 +442,7 @@ function handleImportFileChange(file) {
|
||||
return
|
||||
}
|
||||
importing.value = true
|
||||
const res = await batchImportExamQuestions({ items })
|
||||
const res = await batchImportExamQuestions({ bank_id: props.bankId || undefined, items })
|
||||
if (res && res.code === 0) {
|
||||
const data = res.data || {}
|
||||
ElMessage.success(`导入完成:成功 ${data.success ?? 0} 条,失败 ${data.failed ?? 0} 条`)
|
||||
@ -668,11 +659,16 @@ onMounted(async () => {
|
||||
|
||||
.topbar .title {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
/* margin-bottom: 12px; */
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
|
||||
@ -1,75 +1,50 @@
|
||||
<template>
|
||||
<div class="examination-questions">
|
||||
<template v-if="!examListVisible">
|
||||
<!-- 搜索栏 -->
|
||||
<div class="search-bar">
|
||||
<el-form :inline="true" :model="filters">
|
||||
<div class="form-fields">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="filters.keyword" placeholder="请输入题目关键词" clearable
|
||||
@keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
<el-form-item label="题型">
|
||||
<el-select v-model="filters.type" placeholder="请选择题型" clearable>
|
||||
<el-option v-for="opt in dictTypeOptions" :key="opt.dict_value" :label="opt.dict_label"
|
||||
:value="opt.dict_value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-divider />
|
||||
<div class="form-actions">
|
||||
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<div class="toolbar">
|
||||
<el-button type="primary" :icon="Plus" @click="handleCreate">新建题库</el-button>
|
||||
<div class="toolright">
|
||||
<el-button @click="handleBatchImport" :icon="Upload">批量导入</el-button>
|
||||
<el-button @click="handleRefresh" :icon="Refresh">刷新</el-button>
|
||||
<!-- 搜索栏 -->
|
||||
<div class="search-bar">
|
||||
<el-form :inline="true" :model="filters">
|
||||
<div class="form-actions">
|
||||
<div class="left">
|
||||
<el-button type="primary" :icon="Plus" @click="handleCreate">新建题库</el-button>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button @click="handleBatchImport" :icon="Upload">批量导入</el-button>
|
||||
<el-button @click="handleRefresh" :icon="Refresh">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 题库列表 -->
|
||||
<el-table v-loading="loading" :data="bankList" stripe border style="width: 100%">
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column prop="bank_name" label="题库名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="bank_desc" label="描述" min-width="200" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="String(row.status)==='0' ? 'success' : 'info'">{{ String(row.status)==='0' ? '启用' : '禁用' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column prop="create_time" label="创建时间" width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row.create_time) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="primary" size="small" @click="handleAdd(row)">题目管理</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 题库列表 -->
|
||||
<el-table v-loading="loading" :data="bankList" stripe border style="width: 100%">
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column prop="bank_name" label="题库名称" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="bank_desc" label="描述" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button link type="primary" size="small" @click="handleAdd(row)">题目管理</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
|
||||
:page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="handlePageChange" @size-change="handleSizeChange" />
|
||||
</div>
|
||||
<EditDialog :visible="editVisible" :mode="editMode" :model="editModel" @close="editVisible = false"
|
||||
@saved="handleSaved" />
|
||||
<EditBanks :visible="bankVisible" :mode="bankMode" :model="bankModel" @close="bankVisible = false" @saved="handleBankSaved" />
|
||||
<DetailDialog :visible="viewVisible" :model="viewModel" @close="viewVisible = false" />
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
|
||||
:page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="handlePageChange" @size-change="handleSizeChange" />
|
||||
</div>
|
||||
<EditDialog :visible="editVisible" :mode="editMode" :model="editModel" @close="editVisible = false"
|
||||
@saved="handleSaved" />
|
||||
<EditBanks :visible="bankVisible" :mode="bankMode" :model="bankModel" @close="bankVisible = false"
|
||||
@saved="handleBankSaved" />
|
||||
<DetailDialog :visible="viewVisible" :model="viewModel" @close="viewVisible = false" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<ExamList :bank-id="examListBankId" @back="examListVisible = false" />
|
||||
<ExamList :bank-id="examListBankId" :bank-name="examListBankName" @back="examListVisible = false" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@ -111,6 +86,7 @@ const bankModel = ref(null);
|
||||
|
||||
const examListVisible = ref(false);
|
||||
const examListBankId = ref(null);
|
||||
const examListBankName = ref('');
|
||||
|
||||
const auth = useAuthStore();
|
||||
|
||||
@ -156,7 +132,7 @@ const handleBatchImport = () => {
|
||||
ElMessage.info('批量导入功能开发中');
|
||||
};
|
||||
|
||||
const handleView = async (row) => {};
|
||||
const handleView = async (row) => { };
|
||||
|
||||
const handleRefresh = () => {
|
||||
fetchBankList();
|
||||
@ -171,6 +147,7 @@ const handleBankSaved = async (payload) => {
|
||||
}
|
||||
ElMessage.success('保存成功');
|
||||
bankVisible.value = false;
|
||||
await fetchBankList();
|
||||
} catch (e) {
|
||||
ElMessage.error('保存失败');
|
||||
}
|
||||
@ -184,6 +161,7 @@ const handleEdit = (row) => {
|
||||
|
||||
const handleAdd = (row) => {
|
||||
examListBankId.value = row?.id || null;
|
||||
examListBankName.value = row?.bank_name || '';
|
||||
examListVisible.value = true;
|
||||
};
|
||||
|
||||
@ -214,7 +192,7 @@ const handleDelete = async (row) => {
|
||||
ElMessage.success('删除成功');
|
||||
fetchBankList();
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -301,6 +279,7 @@ onMounted(() => {
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="p-4">Examinee</div>
|
||||
</template>
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="p-4">Practice</div>
|
||||
</template>
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="p-4">Training</div>
|
||||
</template>
|
||||
@ -6,7 +6,7 @@ runmode = dev
|
||||
# MySQL - 远程连接配置
|
||||
mysqluser = gotest
|
||||
mysqlpass = 2nZhRdMPCNZrdzsd
|
||||
mysqlurls = 192.168.31.10:3306
|
||||
mysqlurls = 212.64.112.158:3388
|
||||
mysqldb = gotest
|
||||
|
||||
# ORM配置
|
||||
|
||||
@ -24,6 +24,8 @@ func (c *ExamQuestionController) GetList() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
keyword := c.GetString("keyword")
|
||||
typeStr := c.GetString("type")
|
||||
bankId, _ := c.GetInt64("bank_id", 0)
|
||||
|
||||
var qtype *int8
|
||||
if typeStr != "" {
|
||||
if iv, err := strconv.Atoi(typeStr); err == nil {
|
||||
@ -31,12 +33,15 @@ func (c *ExamQuestionController) GetList() {
|
||||
qtype = &v
|
||||
}
|
||||
}
|
||||
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 10)
|
||||
|
||||
list, total, err := services.GetExamQuestions(services.QuestionListParams{
|
||||
TenantId: tenantId,
|
||||
Keyword: keyword,
|
||||
QuestionType: qtype,
|
||||
BankId: bankId,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
@ -45,7 +50,7 @@ func (c *ExamQuestionController) GetList() {
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
// build minimal DTO to limit fields in response
|
||||
|
||||
items := make([]map[string]interface{}, 0, len(list))
|
||||
for _, q := range list {
|
||||
if q == nil {
|
||||
@ -59,6 +64,7 @@ func (c *ExamQuestionController) GetList() {
|
||||
"score": q.Score,
|
||||
})
|
||||
}
|
||||
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 0,
|
||||
"message": "ok",
|
||||
@ -101,6 +107,7 @@ func (c *ExamQuestionController) Create() {
|
||||
QuestionAnalysis string `json:"question_analysis"`
|
||||
Options []map[string]string `json:"options"`
|
||||
Answer interface{} `json:"answer"`
|
||||
BankId int64 `json:"bank_id"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
@ -115,6 +122,9 @@ func (c *ExamQuestionController) Create() {
|
||||
Score: payload.Score,
|
||||
Status: 1,
|
||||
}
|
||||
if payload.BankId > 0 {
|
||||
q.BankId = payload.BankId
|
||||
}
|
||||
var opts []models.ExamQuestionOption
|
||||
for _, o := range payload.Options {
|
||||
opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]})
|
||||
@ -149,6 +159,7 @@ func (c *ExamQuestionController) Create() {
|
||||
func (c *ExamQuestionController) BatchCreate() {
|
||||
tenantId, _ := c.Ctx.Input.GetData("tenantId").(int)
|
||||
var payload struct {
|
||||
BankId int64 `json:"bank_id"`
|
||||
Items []struct {
|
||||
QuestionTitle string `json:"question_title"`
|
||||
QuestionType int8 `json:"question_type"`
|
||||
@ -182,6 +193,9 @@ func (c *ExamQuestionController) BatchCreate() {
|
||||
Score: item.Score,
|
||||
Status: 1,
|
||||
}
|
||||
if payload.BankId > 0 {
|
||||
q.BankId = payload.BankId
|
||||
}
|
||||
var opts []models.ExamQuestionOption
|
||||
for _, o := range item.Options {
|
||||
opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]})
|
||||
@ -251,6 +265,7 @@ func (c *ExamQuestionController) Update() {
|
||||
QuestionAnalysis string `json:"question_analysis"`
|
||||
Options []map[string]string `json:"options"`
|
||||
Answer interface{} `json:"answer"`
|
||||
BankId int64 `json:"bank_id"`
|
||||
}
|
||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||||
c.Data["json"] = map[string]interface{}{"code": 1, "message": "请求参数错误: " + err.Error(), "data": nil}
|
||||
@ -258,6 +273,9 @@ func (c *ExamQuestionController) Update() {
|
||||
return
|
||||
}
|
||||
q := &models.ExamQuestion{QuestionType: payload.QuestionType, QuestionTitle: payload.QuestionTitle, QuestionAnalysis: payload.QuestionAnalysis, Score: payload.Score}
|
||||
if payload.BankId > 0 {
|
||||
q.BankId = payload.BankId
|
||||
}
|
||||
var opts []models.ExamQuestionOption
|
||||
for _, o := range payload.Options {
|
||||
opts = append(opts, models.ExamQuestionOption{OptionLabel: o["label"], OptionContent: o["content"]})
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
type ExamQuestion struct {
|
||||
Id int64 `orm:"column(id);auto" json:"id"`
|
||||
TenantId int `orm:"column(tenant_id)" json:"tenant_id"`
|
||||
BankId int64 `orm:"column(bank_id);null" json:"bank_id"`
|
||||
QuestionType int8 `orm:"column(question_type)" json:"question_type"`
|
||||
QuestionTitle string `orm:"column(question_title);size(1000)" json:"question_title"`
|
||||
QuestionAnalysis string `orm:"column(question_analysis);size(2000);null" json:"question_analysis"`
|
||||
|
||||
@ -13,6 +13,7 @@ type QuestionListParams struct {
|
||||
TenantId int
|
||||
Keyword string
|
||||
QuestionType *int8
|
||||
BankId int64
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
@ -42,6 +43,9 @@ func GetExamQuestions(params QuestionListParams) ([]*models.ExamQuestion, int64,
|
||||
if params.QuestionType != nil {
|
||||
qs = qs.Filter("question_type", *params.QuestionType)
|
||||
}
|
||||
if params.BankId > 0 {
|
||||
qs = qs.Filter("bank_id", params.BankId)
|
||||
}
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@ -121,7 +125,13 @@ func UpdateExamQuestion(tenantId int, id int64, q *models.ExamQuestion, options
|
||||
existing.QuestionTitle = q.QuestionTitle
|
||||
existing.QuestionAnalysis = q.QuestionAnalysis
|
||||
existing.Score = q.Score
|
||||
if _, err := o.Update(&existing, "QuestionType", "QuestionTitle", "QuestionAnalysis", "Score"); err != nil {
|
||||
// 可选更新题库归属
|
||||
fields := []string{"QuestionType", "QuestionTitle", "QuestionAnalysis", "Score"}
|
||||
if q.BankId > 0 {
|
||||
existing.BankId = q.BankId
|
||||
fields = append(fields, "BankId")
|
||||
}
|
||||
if _, err := o.Update(&existing, fields...); err != nil {
|
||||
return err
|
||||
}
|
||||
// soft delete old options and answer
|
||||
|
||||
Loading…
Reference in New Issue
Block a user