style: 调整ManageListRemote.vue中的选择器样式,优化课程管理界面的操作按钮布局,增强用户体验;更新index.scss以修正列表项内文本对齐方式。

This commit is contained in:
huweihang
2025-12-12 17:20:29 +08:00
parent 2d06dde984
commit ef926e6418
2 changed files with 198 additions and 105 deletions

View File

@@ -443,7 +443,7 @@ li{
padding: 0 20px;
p{
display: flex;
align-items: center;
align-items: baseline;
justify-content: center;
.el-icon-warning-outline{
margin-right: 6px;

View File

@@ -12,9 +12,23 @@
</div>
<div class="filter-field filter-field--teacher teacher-filter">
<div class="teacher-select-wrapper">
<el-select class="creator-select" ref="teacherSelect" v-model="teacherSelected" multiple filterable remote
clearable reserve-keyword placeholder="授课教师" :multiple-limit="5" :remote-method="remoteSearchTeacher"
:loading="teacherLoading" @change="handleTeacherChange" @clear="handleTeacherClear">
<el-select
class="creator-select"
ref="teacherSelect"
v-model="teacherSelected"
multiple
filterable
remote
clearable
reserve-keyword
placeholder="授课教师"
:multiple-limit="5"
:remote-method="remoteSearchTeacher"
:loading="teacherLoading"
@input.native="limitTeacherInput"
@change="handleTeacherChange"
@clear="handleTeacherClear"
>
<el-option v-for="item in teacherOptions" :key="item.teacherId" :label="item.teacherName"
:value="item.teacherId">
<span>{{ item.teacherName }}</span>
@@ -93,9 +107,23 @@
</div>
<div class="filter-field filter-field--creator creator-filter">
<div class="teacher-select-wrapper">
<el-select class="creator-select" ref="creatorSelect" v-model="creatorSelected" multiple filterable remote
clearable reserve-keyword placeholder="创建人" :multiple-limit="5" :remote-method="remoteSearchCreator"
:loading="creatorLoading" @change="handleCreatorChange" @clear="handleCreatorClear">
<el-select
class="creator-select"
ref="creatorSelect"
v-model="creatorSelected"
multiple
filterable
remote
clearable
reserve-keyword
placeholder="创建人"
:multiple-limit="5"
:remote-method="remoteSearchCreator"
:loading="creatorLoading"
@input.native="limitCreatorInput"
@change="handleCreatorChange"
@clear="handleCreatorClear"
>
<el-option v-for="item in creatorOptions" :key="item.userId" :label="item.name" :value="item.userId">
<span>{{ item.name }}</span>
<span v-if="item.code" class="option-code">{{ item.code }}</span>
@@ -143,12 +171,12 @@
</template>
</el-table-column>
<el-table-column label="课程名称" prop="name" header-align="center" align="left" min-width="360"
show-overflow-tooltip fixed="left" sortable>
show-overflow-tooltip fixed="left" sortable="custom">
<template slot-scope="scope">
<span class="course-name" @click="viewTopic(scope.row)">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="课程分类" prop="sysType" min-width="180" align="center" sortable show-overflow-tooltip>
<el-table-column label="课程分类" prop="sysType" min-width="180" align="center" sortable="custom" show-overflow-tooltip>
<template slot-scope="scope">
<span class="common-cell single-line-ellipsis">{{ formatSysTypeChain(scope.row) }}</span>
</template>
@@ -158,22 +186,22 @@
<span class="common-cell">{{ scope.row.teacherName }}</span>
</template>
</el-table-column>
<el-table-column label="课程时长" prop="courseDuration" min-width="110" align="center" sortable>
<el-table-column label="课程时长" prop="courseDuration" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ formatCourseDuration(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column label="学习人数" prop="studys" min-width="110" align="center" sortable>
<el-table-column label="学习人数" prop="studys" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.studys || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="课程评分" prop="score" min-width="110" align="center" sortable>
<el-table-column label="课程评分" prop="score" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ formatScore(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column label="审核状态" prop="status" min-width="110" align="center" sortable>
<el-table-column label="审核状态" prop="status" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell" v-if="scope.row.status == 1">-</span>
<span class="common-cell" v-if="scope.row.status == 2">审核中</span>
@@ -181,29 +209,29 @@
<span :class="['common-cell', 'status--reject']" v-if="scope.row.status == 3">审核驳回</span>
</template>
</el-table-column>
<el-table-column label="发布状态" prop="published" min-width="110" align="center" sortable>
<el-table-column label="发布状态" prop="published" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.published == true ? '已发布' : '未发布' }}</span>
</template>
</el-table-column>
<el-table-column label="启停用状态" prop="enabled" min-width="130" align="center" sortable>
<el-table-column label="启停用状态" prop="enabled" min-width="130" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.enabled == true ? '启用' : '停用' }}</span>
</template>
</el-table-column>
<el-table-column label="公开课" prop="openCourse" min-width="110" align="center" sortable>
<el-table-column label="公开课" prop="openCourse" min-width="110" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.openCourse == 1 ? '是' : '否' }}</span>
</template>
</el-table-column>
<el-table-column label="资源归属" prop="orgName" min-width="220" align="center" sortable>
<el-table-column label="资源归属" prop="orgName" min-width="220" align="center" sortable="custom">
<template slot-scope="scope">
<el-tooltip :content="scope.row.orgFullName || scope.row.orgName" placement="top" effect="dark">
<span class="common-cell">{{ scope.row.orgName }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="创建人" prop="sysCreateBy" min-width="130" align="center" sortable>
<el-table-column label="创建人" prop="sysCreateBy" min-width="130" align="center" sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.sysCreateBy }}</span>
</template>
@@ -216,57 +244,48 @@
</template>
</el-table-column>
<el-table-column label="创建时间" prop="sysCreateTime" min-width="200" show-overflow-tooltip align="center"
sortable>
sortable="custom">
<template slot-scope="scope">
<span class="common-cell">{{ scope.row.sysCreateTime }}</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="280px" fixed="right" header-align="center" align="left">
<template slot-scope="scope" class="btn-gl">
<!-- 20240621 修改scope.row.isPermission = fasle 时不展示操作按钮-->
<!-- v-if="scope.row.isPermission && !forChoose && scope.row.status == 2" -->
<template v-if="scope.row.isPermission && scope.row.status != 2">
<el-button type="text" size="mini"
class="action-link--primary" @click="editCurriculum(scope.row)">编辑</el-button>
<el-divider direction="vertical"></el-divider>
<template v-if="getInlineActions(scope.row).length">
<span v-for="(action, index) in getInlineActions(scope.row)" :key="action.key">
<el-button
type="text"
size="mini"
:class="action.className"
@click="handleAction(action.key, scope.row)"
>
{{ action.label }}
</el-button>
<el-divider
v-if="index < getInlineActions(scope.row).length - 1 || (index === getInlineActions(scope.row).length - 1 && getDropdownActions(scope.row).length)"
direction="vertical"
></el-divider>
</span>
</template>
<template v-if="showSetTopFeature && scope.row.published">
<el-button type="text" size="mini"
class="action-link--primary" @click="showQrimage(scope.row)">二维码</el-button>
<el-divider direction="vertical"></el-divider>
</template>
<template v-if="scope.row.isPermission && !forChoose && scope.row.published">
<el-button @click="showManageStudy(scope.row)" type="text" size="mini"
class="action-link--primary">管理</el-button>
<el-divider direction="vertical"></el-divider>
</template>
<template v-if="scope.row.isPermission && !forChoose && scope.row.status == 2">
<el-button type="text" size="mini" class="action-link--primary"
@click="withdraw(scope.row)">撤回</el-button>
<el-divider direction="vertical"></el-divider>
</template>
<template v-if="scope.row.isPermission && (scope.row.status != 2 && !scope.row.published) || scope.row.isPermission && !scope.row.enabled">
<el-button
type="text" class="action-link--danger" size="mini" @click="delItem(scope.row)">删除</el-button>
<el-divider direction="vertical"></el-divider>
</template>
<el-dropdown v-if="scope.row.isPermission && scope.row.published" type="text" size="mini"
style="margin-left:0px">
<el-button type="text" size="mini" class="action-link--more">更多<i
class="el-icon-arrow-down el-icon--right"></i></el-button>
<el-dropdown
v-if="getDropdownActions(scope.row).length"
type="text"
size="mini"
style="margin-left:0px"
trigger="click"
>
<el-button type="text" size="mini" class="action-link--more">
更多<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="copyCourse(scope.row)"
class="action-link--primary">复制</el-dropdown-item>
<el-dropdown-item v-if="scope.row.published" @click.native="isDisable(scope.row)"
class="action-link--bold">{{
scope.row.enabled ?
'停用' : '启用' }}</el-dropdown-item>
<el-dropdown-item v-if="showSetTopFeature && scope.row.published" @click.native="setTop(scope.row)">{{
scope.row.isTop ? '取消置顶' : '置顶' }}</el-dropdown-item>
<el-dropdown-item
v-for="action in getDropdownActions(scope.row)"
:key="action.key"
:class="action.className"
@click.native="handleAction(action.key, scope.row)"
>
{{ action.label }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
@@ -649,6 +668,11 @@ export default {
const limited = (keyword || '').slice(0, 50);
if (this.$refs.teacherSelect && this.$refs.teacherSelect.query !== limited) {
this.$refs.teacherSelect.query = limited;
this.$nextTick(() => {
if (this.$refs.teacherSelect && this.$refs.teacherSelect.$refs && this.$refs.teacherSelect.$refs.input) {
this.$refs.teacherSelect.$refs.input.value = limited;
}
});
}
const query = limited.trim();
if (!query || query.length <= 1) {
@@ -697,6 +721,11 @@ export default {
const limited = (keyword || '').slice(0, 50);
if (this.$refs.creatorSelect && this.$refs.creatorSelect.query !== limited) {
this.$refs.creatorSelect.query = limited;
this.$nextTick(() => {
if (this.$refs.creatorSelect && this.$refs.creatorSelect.$refs && this.$refs.creatorSelect.$refs.input) {
this.$refs.creatorSelect.$refs.input.value = limited;
}
});
}
const query = limited.trim();
if (!query || query.length <= 1) {
@@ -740,6 +769,24 @@ export default {
this.creatorSelected = [];
this.params.createUserId = '';
},
limitTeacherInput(event) {
const limited = (event && event.target && event.target.value ? event.target.value : '').slice(0, 50);
if (event && event.target && event.target.value !== limited) {
event.target.value = limited;
}
if (this.$refs.teacherSelect) {
this.$refs.teacherSelect.query = limited;
}
},
limitCreatorInput(event) {
const limited = (event && event.target && event.target.value ? event.target.value : '').slice(0, 50);
if (event && event.target && event.target.value !== limited) {
event.target.value = limited;
}
if (this.$refs.creatorSelect) {
this.$refs.creatorSelect.query = limited;
}
},
handleTopSort() {
if (this.$refs.topSorter) {
this.$refs.topSorter.open();
@@ -817,7 +864,7 @@ export default {
const hasStart = !!this.params.learningTimeStart;
const hasEnd = !!this.params.learningTimeEnd;
if ((hasStart && !hasEnd) || (!hasStart && hasEnd)) {
this.$message.warning('请选择完整的培训时间范围');
this.$showMessage('请选择完整的培训时间范围', 'warning');
return false;
}
return true;
@@ -1004,7 +1051,7 @@ export default {
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (error) {
this.$message.error(error.message || '导出失败');
this.$showMessage(error.message || '导出失败', 'error');
} finally {
this.exportLoading = false;
}
@@ -1032,30 +1079,21 @@ export default {
// console.log('fa')
apiCourse.setTop(params).then(res => {
if (res.status === 200 && res.result === true) {
this.$message.success('置顶成功!')
this.$showMessage('置顶成功!', 'success')
this.searchData();
} else if (res.status === 500) {
this.$message({
type: 'error',
message: '已置顶10条课程若需继续置顶请对部分课程执行取消置顶操作'
});
this.$showMessage('已置顶10条课程若需继续置顶请对部分课程执行取消置顶操作', 'error');
} else {
this.$message({
type: 'error',
message: res.message
});
this.$showMessage(res.message, 'error');
}
})
} else if (row.isTop == true) {
apiCourse.setTop(params).then(res => {
if (res.status === 200 && res.result === true) {
this.$message.success('取消成功!')
this.$showMessage('取消成功!', 'success')
this.searchData();
} else {
this.$message({
type: 'error',
message: res.message
});
this.$showMessage(res.message, 'error');
}
})
}
@@ -1077,13 +1115,13 @@ export default {
};
apiCourse.copyCourse(reqdata).then(rs => {
if (rs.status === 200) {
this.$message({ type: 'success', message: '复制成功', duration: 5000 });
this.$showMessage('复制成功', 'success');
this.searchData();
} else {
this.$message({ type: 'error', message: rs.message || '复制失败', duration: 5000 });
this.$showMessage(rs.message || '复制失败', 'error');
}
}).catch(() => {
this.$message({ type: 'error', message: '复制失败', duration: 5000 });
this.$showMessage('复制失败', 'error');
});
}).catch(() => { });
},
@@ -1097,13 +1135,13 @@ export default {
}).then(() => {
apiCourse.revokeSubmit(row.id).then((res) => {
if (res.status === 200 && res.result) {
this.$message({ type: 'success', message: '撤回成功', duration: 5000 });
this.$showMessage('撤回成功', 'success');
this.searchData();
} else {
this.$message({ type: 'error', message: res.message || '撤回失败', duration: 5000 });
this.$showMessage(res.message || '撤回失败', 'error');
}
}).catch(() => {
this.$message({ type: 'error', message: '撤回失败', duration: 5000 });
this.$showMessage('撤回失败', 'error');
});
}).catch(() => { });
},
@@ -1158,15 +1196,15 @@ export default {
}
apiCourse.audit(params).then(res => {
if (res.status === 200) {
this.$message.success('操作成功!');
this.$showMessage('操作成功!', 'success');
this.dialogVisible = false;
this.searchData();
} else {
this.$message.error(res.message);
this.$showMessage(res.message, 'error');
}
})
} else {
this.$message.warning('暂未开放!');
this.$showMessage('暂未开放!', 'warning');
}
},
@@ -1199,13 +1237,13 @@ export default {
try {
const { status } = await apiCourse.setEnabled(params);
if (status === 200) {
this.$message({ type: 'success', message: `${actionText}成功`, duration: 5000 });
this.$showMessage(`${actionText}成功`, 'success');
row.enabled = nextEnabled;
} else {
this.$message({ type: 'error', message: `${actionText}失败`, duration: 5000 });
this.$showMessage(`${actionText}失败`, 'error');
}
} catch (error) {
this.$message({ type: 'error', message: `${actionText}失败`, duration: 5000 });
this.$showMessage(`${actionText}失败`, 'error');
}
},
// 课程查询
@@ -1225,11 +1263,11 @@ export default {
this.page.count = rs.result.count;
this.page.pageSize = rs.result.pageSize;
} else {
return this.$message.error(rs.message);
return this.$showMessage(rs.message, 'error');
}
}).catch(err => {
console.error('查询课程列表失败:', err);
this.$message.error('查询失败,请稍后重试');
this.$showMessage('查询失败,请稍后重试', 'error');
});
},
@@ -1253,7 +1291,7 @@ export default {
},
viewTopic(row) {
if (row.status == 1) {
return this.$message.warning('请提交课程再预览!')
return this.$showMessage('请提交课程再预览!', 'warning')
}
this.examin = {};
this.examin.detailType = row.type;
@@ -1311,7 +1349,7 @@ export default {
if (!ele) return;
ele.select();
document.execCommand('Copy');
this.$message.success('复制成功');
this.$showMessage('复制成功', 'success');
},
downloadQrcode() {
const container = document.getElementById('qrcode');
@@ -1462,10 +1500,10 @@ export default {
// } else {
// item.isTop = true;
// }
// this.$message({ message: msg, type: 'success', offset: 50 });
// this.$showMessage('xxx', 'success');
// },
delItem(row) {
// this.$message({ type: 'success',customClass: 'custom-message-dialog', message: '删除成功', duration: 10000000 });
// this.$showMessage('删除成功', 'success');
// return false
this.$confirm(`<i class="el-icon-warning-outline"></i>确认删除${row.name}吗?`, '删除确认', {
confirmButtonText: '确定',
@@ -1483,7 +1521,7 @@ export default {
// {id:课程id,多个使用逗号分隔,Boolean erasable 是否物理删除,title:课程的名称, remark 备注}
const { status } = await apiCourse.del(params);
if (status === 200) {
this.$message({ type: 'success', message: '删除成功', duration: 5000 }); //只是之前发布过的课程删除才可
this.$showMessage('删除成功', 'success'); //只是之前发布过的课程删除才可
// if(!row.erasable){
// let event = {
// key: "CourseDelete",//被管理员删除
@@ -1503,11 +1541,11 @@ export default {
this.searchData();
}
} catch (error) {
this.$message({ type: 'error', message: '删除失败', duration: 5000 });
this.$showMessage('删除失败', 'error');
}
})
.catch((err) => {
// this.$message({ type: 'info', message: '已取消删除', duration: 5000 });
// this.$showMessage('已取消删除', 'info');
});
},
showAddCatalogZhang(bal) {
@@ -1516,6 +1554,64 @@ export default {
saveNewCatalogZhang() {
this.catalogs.addNewZhang = false;
},
handleAction(key, row) {
switch (key) {
case 'edit':
return this.editCurriculum(row);
case 'qrcode':
return this.showQrimage(row);
case 'manage':
return this.showManageStudy(row);
case 'withdraw':
return this.withdraw(row);
case 'delete':
return this.delItem(row);
case 'copy':
return this.copyCourse(row);
case 'toggleEnable':
return this.isDisable(row);
case 'toggleTop':
return this.setTop(row);
default:
return;
}
},
buildActions(row) {
const actions = [];
// 优先级按原有展示顺序
if (row.isPermission && row.status != 2) {
actions.push({ key: 'edit', label: '编辑', className: 'action-link--primary' });
}
if (this.showSetTopFeature && row.published) {
actions.push({ key: 'qrcode', label: '二维码', className: 'action-link--primary' });
}
if (row.isPermission && !this.forChoose && row.published) {
actions.push({ key: 'manage', label: '管理', className: 'action-link--primary' });
}
if (row.isPermission && !this.forChoose && row.status == 2) {
actions.push({ key: 'withdraw', label: '撤回', className: 'action-link--primary' });
}
if ((row.isPermission && row.status != 2 && !row.published) || (row.isPermission && !row.enabled)) {
actions.push({ key: 'delete', label: '删除', className: 'action-link--danger' });
}
// 更多里的动作
if (row.isPermission && row.published) {
actions.push({ key: 'copy', label: '复制', className: 'action-link--primary' });
actions.push({ key: 'toggleEnable', label: row.enabled ? '停用' : '启用', className: 'action-link--bold' });
if (this.showSetTopFeature) {
actions.push({ key: 'toggleTop', label: row.isTop ? '取消置顶' : '置顶', className: '' });
}
}
return actions;
},
getInlineActions(row) {
const actions = this.buildActions(row);
return actions.slice(0, 4);
},
getDropdownActions(row) {
const actions = this.buildActions(row);
return actions.length > 4 ? actions.slice(4) : [];
}
}
};
</script>
@@ -1599,8 +1695,6 @@ export default {
margin-bottom: 0;
}
.filter-row--primary .filter-actions {}
.filter-row--advanced {
margin-top: 10px;
}
@@ -2003,8 +2097,11 @@ export default {
}
.action-link--more {
color: rgba(0, 0, 0, .2);
color: #999999;
font-weight: bold;
.el-icon-arrow-down {
font-weight: bold;
}
}
.action-link--bold {
@@ -2300,10 +2397,6 @@ export default {
border-color: #4284F7;
}
}
.el-range-input {
// text-align: left;
}
.el-range-separator {
line-height: 30px;
}