feat: 搜索栏折叠、优化作业
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled

This commit is contained in:
阿梦 2026-05-15 16:50:30 +08:00
parent 5112e9e77c
commit 51531fa49a
3 changed files with 131 additions and 30 deletions

View File

@ -42,6 +42,18 @@ $row_selected_bg: #ebf9ff; // #ffebbc;
.vxe-form {
background-color: transparent !important;
.search-form-actions {
display: inline-flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
// 隐藏 vxe 内置折叠触发器已改用 vxe-button
.vxe-form--item-trigger-node {
display: none !important;
}
}
}

View File

@ -102,9 +102,43 @@ const gridRef = ref()
const defaultSearchFormOptions = {
titleBold: true,
data: {},
collapseNode: true,
collapseStatus: false,
} as VxeFormProps
const SEARCH_FORM_ROW_SPAN = 24
/** 第二行及以后的筛选项折叠;操作区显示展开/收起 */
function applySearchFormCollapse(items: any[], defaultSpan = 6) {
let usedSpan = 0
let rowIndex = 0
return items.map((item) => {
if (item.slots?.default === 'action') {
return item
}
if (item.collapseNode) {
return item
}
const span = Number(item.span ?? defaultSpan)
if (usedSpan + span > SEARCH_FORM_ROW_SPAN) {
rowIndex++
usedSpan = span
} else {
usedSpan += span
if (usedSpan >= SEARCH_FORM_ROW_SPAN) {
rowIndex++
usedSpan = 0
}
}
if (rowIndex >= 1 && item.folding !== false) {
return { ...item, folding: true }
}
return item
})
}
//
const checkedProp = 'checked'
const defaultGridOptions = {
@ -153,7 +187,11 @@ const gridOptions = ref(defaultGridOptions)
//
function initGrid() {
//
const userColumns = (props.grid?.columns || []) as any[]
const leftFixedColumns = userColumns.filter((col) => col.fixed === 'left')
const restColumns = userColumns.filter((col) => col.fixed !== 'left')
//
const gridColumns = []
if (!_hideCheckbox.value) {
gridColumns.push({
@ -163,6 +201,7 @@ function initGrid() {
slots: { header: 'checkbox_header', checkbox: 'checkbox_cell' },
})
}
gridColumns.push(...leftFixedColumns)
if (!_hideEdit.value) {
gridColumns.push({
title: '编辑',
@ -171,11 +210,13 @@ function initGrid() {
slots: { default: 'mj_edit_default' },
})
}
gridColumns.push(...restColumns)
//
const gridOptionsTmp = { ...defaultGridOptions, data: gridOptions.value.data }
const { columns: _columns, ...gridRest } = props.grid || {}
gridOptionsTmp.columns = gridColumns as any
obj.cover(gridOptionsTmp, props.grid)
obj.cover(gridOptionsTmp, gridRest)
for (const column of gridOptionsTmp.columns!) {
if (column.width || column.minWidth) continue
@ -198,7 +239,7 @@ function initGrid() {
...defaultSearchFormOptions,
}
obj.cover(searchFormOptions, props.searchForm)
searchFormOptions.items = [
searchFormOptions.items = applySearchFormCollapse([
{
field: 'keyword',
title: '关键字',
@ -215,7 +256,7 @@ function initGrid() {
{
slots: { default: 'action' },
},
]
])
searchFormOptions.data = gridOptions.value.formConfig?.data || {}
gridOptionsTmp.formConfig = searchFormOptions
}
@ -225,6 +266,7 @@ function initGrid() {
}
gridOptions.value = gridOptionsTmp
nextTick(() => syncSearchFormCollapsed())
}
//
@ -445,6 +487,34 @@ function reload() {
gridRef.value.commitProxy('reload')
}
const searchFormCollapsed = ref(false)
const hasSearchFormFold = computed(() =>
!!gridOptions.value.formConfig?.items?.some((item: any) => item.folding),
)
function getSearchFormRef() {
const maps = gridRef.value?.getRefMaps?.()
if (!maps) return null
const formRef = maps.refForm
return formRef?.value ?? formRef
}
function syncSearchFormCollapsed() {
const formRef = getSearchFormRef()
if (formRef?.getCollapseStatus) {
searchFormCollapsed.value = formRef.getCollapseStatus()
}
}
function toggleSearchCollapse() {
const formRef = getSearchFormRef()
if (!formRef?.toggleCollapse) return
formRef.toggleCollapse().then(() => {
syncSearchFormCollapsed()
})
}
//
function searchFormReset() {
//
@ -629,12 +699,23 @@ defineExpose({
</template>
<template #action>
<vxe-button icon="vxe-icon-repeat" @click="searchFormReset">
重置
</vxe-button>
<vxe-button type="submit" icon="vxe-icon-search" status="primary">
搜索
</vxe-button>
<div class="search-form-actions">
<vxe-button icon="vxe-icon-repeat" @click="searchFormReset">
重置
</vxe-button>
<vxe-button type="submit" icon="vxe-icon-search" status="primary">
搜索
</vxe-button>
<vxe-button
v-if="hasSearchFormFold"
:icon="
searchFormCollapsed ? 'vxe-icon-arrow-down' : 'vxe-icon-arrow-up'
"
@click="toggleSearchCollapse"
>
{{ searchFormCollapsed ? '展开' : '收起' }}
</vxe-button>
</div>
</template>
</VxeGrid>

View File

@ -266,6 +266,15 @@ const searchForm = {
//
const grid = {
columns: [
{
title: '操作',
field: 'operation',
width: 300,
fixed: 'left',
slots: {
default: 'operation',
},
},
{
title: '年级',
field: 'gradeId',
@ -315,13 +324,6 @@ const grid = {
default: 'uploadStatus',
},
},
{
title: '操作',
minWidth: 380,
slots: {
default: 'operation',
},
},
],
beforeLoadData(params) {
if (userInfo.value.isOnlyStaff) {
@ -471,17 +473,22 @@ onMounted(() => {
<el-button size="small" type="success" @click="createTask(row)">
布置作业
</el-button>
<el-button
v-if="row.uploadStatus !== 1"
size="small"
type="info"
@click="triggerUploadPdf(row)"
>
上传试题
</el-button>
<el-button size="small" type="danger" @click="deletePaper(row)">
删除试卷
</el-button>
<el-dropdown trigger="hover">
<el-button size="small">更多</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-if="row.uploadStatus !== 1"
@click="triggerUploadPdf(row)"
>
上传试题
</el-dropdown-item>
<el-dropdown-item @click="deletePaper(row)">
删除试卷
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</MjTable>
@ -509,8 +516,9 @@ onMounted(() => {
.operation-btns {
display: flex;
flex-wrap: wrap;
flex-wrap: nowrap;
gap: 4px;
align-items: center;
justify-content: flex-start;
.el-button + .el-button {