原portal嵌套重写

This commit is contained in:
670788339
2025-10-24 15:27:44 +08:00
parent 0394919963
commit 701c26fd33
2 changed files with 996 additions and 355 deletions

View File

@@ -0,0 +1,390 @@
<template>
<div class="u-page" style="padding-right:32px">
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white">
<el-form :inline="true" style="margin-left: 12px;" :model="pageData" class="demo-form-inline">
<el-form-item label="标签ID:" label-width="60px">
<el-input id="tag-id" placeholder="请输入标签ID" v-model="pageData.id" clearable />
</el-form-item>
<el-form-item label="标签名称:" label-width="80px">
<el-input id="tag-name" placeholder="请输入标签名称" v-model="pageData.tagName" clearable />
</el-form-item>
<el-form-item label="热点标签:" label-width="80px">
<el-select v-model="pageData.isHot" style="width: 120px;" clearable placeholder="请选择状态">
<el-option label="开启" value="true"></el-option>
<el-option label="关闭" value="false"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="getsearch" icon="el-icon-search" type="primary">查询</el-button>
<!-- 添加重置按钮 -->
<el-button @click="resetSearch" icon="el-icon-refresh">重置</el-button>
</el-form-item>
</el-form>
</div>
<div style="padding: 5px 0px 2px 12px;">
<!-- <el-checkbox label="前台公共显示"></el-checkbox>-->
<!-- <el-checkbox label="热点标签展示"></el-checkbox>-->
</div>
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white">
<el-table style="width: 96%; margin:2px 32px 10px 12px;" :data="pageData.list" border stripe
:header-cell-style="{ background: '#E9F0FF' }"
@selection-change="handleSelectionChange"
@sort-change="handleSortChange">
<el-table-column type="selection" width="80px"></el-table-column>
<el-table-column label="标签ID" width="200px" prop="id"></el-table-column>
<el-table-column label="标签名称" width="235px" prop="tagName"></el-table-column>
<el-table-column label="已关联课程" width="220px"
prop="useCount"
sortable="custom"
:sort-orders="['descending', 'ascending']"
>
<template #default="scope">
<a v-if="scope.row && scope.row.useCount > 0"
@click="showCourseByTag(`${scope.row.id}`)"
style="font-weight:bold; color: #409EFF; text-decoration: underline;">
{{ scope.row.useCount }}
</a>
<span style="font-weight:bold; color: #409EFF; text-decoration: underline;" v-else>0</span>
</template>
</el-table-column>
<el-table-column label="前台公共显示" width="220px" prop="isPublic">
<template #default="scope"><!-- 开关状态会直接修改 pageData.list 中的数据 -->
<el-switch
v-model="scope.row.isPublic"
:disabled="scope.row.isHot==1?true:false"
@change="handlePublicChange(scope.row)"
>
</el-switch>
</template>
</el-table-column>
<el-table-column label="热点标签展示" width="220px" prop="isHot">
<template #default="scope">
<el-switch
v-model="scope.row.isHot"
:disabled="scope.row.isPublic==0?true:false"
@change="handleHotChange(scope.row)"
>
</el-switch>
</template>
</el-table-column>
</el-table>
<div v-if="pageData.list.length > 0" style="text-align: center;margin-top: 50px;">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageData.pageIndex"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageData.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<!-- 标签关联课程弹窗 -->
<el-dialog custom-class="g-dialog" title="关联课程"
width="850px" top="20px"
v-model="dialogVisible"
:modal-append-to-body="true"
:append-to-body="true">
<div class="dialog-content-container">
<el-table
:data="pageData.list2"
border stripe style="width: 100%"
:header-cell-style="{ background: '#E9F0FF' }"
@sort-change="handleSortChange2">
<el-table-column label="序号" width="60px" align="center">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="关联课程名称" width="200px" prop="courseName"></el-table-column>
<el-table-column label="关联课程ID" width="100px" prop="courseId"></el-table-column>
<el-table-column label="关联人" width="80px" prop="sysCreateBy"></el-table-column>
<el-table-column label="关联时间" width="110px" prop="sysCreateTime"
:formatter="dateFormat" sortable="custom"
:sort-orders="['descending', 'ascending']"></el-table-column>
<el-table-column label="本课程绑定的其他标签" width="200px" prop="otherTags"></el-table-column>
<el-table-column label="操作" width="60px">
<template #default="scope">
<a @click="unbindCurrentTag(scope.row)"
style="font-weight:bold; color: #409EFF;">
解绑
</a>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div v-if="pageData.list2.length > 0" class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange2"
@current-change="handleCurrentChange2"
:current-page="pageData.pageIndex2"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageData.pageSize2"
layout="total, sizes, prev, pager, next, jumper"
:total="total2">
</el-pagination>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import moment from 'moment';
import apiCourseTag from '@/api/courseTag.js'
import { mapGetters } from 'vuex';
export default {
name: 'courseTagItems',
computed: {
...mapGetters(['userInfo'])
},
data() {
return {
pageData: {
pageIndex: 1,
pageIndex2: 1,
pageSize: 10,
pageSize2: 10,
list:[],
list2:[],
orderField: null,
orderAsc: null,
orderField2: null,
orderAsc2: null,
},
total: 0,
total2: 0,
dialogVisible: false,
tagId: null,
}
},
created() {
this.getCourseTagList()
},
methods: {
//重置搜索条件
resetSearch() {
this.pageData.id = '';
this.pageData.tagName = '';
this.pageData.isHot = '';
this.pageData.pageIndex = 1;
this.getCourseTagList(); // 重置后重新加载列表
},
//初始化:课程标签列表
getsearch(){
this.pageData.pageIndex = 1;
this.getCourseTagList()
},
//课程标签列表:排序
handleSortChange({ prop, order }) {
this.pageData.orderField = prop; // 当前排序字段
this.pageData.orderAsc = order === 'ascending'; // 排序方向
this.getCourseTagList(); // 重新获取数据
},
//TODO:课程标签列表:监听选中项变化(批量的设置标签公共显示|热点标签)
handleSelectionChange(selection) {
this.selectedRows = selection; // 更新选中的行数据
},
//课程标签列表:获取课程标签列表数据
getCourseTagList() {
const { pageIndex, pageSize, orderField, orderAsc } = this.pageData
let query = { pageIndex, pageSize, orderField, orderAsc}
//拼接查询条件
if (this.pageData.id) {
const { id } = this.pageData
query.id = id
}
if (this.pageData.tagName) {
const { tagName } = this.pageData
query.tagName = tagName
}
if (this.pageData.isHot) {
const { isHot } = this.pageData
query.isHot = isHot
}
apiCourseTag.portalPageList(query).then((res) => {
if (res.status == 200) {
this.total = res.result?.count || 0
this.pageData.list = res.result?.list || []
} else {
this.$message.error('获取数据失败')
}
}).catch(() => {
this.$message.error('获取数据失败')
})
},
//课程标签列表:改变标签的公共属性
async handlePublicChange(row) {
// 保存原始状态用于回滚
const originalStatus = row.isPublic;
try {
// 调用 API 更新状态
await apiCourseTag.changeTagPublic(row);
this.$message.success('更新成功');
} catch (error) {
// 发生错误时回滚状态
row.isPublic = originalStatus;
this.$message.error('更新失败:' + error.message);
}
},
//课程标签列表:改变标签的热点属性
async handleHotChange(row) {
// const isPublic=row.isPublic;
// 保存原始状态用于回滚
const originalStatus = row.isHot;
try {
// 调用 API 更新状态
await apiCourseTag.changeTagHot(row).then((res)=>{
if (res.status == 200){
this.$message.success(res.message);
}else {
row.isHot=false;
this.$message.warning(res.message);
}
});
} catch (error) {
// 发生错误时回滚状态
row.isHot = originalStatus;
this.$message.error('更新失败:' + error.message);
}
},
//课程标签列表:改变条数的回调
handleSizeChange(value) {
this.pageData.pageIndex = 1;
this.pageData.pageSize = value;
this.getCourseTagList();
},
//课程标签列表:改变页数的回调
handleCurrentChange(value) {
this.pageData.pageIndex = value;
this.getCourseTagList();
},
//标签关联的所有课程弹出框显示指定标签id关联的课程列表
showCourseByTag(tagId) {
this.tagId=tagId;
this.getCourseOfTagList(tagId);
this.dialogVisible=true;
},
//分页查询指定标签关联的所有课程
getCourseOfTagList(){
const { pageIndex2:pageIndex, pageSize2:pageSize, orderField2:orderField, orderAsc2:orderAsc } = this.pageData
let query = { pageIndex, pageSize, orderField, orderAsc }
//拼接查询条件
if (this.tagId) {
query.id = this.tagId
apiCourseTag.showCourseByTag(query).then((res) => {
if (res.status == 200) {
this.total2 = res.result.count
this.pageData.list2 = res.result.list
if (this.total2==0){
this.dialogVisible=false
this.getCourseTagList(); // 重新获取课程标签列表数据
}
}
})
.catch(() => {
this.$message.error('获取数据失败')
});
}
},
//标签关联课程列表:排序
handleSortChange2({ prop, order }) {
this.pageData.orderField2 = prop; // 当前排序字段
this.pageData.orderAsc2 = order === 'ascending'; // 排序方向
this.getCourseOfTagList(); // 重新获取数据
},
//标签关联的所有课程列表:改变条数的回调
handleSizeChange2(value) {
this.pageData.pageIndex2= 1;
this.pageData.pageSize2 = value;
this.getCourseOfTagList();
},
//标签关联的所有课程列表:改变页数的回调
handleCurrentChange2(value) {
this.pageData.pageIndex2 = value;
this.getCourseOfTagList();
},
//关联时间格式化
dateFormat(row, column) {
return row[column.property] ?
moment(row[column.property]).format('YYYY-MM-DD') : '';
},
//解除指定课程和当前标签的关联关系
unbindCurrentTag (row) {
let id = row.id;
let tagId = this.tagId;
let courseId = row.courseId;
//拼接查询条件
if (tagId && courseId) {
let params = { id, tagId, courseId }
apiCourseTag.unbindCourseTagRelation(params).then((res) => {
if (res.status == 200) {
//刷新列表
this.getCourseOfTagList(this.tagId);
}
})
.catch(() => {
this.$message.error('解绑失败!')
});
}
}
}
}
</script>
<style>
.demo-form-inline {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px; /* 间距 */
}
.demo-form-inline .el-form-item {
margin-bottom: 0; /* 消除默认底部间距 */
}
.dialog-content-container {
padding: 10px;
border: 1px solid #d9d9d9;
}
.pagination-container {
margin-top: 20px;
text-align: center;
}
.g-dialog .el-dialog__header {
background-color: #409EFF;
padding: 15px 20px;
}
.g-dialog .el-dialog__title {
color: white;
font-weight: bold;
}
.g-dialog .el-dialog__headerbtn .el-dialog__close {
color: white;
}
</style>

View File

@@ -1,390 +1,641 @@
<template> <template>
<div class="u-page" style="padding-right:32px"> <div class="tagManage">
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white"> <!-- 搜索框及按钮 -->
<el-form :inline="true" style="margin-left: 12px;" :model="pageData" class="demo-form-inline"> <div class="filter">
<el-form-item label="标签ID:" label-width="60px"> <div class="filterItems">
<el-input id="tag-id" placeholder="请输入标签ID" v-model="pageData.id" clearable /> <div class="select">
</el-form-item> <a-input
v-model:value="searchParam.id"
<el-form-item label="标签名称:" label-width="80px"> style="width: 270px; height: 40px; border-radius: 8px"
<el-input id="tag-name" placeholder="请输入标签名称" v-model="pageData.tagName" clearable /> placeholder="请输入标签ID"
</el-form-item> allowClear
showSearch
<el-form-item label="热点标签:" label-width="80px">
<el-select v-model="pageData.isHot" style="width: 120px;" clearable placeholder="请选择状态">
<el-option label="开启" value="true"></el-option>
<el-option label="关闭" value="false"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="getsearch" icon="el-icon-search" type="primary">查询</el-button>
<!-- 添加重置按钮 -->
<el-button @click="resetSearch" icon="el-icon-refresh">重置</el-button>
</el-form-item>
</el-form>
</div>
<div style="padding: 5px 0px 2px 12px;">
<!-- <el-checkbox label="前台公共显示"></el-checkbox>-->
<!-- <el-checkbox label="热点标签展示"></el-checkbox>-->
</div>
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white">
<el-table style="width: 96%; margin:2px 32px 10px 12px;" :data="pageData.list" border stripe
:header-cell-style="{ background: '#E9F0FF' }"
@selection-change="handleSelectionChange"
@sort-change="handleSortChange">
<el-table-column type="selection" width="80px"></el-table-column>
<el-table-column label="标签ID" width="200px" prop="id"></el-table-column>
<el-table-column label="标签名称" width="235px" prop="tagName"></el-table-column>
<el-table-column label="已关联课程" width="220px"
prop="useCount"
sortable="custom"
:sort-orders="['descending', 'ascending']"
> >
<template #default="scope"> </a-input>
<a v-if="scope.row && scope.row.useCount > 0" </div>
@click="showCourseByTag(`${scope.row.id}`)" <div class="select">
style="font-weight:bold; color: #409EFF; text-decoration: underline;"> <a-input
{{ scope.row.useCount }} v-model:value="searchParam.tagName"
style="width: 270px; height: 40px; border-radius: 8px"
placeholder="请输入标签名称"
allowClear
showSearch
>
</a-input>
</div>
<div class="select">
<a-select
v-model:value="searchParam.isHot"
style="width: 270px"
placeholder="请选择热点标签状态"
:options="hotOptions"
allowClear
></a-select>
</div>
<div style="display: flex; margin-bottom: 20px">
<div class="btnn btn1" @click="searchSubmit">
<div class="search"></div>
<div class="btnText">搜索</div>
</div>
<div class="btn btn2" @click="searchReset">
<div class="search"></div>
<div class="btnText">重置</div>
</div>
</div>
</div>
</div>
<!-- 表格 -->
<div style="padding: 10px 35px">
<a-table
:header-cell-style="{ 'text-align': 'center' }"
style="border: 1px solid #f2f6fe"
:columns="columns"
:data-source="tableData"
:loading="tableLoading"
:scroll="{ x: 'max-content' }"
:pagination="false"
rowKey="id"
@change="handleTableChange"
>
<template #bodyCell="{ record, column }">
<!-- 已关联课程列 -->
<template v-if="column.key === 'useCount'">
<a
v-if="record.useCount > 0"
@click="showCourseByTag(record.id)"
style="color: #4ea6ff; text-decoration: underline; cursor: pointer;"
>
{{ record.useCount }}
</a> </a>
<span style="font-weight:bold; color: #409EFF; text-decoration: underline;" v-else>0</span> <span v-else style="color: #999;">0</span>
</template> </template>
</el-table-column>
<el-table-column label="前台公共显示" width="220px" prop="isPublic"> <!-- 前台公共显示 -->
<template #default="scope"><!-- 开关状态会直接修改 pageData.list 中的数据 --> <template v-else-if="column.key === 'isPublic'">
<el-switch <a-switch
v-model="scope.row.isPublic" v-model:checked="record.isPublic"
:disabled="scope.row.isHot==1?true:false" :disabled="record.isHot"
@change="handlePublicChange(scope.row)" @change="handlePublicChange(record)"
> />
</el-switch>
</template> </template>
</el-table-column>
<el-table-column label="热点标签展示" width="220px" prop="isHot"> <!-- 热点标签展示 -->
<template #default="scope"> <template v-else-if="column.key === 'isHot'">
<el-switch <a-switch
v-model="scope.row.isHot" v-model:checked="record.isHot"
:disabled="scope.row.isPublic==0?true:false" :disabled="!record.isPublic"
@change="handleHotChange(scope.row)" @change="handleHotChange(record)"
> />
</el-switch>
</template> </template>
</el-table-column> </template>
</el-table> </a-table>
<div v-if="pageData.list.length > 0" style="text-align: center;margin-top: 50px;">
<el-pagination <div class="tableBox">
background <div class="pa">
@size-change="handleSizeChange" <a-pagination
@current-change="handleCurrentChange" v-if="tableDataTotal > 10"
:current-page="pageData.pageIndex" :showSizeChanger="false"
:page-sizes="[10, 20, 30, 40]" :showQuickJumper="true"
:page-size="pageData.pageSize" :hideOnSinglePage="true"
layout="total, sizes, prev, pager, next, jumper" :pageSize="pageSize"
:total="total" v-model:current="searchParam.pageIndex"
></el-pagination> :total="tableDataTotal"
class="pagination"
@change="changePagination"
/>
</div> </div>
</div> </div>
</div>
<!-- 标签关联课程弹窗 --> <!-- 标签关联课程弹窗 -->
<el-dialog custom-class="g-dialog" title="关联课程" <a-modal
width="850px" top="20px" v-model:visible="courseDialogVisible"
v-model="dialogVisible" :title="null"
:modal-append-to-body="true" :footer="null"
:append-to-body="true"> :closable="false"
<div class="dialog-content-container"> wrapClassName="courseDialog"
<el-table width="850px"
:data="pageData.list2" >
border stripe style="width: 100%" <div
:header-cell-style="{ background: '#E9F0FF' }" class="modalHeader"
@sort-change="handleSortChange2"> style="
<el-table-column label="序号" width="60px" align="center"> width: 100%;
<template #default="scope"> height: 68px;
{{ scope.$index + 1 }} display: flex;
</template> align-items: center;
</el-table-column> justify-content: space-between;
<el-table-column label="关联课程名称" width="200px" prop="courseName"></el-table-column> "
<el-table-column label="关联课程ID" width="100px" prop="courseId"></el-table-column> >
<el-table-column label="关联人" width="80px" prop="sysCreateBy"></el-table-column> <div class="headerLeft" style="margin-left: 32px">
<el-table-column label="关联时间" width="110px" prop="sysCreateTime" <span class="headerLeftText" style="font-size: 16px">关联课程</span>
:formatter="dateFormat" sortable="custom" </div>
:sort-orders="['descending', 'ascending']"></el-table-column> <div style="cursor: pointer; margin-right: 32px" @click="closeCourseDialog">
<el-table-column label="本课程绑定的其他标签" width="200px" prop="otherTags"></el-table-column>
<el-table-column label="操作" width="60px">
<template #default="scope">
<a @click="unbindCurrentTag(scope.row)"
style="font-weight:bold; color: #409EFF;">
解绑
</a>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div v-if="pageData.list2.length > 0" class="pagination-container">
<el-pagination
background
@size-change="handleSizeChange2"
@current-change="handleCurrentChange2"
:current-page="pageData.pageIndex2"
:page-sizes="[10, 20, 30, 40]"
:page-size="pageData.pageSize2"
layout="total, sizes, prev, pager, next, jumper"
:total="total2">
</el-pagination>
</div> </div>
</div> </div>
</el-dialog>
<div class="modalMain" style="padding: 20px;">
<a-table
:columns="courseColumns"
:data-source="courseTableData"
:loading="courseTableLoading"
:pagination="false"
:scroll="{ x: 'max-content' }"
rowKey="id"
>
<template #bodyCell="{ record, column }">
<!-- 关联时间格式化 -->
<template v-if="column.key === 'sysCreateTime'">
{{ formatDate(record.sysCreateTime) }}
</template>
<!-- 操作列 -->
<template v-else-if="column.key === 'operation'">
<a-button type="link" @click="unbindCurrentTag(record)">解绑</a-button>
</template>
</template>
</a-table>
<div class="tableBox">
<div class="pa">
<a-pagination
v-if="courseTableTotal > 10"
:showSizeChanger="false"
:showQuickJumper="true"
:hideOnSinglePage="true"
:pageSize="coursePageSize"
v-model:current="courseSearchParam.pageIndex"
:total="courseTableTotal"
class="pagination"
@change="changeCoursePagination"
/>
</div>
</div>
</div>
</a-modal>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment'; import { reactive, toRefs, ref } from "vue";
import apiCourseTag from '@/api/courseTag.js' import { message } from "ant-design-vue";
import { mapGetters } from 'vuex'; import { apiCourseTag } from "@/api/courseTag.js";
import moment from "moment";
export default { export default {
name: 'courseTagItems', name: "TagManage",
computed: { setup() {
...mapGetters(['userInfo']) const state = reactive({
}, tableLoading: false,
data() { courseTableLoading: false,
return { courseDialogVisible: false,
pageData: {
searchParam: {
pageIndex: 1, pageIndex: 1,
pageIndex2: 1,
pageSize: 10, pageSize: 10,
pageSize2: 10, id: "",
list:[], tagName: "",
list2:[], isHot: undefined
orderField: null,
orderAsc: null,
orderField2: null,
orderAsc2: null,
}, },
total: 0,
total2: 0, courseSearchParam: {
dialogVisible: false, pageIndex: 1,
tagId: null, pageSize: 10,
id: null
},
tableData: [],
courseTableData: [],
tableDataTotal: 0,
courseTableTotal: 0,
pageSize: 10,
coursePageSize: 10,
hotOptions: [
{ value: "true", label: "开启" },
{ value: "false", label: "关闭" }
]
});
const columns = ref([
{
title: "标签ID",
dataIndex: "id",
key: "id",
width: 200,
align: "center"
},
{
title: "标签名称",
dataIndex: "tagName",
key: "tagName",
width: 235,
align: "center"
},
{
title: "已关联课程",
dataIndex: "useCount",
key: "useCount",
width: 220,
align: "center",
sorter: true
},
{
title: "前台公共显示",
dataIndex: "isPublic",
key: "isPublic",
width: 220,
align: "center"
},
{
title: "热点标签展示",
dataIndex: "isHot",
key: "isHot",
width: 220,
align: "center"
} }
}, ]);
created() {
this.getCourseTagList()
},
methods: {
//重置搜索条件 const courseColumns = ref([
resetSearch() { {
this.pageData.id = ''; title: "序号",
this.pageData.tagName = ''; key: "index",
this.pageData.isHot = ''; width: 80,
this.pageData.pageIndex = 1; align: "center",
this.getCourseTagList(); // 重置后重新加载列表 customRender: ({ index }) => index + 1
}, },
{
//初始化:课程标签列表 title: "关联课程名称",
getsearch(){ dataIndex: "courseName",
this.pageData.pageIndex = 1; key: "courseName",
this.getCourseTagList() width: 200,
align: "center"
}, },
{
//课程标签列表:排序 title: "关联课程ID",
handleSortChange({ prop, order }) { dataIndex: "courseId",
this.pageData.orderField = prop; // 当前排序字段 key: "courseId",
this.pageData.orderAsc = order === 'ascending'; // 排序方向 width: 120,
this.getCourseTagList(); // 重新获取数据 align: "center"
}, },
{
//TODO:课程标签列表:监听选中项变化(批量的设置标签公共显示|热点标签) title: "关联人",
handleSelectionChange(selection) { dataIndex: "sysCreateBy",
this.selectedRows = selection; // 更新选中的行数据 key: "sysCreateBy",
width: 100,
align: "center"
}, },
{
//课程标签列表:获取课程标签列表数据 title: "关联时间",
getCourseTagList() { dataIndex: "sysCreateTime",
const { pageIndex, pageSize, orderField, orderAsc } = this.pageData key: "sysCreateTime",
let query = { pageIndex, pageSize, orderField, orderAsc} width: 150,
//拼接查询条件 align: "center",
if (this.pageData.id) { sorter: true
const { id } = this.pageData },
query.id = id {
title: "本课程绑定的其他标签",
dataIndex: "otherTags",
key: "otherTags",
width: 200,
align: "center"
},
{
title: "操作",
key: "operation",
width: 100,
align: "center"
} }
if (this.pageData.tagName) { ]);
const { tagName } = this.pageData
query.tagName = tagName // 获取标签列表
} const getTagList = async () => {
if (this.pageData.isHot) { state.tableLoading = true;
const { isHot } = this.pageData try {
query.isHot = isHot const params = {
} pageIndex: state.searchParam.pageIndex,
apiCourseTag.portalPageList(query).then((res) => { pageSize: state.searchParam.pageSize,
if (res.status == 200) { id: state.searchParam.id || undefined,
this.total = res.result?.count || 0 tagName: state.searchParam.tagName || undefined,
this.pageData.list = res.result?.list || [] isHot: state.searchParam.isHot || undefined
};
const res = await apiCourseTag.portalPageList(params);
if (res.status === 200) {
state.tableData = res.result?.list || [];
state.tableDataTotal = res.result?.count || 0;
} else { } else {
this.$message.error('获取数据失败') message.error('获取数据失败');
} }
}).catch(() => {
this.$message.error('获取数据失败')
})
},
//课程标签列表:改变标签的公共属性
async handlePublicChange(row) {
// 保存原始状态用于回滚
const originalStatus = row.isPublic;
try {
// 调用 API 更新状态
await apiCourseTag.changeTagPublic(row);
this.$message.success('更新成功');
} catch (error) { } catch (error) {
// 发生错误时回滚状态 message.error('获取数据失败');
row.isPublic = originalStatus; } finally {
this.$message.error('更新失败:' + error.message); state.tableLoading = false;
} }
}, };
//课程标签列表:改变标签的热点属性 // 搜索提交
async handleHotChange(row) { const searchSubmit = () => {
// const isPublic=row.isPublic; state.searchParam.pageIndex = 1;
// 保存原始状态用于回滚 getTagList();
const originalStatus = row.isHot; };
// 搜索重置
const searchReset = () => {
state.searchParam = {
pageIndex: 1,
pageSize: 10,
id: "",
tagName: "",
isHot: undefined
};
getTagList();
};
// 分页变化
const changePagination = (page) => {
state.searchParam.pageIndex = page;
getTagList();
};
// 表格排序变化
const handleTableChange = (pagination, filters, sorter) => {
if (sorter.field === 'useCount') {
// 处理排序逻辑
console.log('排序字段:', sorter.field, '排序方式:', sorter.order);
}
};
// 改变公共显示状态
const handlePublicChange = async (record) => {
const originalStatus = record.isPublic;
try { try {
// 调用 API 更新状态 await apiCourseTag.changeTagPublic(record);
await apiCourseTag.changeTagHot(row).then((res)=>{ message.success('更新成功');
if (res.status == 200){
this.$message.success(res.message);
}else {
row.isHot=false;
this.$message.warning(res.message);
}
});
} catch (error) { } catch (error) {
// 发生错误时回滚状态 record.isPublic = originalStatus;
row.isHot = originalStatus; message.error('更新失败');
this.$message.error('更新失败:' + error.message);
} }
}, };
//课程标签列表:改变条数的回调 // 改变热点状态
handleSizeChange(value) { const handleHotChange = async (record) => {
this.pageData.pageIndex = 1; const originalStatus = record.isHot;
this.pageData.pageSize = value; try {
this.getCourseTagList(); const res = await apiCourseTag.changeTagHot(record);
}, if (res.status === 200) {
//课程标签列表:改变页数的回调 message.success(res.message);
handleCurrentChange(value) { } else {
this.pageData.pageIndex = value; record.isHot = false;
this.getCourseTagList(); message.warning(res.message);
}, }
} catch (error) {
record.isHot = originalStatus;
message.error('更新失败');
}
};
//标签关联的所有课程弹出框显示指定标签id关联课程列表 // 显示关联课程
showCourseByTag(tagId) { const showCourseByTag = async (tagId) => {
this.tagId=tagId; state.courseDialogVisible = true;
this.getCourseOfTagList(tagId); state.courseSearchParam.id = tagId;
this.dialogVisible=true; state.courseSearchParam.pageIndex = 1;
}, await getCourseListByTag();
};
//分页查询指定标签关联的所有课程 // 获取关联课程列表
getCourseOfTagList(){ const getCourseListByTag = async () => {
const { pageIndex2:pageIndex, pageSize2:pageSize, orderField2:orderField, orderAsc2:orderAsc } = this.pageData state.courseTableLoading = true;
let query = { pageIndex, pageSize, orderField, orderAsc } try {
//拼接查询条件 const params = {
if (this.tagId) { pageIndex: state.courseSearchParam.pageIndex,
query.id = this.tagId pageSize: state.courseSearchParam.pageSize,
apiCourseTag.showCourseByTag(query).then((res) => { id: state.courseSearchParam.id
if (res.status == 200) { };
this.total2 = res.result.count
this.pageData.list2 = res.result.list
if (this.total2==0){
this.dialogVisible=false
this.getCourseTagList(); // 重新获取课程标签列表数据
}
}
})
.catch(() => {
this.$message.error('获取数据失败')
});
}
},
//标签关联课程列表:排序 const res = await apiCourseTag.showCourseByTag(params);
handleSortChange2({ prop, order }) { if (res.status === 200) {
this.pageData.orderField2 = prop; // 当前排序字段 state.courseTableData = res.result?.list || [];
this.pageData.orderAsc2 = order === 'ascending'; // 排序方向 state.courseTableTotal = res.result?.count || 0;
this.getCourseOfTagList(); // 重新获取数据
},
//标签关联的所有课程列表:改变条数的回调 if (state.courseTableTotal === 0) {
handleSizeChange2(value) { state.courseDialogVisible = false;
this.pageData.pageIndex2= 1; getTagList();
this.pageData.pageSize2 = value; }
this.getCourseOfTagList(); }
}, } catch (error) {
//标签关联的所有课程列表:改变页数的回调 message.error('获取数据失败');
handleCurrentChange2(value) { } finally {
this.pageData.pageIndex2 = value; state.courseTableLoading = false;
this.getCourseOfTagList(); }
}, };
//关联时间格式化
dateFormat(row, column) {
return row[column.property] ?
moment(row[column.property]).format('YYYY-MM-DD') : '';
},
//解除指定课程和当前标签的关联关系 // 关闭课程对话框
unbindCurrentTag (row) { const closeCourseDialog = () => {
let id = row.id; state.courseDialogVisible = false;
let tagId = this.tagId; };
let courseId = row.courseId;
//拼接查询条件 // 课程分页变化
if (tagId && courseId) { const changeCoursePagination = (page) => {
let params = { id, tagId, courseId } state.courseSearchParam.pageIndex = page;
apiCourseTag.unbindCourseTagRelation(params).then((res) => { getCourseListByTag();
if (res.status == 200) { };
//刷新列表
this.getCourseOfTagList(this.tagId); // 解绑标签
const unbindCurrentTag = async (record) => {
try {
const params = {
id: record.id,
tagId: state.courseSearchParam.id,
courseId: record.courseId
};
const res = await apiCourseTag.unbindCourseTagRelation(params);
if (res.status === 200) {
message.success('解绑成功');
getCourseListByTag();
getTagList(); // 刷新主列表
} }
}) } catch (error) {
.catch(() => { message.error('解绑失败');
this.$message.error('解绑失败!')
});
} }
};
// 日期格式化
const formatDate = (date) => {
return date ? moment(date).format('YYYY-MM-DD') : '';
};
// 初始化加载
getTagList();
return {
...toRefs(state),
columns,
courseColumns,
searchSubmit,
searchReset,
changePagination,
handleTableChange,
handlePublicChange,
handleHotChange,
showCourseByTag,
closeCourseDialog,
changeCoursePagination,
unbindCurrentTag,
formatDate
};
} }
} };
}
</script> </script>
<style> <style lang="scss" scoped>
.demo-form-inline { .tagManage {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.filter {
margin-left: 38px;
margin-right: 38px;
margin-top: 30px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.filterItems {
display: flex;
flex-wrap: wrap;
.select {
margin-right: 20px;
margin-bottom: 20px;
}
.btn {
padding: 0px 26px 0px 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex; display: flex;
align-items: center; align-items: center;
flex-wrap: wrap; justify-content: center;
gap: 10px; /* 间距 */ margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #fff;
line-height: 36px;
margin-left: 5px;
}
}
.btnn {
padding: 0px 26px 0px 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btn1 {
.search {
width: 15px;
height: 17px;
background-image: url("../../assets/images/courseManage/search0.png");
}
}
.btn2 {
.search {
width: 16px;
height: 18px;
background-image: url("../../assets/images/courseManage/reset0.png");
}
}
.btn1:active {
background: #0982ff;
}
.btn2:active {
background: #0982ff;
}
}
}
.tableBox {
margin: 20px 38px 30px;
.ant-table-thead > tr > th {
background-color: #eff4fc;
}
th {
background-color: #eff4fc !important;
text-align: center !important;
}
}
.tableBox {
padding-bottom: 20px;
.pa {
width: 100%;
display: flex;
justify-content: center;
}
}
} }
.demo-form-inline .el-form-item { .courseDialog {
margin-bottom: 0; /* 消除默认底部间距 */ .ant-modal {
} .ant-modal-body {
padding: 0;
.dialog-content-container { .modalHeader {
padding: 10px; background: linear-gradient(
border: 1px solid #d9d9d9; 0deg,
} rgba(78, 166, 255, 0) 0%,
rgba(78, 166, 255, 0.2) 100%
);
}
.pagination-container { .modalMain {
margin-top: 20px; padding: 20px;
text-align: center;
}
.g-dialog .el-dialog__header { .tableBox {
background-color: #409EFF; margin: 20px 0 0 0;
padding: 15px 20px; }
} }
}
.g-dialog .el-dialog__title { }
color: white;
font-weight: bold;
}
.g-dialog .el-dialog__headerbtn .el-dialog__close {
color: white;
} }
</style> </style>