mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/fe-manage.git
synced 2025-12-07 01:46:43 +08:00
Merge remote-tracking branch '121/test1024' into test1024
This commit is contained in:
@@ -5,9 +5,9 @@ import httpUserbase from './confign'
|
||||
export const RECOMMEND_PAGE = "/systemapi/xboe/m/boe/cases/recommend/page post";
|
||||
//发起案例列表或案例管理列表
|
||||
export const isTopList = (data) => http.post('/xboe/m/boe/cases/isTopList', data, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
//下载失败数据
|
||||
export const downloadErrorData = (params) => http.get('/xboe/m/boe/cases/recommend/download', { params })
|
||||
@@ -28,11 +28,20 @@ export const caseInfoDownload = (data) => http.post('xboe/m/boe/cases/recommend/
|
||||
// 案例撤回接口
|
||||
export const rePushOrWithdraw = (data) => http.post('xboe/m/boe/cases/recommend/rePushOrWithdraw', data)
|
||||
// 案例推荐
|
||||
export const caseRecommend = (data) => http.post('/xboe/m/boe/cases/recommend/launch', data,{
|
||||
timeout:60000
|
||||
export const caseRecommend = (data) => http.post('/xboe/m/boe/cases/recommend/launch', data, {
|
||||
timeout: 60000
|
||||
})
|
||||
|
||||
//案例推荐选人的查询列表
|
||||
export const userList = (data) => httpUserbase.post('/user/list', data)
|
||||
//案例查询组织所有人数
|
||||
export const getOrgUsers = (data) => httpUserbase.post('/user/getOrgUsers', data)
|
||||
export const getOrgUsers = (data) => httpUserbase.post('/user/getOrgUsers', data)
|
||||
|
||||
// AI调用日志列表查询
|
||||
export const getAiLogList = (data) => http.post('/xboe/m/boe/caseDocumentLog/pageQuery', data)
|
||||
// 清空日志
|
||||
export const getClearLogs = (data) => http.post('/xboe/m/boe/caseDocumentLog/clearLogs', data)
|
||||
// 重试
|
||||
export const getRetry = (data) => http.post('/xboe/m/boe/caseDocumentLog/retry', data)
|
||||
|
||||
|
||||
|
||||
45
src/api/courseTag.js
Normal file
45
src/api/courseTag.js
Normal file
@@ -0,0 +1,45 @@
|
||||
/**课程标签模块的相关处理*/
|
||||
// import ajax from '@/utils/xajax.js'
|
||||
// import http from "@/api/configPublic";
|
||||
// import {getCookieForName} from "@/api/method";
|
||||
import http from "./config";
|
||||
|
||||
/**
|
||||
* 分页查询:标签列表
|
||||
*/
|
||||
// const portalPageList = (query = {}) => http.get(`/manageApi/admin/courseTag/list`, {params: query});
|
||||
export const portalPageList = (obj) => http.get('/admin/courseTag/list', {params: obj})
|
||||
|
||||
//改变标签的公共属性
|
||||
export const changeTagPublic = (id = {}) => http.post(`/admin/courseTag/changePublicStatus`, id);
|
||||
|
||||
//改变标签的热点属性
|
||||
export const changeTagHot = (id = {}) => http.post(`/admin/courseTag/changeHotStatus`, id);
|
||||
|
||||
//查询指定id的标签关联的所有课程
|
||||
export const showCourseByTag = (obj = {}) => http.get(`/admin/courseTag/showCourseByTag`, {params: obj});
|
||||
|
||||
|
||||
//解除指定id的课程和某个标签之间的关联关系
|
||||
export const unbindCourseTagRelation = (id = {}) => http.post(`/admin/courseTag/unbind`, id);
|
||||
|
||||
//编辑课程:标签模糊查询
|
||||
export const searchTags = (params = {}) => http.post(`/admin/courseTag/searchTags`, params);
|
||||
|
||||
|
||||
//编辑课程:创建标签(与当前课程关联)
|
||||
export const createTag = (params = {}) => http.post(`/admin/courseTag/createTag`, params);
|
||||
|
||||
//导出
|
||||
export const exportTagFile = (params = {}) => http.get(`/admin/courseTag/exportTag`, params);
|
||||
|
||||
/*export default {
|
||||
portalPageList,
|
||||
changeTagPublic,
|
||||
changeTagHot,
|
||||
showCourseByTag,
|
||||
unbindCourseTagRelation,
|
||||
searchTags,
|
||||
createTag,
|
||||
getHotTagList
|
||||
}*/
|
||||
BIN
src/assets/images/navleft/tag.png
Normal file
BIN
src/assets/images/navleft/tag.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
599
src/views/case/AICallLog.vue
Normal file
599
src/views/case/AICallLog.vue
Normal file
@@ -0,0 +1,599 @@
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<span style="margin-right: 10px;">案例标题</span>
|
||||
<a-input v-model:value="searchData.caseTitle" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="" />
|
||||
</div>
|
||||
<div class="select">
|
||||
<span style="margin-right: 10px;">操作类型</span>
|
||||
<a-select v-model:value="searchData.optType" style="width: 270px" placeholder="请选择课程类型" allowClear>
|
||||
<a-select-option value="create">新增</a-select-option>
|
||||
<a-select-option value="update">更改</a-select-option>
|
||||
<a-select-option value="delete">删除</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<div class="select">
|
||||
<div class="select addTimeBox">
|
||||
<span style="margin-right: 10px;">调用时间</span>
|
||||
<a-range-picker v-model:value="searchData.callTimeList" style="width: 350px" format="YYYY-MM-DD"
|
||||
valueFormat="YYYY-MM-DD" separator="至" :placeholder="[' 开始时间', ' 结束时间']" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="select">
|
||||
<span style="margin-right: 10px;">接口调用结果</span>
|
||||
<a-select v-model:value="searchData.optStatus" style="width: 270px" placeholder="请选择课程类型" allowClear>
|
||||
<a-select-option value="1">成功</a-select-option>
|
||||
<a-select-option value="2">失败</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<div class="select">
|
||||
<span style="margin-right: 10px;">业务处理结果</span>
|
||||
<a-select v-model:value="searchData.caseStatus" style="width: 270px" placeholder="请选择课程类型" allowClear>
|
||||
<a-select-option value="1">成功</a-select-option>
|
||||
<a-select-option value="2">失败</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="handleSearch">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">查询</div>
|
||||
</div>
|
||||
<div class="btn btn2" @click="handleReset" style="width: 105px">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="clear-btn">
|
||||
<a-button type="primary" @click="handleClearLog" danger ghost>清空日志</a-button>
|
||||
</div>
|
||||
<div class="tableBox">
|
||||
<a-table style="border: 1px solid #f2f6fe" :columns="column" :data-source="tableData" :loading="loading"
|
||||
:scroll="{ x: 1100 }" :pagination="false">
|
||||
<template #actions="{ record }">
|
||||
<a-space :key="record.id">
|
||||
<a-button @click="() => handleMark(record)" type="link">
|
||||
查看
|
||||
</a-button>
|
||||
<a-button @click="() => handleRetry(record)" :disabled="record.caseStatus == 1 && record.optStatus == 1"
|
||||
type="link">
|
||||
重试
|
||||
</a-button>
|
||||
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<div class="pa" style="display: flex; justify-content: flex-end; padding: 0 38px">
|
||||
<a-pagination show-quick-jumper :pageSize="pageSize" :current="pageIndex" :total="total" class="pagination"
|
||||
@change="handelChangePage" :max-tag-count="1" show-size-changer />
|
||||
</div>
|
||||
<a-modal v-model:visible="markShow" :footer="null" width="40%" title="查看详细报文">
|
||||
<div class="markContent">
|
||||
<p>{{ resContent }}</p>
|
||||
<p>{{ reqContent }}</p>
|
||||
</div>
|
||||
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="jsx">
|
||||
import { defineComponent, onMounted, reactive, toRefs } from "vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { getAiLogList, getClearLogs, getRetry } from "@/api/case";
|
||||
import {message} from "ant-design-vue";
|
||||
import { get } from "jquery";
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
searchData: {
|
||||
caseTitle: "",
|
||||
optType: "",
|
||||
optStatus: "",
|
||||
caseStatus: "",
|
||||
callTimeList: [],
|
||||
},
|
||||
markShow: false,
|
||||
resContent: '',
|
||||
reqContent: '',
|
||||
total: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
column: [
|
||||
{
|
||||
title: "案例标题",
|
||||
dataIndex: "caseTitle",
|
||||
key: "caseTitle",
|
||||
width: "10%",
|
||||
ellipsis: true,
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作类型",
|
||||
dataIndex: "optType",
|
||||
key: "optType",
|
||||
width: "10%",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "调用接口",
|
||||
dataIndex: "requestUrl",
|
||||
key: "requestUrl",
|
||||
width: "10%",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "调用时间",
|
||||
dataIndex: "optTime",
|
||||
key: "optTime",
|
||||
ellipsis: true,
|
||||
width: "15%",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "请求参数",
|
||||
dataIndex: "requestBody",
|
||||
key: "requestBody",
|
||||
width: "25%",
|
||||
ellipsis: true,
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "响应参数",
|
||||
dataIndex: "responseBody",
|
||||
key: "responseBody",
|
||||
width: "25%",
|
||||
ellipsis: true,
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "接口调用结果",
|
||||
dataIndex: "optStatus",
|
||||
key: "optStatus",
|
||||
width: "8%",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
switch (text) {
|
||||
case 1:
|
||||
return <span style={{ color: "#A5D161" }} >成功</ span>;
|
||||
case 2:
|
||||
return <span style={{ color: "#DB0F28" }}>失败</span>;
|
||||
default:
|
||||
return <span>-</span>;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "业务处理结果",
|
||||
dataIndex: "caseStatus",
|
||||
key: "caseStatus",
|
||||
width: "8%",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
switch (text) {
|
||||
case 1:
|
||||
return <span style={{ color: "#A5D161" }} >成功</ span>;
|
||||
case 2:
|
||||
return <span style={{ color: "#DB0F28" }}>失败</span>;
|
||||
default:
|
||||
return <span>-</span>;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: "10%",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
slots: { customRender: "actions" },
|
||||
},
|
||||
|
||||
],
|
||||
tableData: []
|
||||
})
|
||||
const getTableDate = async () => {
|
||||
let res = await getAiLogList({
|
||||
pageIndex: state.pageIndex,
|
||||
pageSize: state.pageSize,
|
||||
caseTitle: state.searchData.caseTitle,
|
||||
optType: state.searchData.optType,
|
||||
optStatus: state.searchData.optStatus,
|
||||
caseStatus: state.searchData.caseStatus,
|
||||
optTimeStart: state.searchData.callTimeList && state.searchData.callTimeList[0] ? state.searchData.callTimeList[0] + ' 00:00:00' : '',
|
||||
optTimeEnd: state.searchData.callTimeList && state.searchData.callTimeList[1] ? state.searchData.callTimeList[1] + ' 00:00:00' : '',
|
||||
});
|
||||
state.tableData = res.data.result.list;
|
||||
state.total = res.data.result.count;
|
||||
}
|
||||
// getTableDate()
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
state.pageIndex = 1
|
||||
// 在这里可以添加实际的搜索逻辑
|
||||
console.log('搜索参数:', state.searchData)
|
||||
getTableDate();
|
||||
};
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
state.pageIndex=1,
|
||||
state.pageSize=10,
|
||||
state.searchData = {
|
||||
caseTitle: "",
|
||||
optType: "",
|
||||
optStatus: "",
|
||||
caseStatus: "",
|
||||
callTimeList: [],
|
||||
};
|
||||
getTableDate();
|
||||
};
|
||||
// 清空日志
|
||||
function handleClearLog() {
|
||||
dialog({ content: '确定清空当前日志吗?', ok: handleClearLogOk });
|
||||
|
||||
}
|
||||
const handleClearLogOk = async () => {
|
||||
|
||||
try {
|
||||
// 这里应该调用实际的API接口
|
||||
let paramsData = {
|
||||
caseTitle: state.searchData.caseTitle,
|
||||
optType: state.searchData.optType,
|
||||
optStatus: state.searchData.optStatus,
|
||||
caseStatus: state.searchData.caseStatus,
|
||||
optTimeStart: state.searchData.callTimeList && state.searchData.callTimeList[0] ? state.searchData.callTimeList[0] + ' 00:00:00' : '',
|
||||
optTimeEnd: state.searchData.callTimeList && state.searchData.callTimeList[1] ? state.searchData.callTimeList[1] + ' 00:00:00' : '',
|
||||
};
|
||||
let res = await getClearLogs(paramsData);
|
||||
console.log(res, '清空日志接口返回参数');
|
||||
if (res.data.status == 200) {
|
||||
message.success(res.data.message);
|
||||
state.pageIndex=1,
|
||||
state.pageSize=10,
|
||||
state.searchData = {
|
||||
caseTitle: "",
|
||||
optType: "",
|
||||
optStatus: "",
|
||||
caseStatus: "",
|
||||
callTimeList: [],
|
||||
};
|
||||
// 重新加载数据
|
||||
getTableDate();
|
||||
} else {
|
||||
message.error(res.data.data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
}
|
||||
}
|
||||
// 查看
|
||||
const handleMark = (record) => {
|
||||
console.log(record);
|
||||
state.markShow = true;
|
||||
state.resContent = record.requestBody;
|
||||
state.reqContent = record.responseBody;
|
||||
}
|
||||
// 重试
|
||||
function handleRetry(record) {
|
||||
dialog({ content: '确定重试当前失败请求吗?', ok: () => handleRetryOk(record) });
|
||||
}
|
||||
const handleRetryOk = async (record) => {
|
||||
try {
|
||||
let res = await getRetry({ logId: record.id });
|
||||
console.log(res, '重试接口返回参数');
|
||||
if(res.data.status == 200){
|
||||
message.success(res.data.message);
|
||||
getTableDate();
|
||||
}else{
|
||||
message.error(res.data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
//分页
|
||||
const handelChangePage = (page, pageSize) => {
|
||||
state.pageIndex = page;
|
||||
state.pageSize = pageSize;
|
||||
getTableDate();
|
||||
};
|
||||
onMounted(() => {
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleSearch,
|
||||
handleReset,
|
||||
handleMark,
|
||||
handleClearLog,
|
||||
handleRetry,
|
||||
handelChangePage,
|
||||
getTableDate
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.addTimeBox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.addTime {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
margin-left: 10px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.ant-picker {
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
// .ant-picker-range .ant-picker-active-bar {
|
||||
// margin-left: 35px;
|
||||
// }
|
||||
}
|
||||
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.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: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.btnn {
|
||||
padding: 0 26px 0 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: #fff;
|
||||
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: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("../../assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tableBox {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.pa {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.pagination {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.ant-pagination-item-link,
|
||||
.ant-pagination-item,
|
||||
.ant-select-selector,
|
||||
.ant-pagination-options-quick-jumper input {
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.unout {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.operation {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
|
||||
.fb {
|
||||
display: flex;
|
||||
margin-right: 20px;
|
||||
|
||||
.jc {
|
||||
color: #4ea6ff;
|
||||
font-size: 14px;
|
||||
margin-left: 20px;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 38px;
|
||||
|
||||
.ant-btn-background-ghost.ant-btn-dangerous {
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.markContent {
|
||||
padding: 20px;
|
||||
min-height: 400px;
|
||||
font-size: 16px;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
390
src/views/tag/PortalTagManage.vue
Normal file
390
src/views/tag/PortalTagManage.vue
Normal 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>
|
||||
1538
src/views/tag/TagManage.vue
Normal file
1538
src/views/tag/TagManage.vue
Normal file
File diff suppressed because it is too large
Load Diff
52
src/views/tag/TagManage1.vue
Normal file
52
src/views/tag/TagManage1.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<!--
|
||||
* @Author: lixg lixg@dongwu-inc.com
|
||||
* @Date: 2022-11-09 09:26:26
|
||||
* @LastEditors: lixg lixg@dongwu-inc.com
|
||||
* @LastEditTime: 2022-12-11 12:01:17
|
||||
* @FilePath: /fe-manage/src/views/courselibrary/CourseManage.vue
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
-->
|
||||
<!-- 标签管理页面 -->
|
||||
<!-- sandbox="allow-forms allow-scripts allow-same-origin allow-popups" -->
|
||||
<template>
|
||||
<div class="articleManage">
|
||||
<iframe
|
||||
id="iframe"
|
||||
style="width: 100%; height: 100%"
|
||||
:src="iframeUrl + '/tag/manages'"
|
||||
frameborder="0"
|
||||
name="myframe"
|
||||
security="restricted"
|
||||
sandbox="allow-forms allow-downloads allow-scripts allow-same-origin allow-popups"
|
||||
></iframe>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { reactive, toRefs, onMounted } from "vue";
|
||||
import { iframeUrl } from "../../api/method";
|
||||
export default {
|
||||
name: "ArticleManage",
|
||||
|
||||
setup() {
|
||||
const state = reactive({
|
||||
iframeUrl: iframeUrl,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// console.log("执行");
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.articleManage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user