2 changed files with 680 additions and 11 deletions
@ -1,13 +1,682 @@ |
|||
<template> |
|||
<div>22222</div> |
|||
<div> |
|||
<div class="page-container" v-show="taber == 'DeepMate'"> |
|||
<!-- 搜索区域 --> |
|||
<div class="search-container"> |
|||
<div class="search-form"> |
|||
<div class="search-item"> |
|||
<span class="form-label">账号</span> |
|||
<el-input |
|||
v-model="searchFormDM.dccode" |
|||
placeholder="请输入账号" |
|||
clearable |
|||
style="height: 36px; width: 140px;" |
|||
/> |
|||
</div> |
|||
<div class="search-item"> |
|||
<span class="form-label">姓名</span> |
|||
<el-input |
|||
v-model="searchFormDM.dcname" |
|||
placeholder="请输入姓名" |
|||
clearable |
|||
style="height: 36px; width: 180px;" |
|||
/> |
|||
</div> |
|||
<div class="search-item"> |
|||
<span class="form-label">客户类型</span> |
|||
<el-select |
|||
v-model="searchFormDM.user_role" |
|||
placeholder="请选择客户类型" |
|||
clearable |
|||
style="height: 36px; width: 160px;" |
|||
> |
|||
<el-option label="非网" value="2" /> |
|||
<el-option label="会员" value="1" /> |
|||
</el-select> |
|||
</div> |
|||
<div class="search-item"> |
|||
<span class="form-label">地区</span> |
|||
<el-select |
|||
v-model="searchFormDM.market" |
|||
placeholder="请选择地区" |
|||
clearable |
|||
style="height: 36px; width: 160px;" |
|||
:loading="isRegionLoading" |
|||
> |
|||
<el-option |
|||
v-for="region in regionList" |
|||
:key="region.id" |
|||
:label="region.text_cn" |
|||
:value="region.market" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
<div class="button-group"> |
|||
<el-button type="primary" @click="searchDM">搜索</el-button> |
|||
<el-button type="danger" @click="enableAccessDM">开通权限</el-button> |
|||
<el-button type="success" @click="exportExcelDM">导出Excel列表</el-button> |
|||
<el-button color="#626aef" @click="exportListDM">查看导出列表</el-button> |
|||
<el-button type="primary" @click="resetBnDM">重置</el-button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- tab切换 --> |
|||
<div class="tab-group"> |
|||
<button |
|||
class="tab-btn" |
|||
:class="{ active: taber === 'DeepMate' }" |
|||
@click="taber = 'DeepMate'" |
|||
> |
|||
DeepMate |
|||
</button> |
|||
<button |
|||
class="tab-btn" |
|||
:class="{ active: taber === 'DeepExplore' }" |
|||
@click="taber = 'DeepExplore'" |
|||
> |
|||
深度探索 |
|||
</button> |
|||
</div> |
|||
|
|||
<!-- 数据 --> |
|||
<el-table |
|||
:data="tableDataDM" |
|||
style="width: 100%; margin-top: 20px;" |
|||
header-cell-class-name="table-header" |
|||
@sort-change="handleSortChangeDM" |
|||
:default-sort="{ order: null }" |
|||
class="table-rounded" |
|||
:loading="tableLoadingDM" |
|||
> |
|||
<el-table-column prop="id" label="序号" align="center" header-align="center" width="60"> |
|||
<template #default="scope"> |
|||
{{ (currentPageDM - 1) * pageSizeDM + scope.$index + 1 }} |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column prop="dccode" label="账号" align="center" header-align="center"/> |
|||
<el-table-column prop="dcname" label="姓名" align="center" header-align="center"/> |
|||
<el-table-column prop="module_name" label="模块名称" align="center" header-align="center"/> |
|||
<el-table-column prop="token_num" label="token数量" align="center" header-align="center"/> |
|||
<el-table-column prop="updated_at" label="操作时间" align="center" header-align="center" sortable="custom"/> |
|||
<el-table-column label="操作" align="center" header-align="center"> |
|||
<template #default="scope"> |
|||
<el-button type="text" @click="handleEditDM(scope.row)">编辑</el-button> |
|||
<el-button type="text" @click="handleLogDM(scope.row.dccode)">操作日志</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
|
|||
<!-- 分页组件 --> |
|||
<div class="demo-pagination-block"> |
|||
<el-pagination |
|||
@size-change="handleSizeChangeDM" |
|||
@current-change="handleCurrentChangeDM" |
|||
:current-page="currentPageDM" |
|||
:page-sizes="[10, 20, 50, 100]" |
|||
:page-size="pageSizeDM" |
|||
layout="total, sizes, prev, pager, next, jumper" |
|||
:total= "datatotalDM" |
|||
/> |
|||
</div> |
|||
|
|||
<!-- 开通/编辑弹窗 --> |
|||
<el-dialog v-model="dialogVisibleDM" :title="addOrUpdataDM === 1 ? '添加权限' : '修改'" width="500px" :before-close="cancelDM"> |
|||
<!-- 设置用户 --> |
|||
<div class="form-item" v-if="addOrUpdataDM === 1"> |
|||
<label class="form-label">设置用户</label> |
|||
<el-input type="textarea" v-model="hlidsInput" rows=10 |
|||
placeholder="请输入HLid... |
|||
示例: |
|||
90048004 |
|||
90048005 |
|||
90048006" |
|||
/> |
|||
<div class="tip">支持批量输入,每次最多1000个(手动/Excel粘贴均可)</div> |
|||
</div> |
|||
|
|||
<!-- 编辑回显 --> |
|||
<div class="info-container" v-if="addOrUpdataDM === 0"> |
|||
<span class="info-item">HLid: {{ hlidsInput }}</span> |
|||
<span class="info-item">剩余次数:{{ deadtoken }}</span> |
|||
</div> |
|||
|
|||
<!-- 设置数量 --> |
|||
<div class="form-item" v-if="addOrUpdataDM === 1"> |
|||
<label class="form-label">设置用户次数</label> |
|||
<div class="count-group"> |
|||
<!-- Deep Mate:不可编辑文本框 --> |
|||
<el-input v-model="dmText" disabled style="width: 160px; margin-right: 16px;"/> |
|||
<!-- token数量:只能正整数 --> |
|||
<el-input v-model.number="token_num" type="number" style="width: 210px;" placeholder="请输入次数(只能为正)"/> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="form-item" v-if="addOrUpdataDM === 0"> |
|||
<label class="form-label">修改用户次数</label> |
|||
<div class="count-group"> |
|||
<!-- Deep Mate:不可编辑文本框 --> |
|||
<el-input v-model="dmText" disabled style="width: 160px; margin-right: 16px;"/> |
|||
<!-- token数量:支持正负整数 --> |
|||
<el-input v-model.number="token_num" type="number" style="width: 210px;" placeholder="请输入次数(可正负)"/> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 按钮区域 --> |
|||
<div class="dialog-footer"> |
|||
<el-button type="default" plain @click="cancelDM">取消</el-button> |
|||
<el-button type="primary" @click="submitFormDM" style="background-color: #ff0000; border-color: #ff0000;">提交</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, reactive, onMounted } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { marketListApi, userDMListApi, exportDeepMateApi, exitDMApi } from '../../api/userPermissions' |
|||
import router from '../../router'; |
|||
import { useRoute } from 'vue-router'; |
|||
|
|||
// token |
|||
const token = localStorage.getItem('token') |
|||
|
|||
// tab切换 |
|||
const taber = ref('DeepMate') |
|||
|
|||
// 获取路由实例 |
|||
const route = useRoute(); |
|||
|
|||
// 组件挂载时:获取地区列表 + 初始化表格数据 |
|||
onMounted(() => { |
|||
const taberQuery = route.query.taber; |
|||
const TaberValues = ["DeepMate", "DeepExplore"]; |
|||
taber.value = TaberValues.includes(String(taberQuery)) ? String(taberQuery) : "DeepMate"; |
|||
|
|||
fetchRegionList(); |
|||
DMTableData(); |
|||
}); |
|||
|
|||
// 地区下拉框 |
|||
const regionList = ref([]); |
|||
const isRegionLoading = ref(false); |
|||
|
|||
// 获取地区列表 |
|||
const fetchRegionList = async () => { |
|||
try { |
|||
isRegionLoading.value = true; |
|||
const data = await marketListApi({token: token}); |
|||
regionList.value = data.list; |
|||
} catch (error) { |
|||
console.error('获取地区列表失败:', error); |
|||
regionList.value = []; |
|||
} finally { |
|||
isRegionLoading.value = false; |
|||
} |
|||
}; |
|||
|
|||
// DeepMate搜索表单 |
|||
const searchFormDM = reactive({ |
|||
dccode: '', |
|||
dcname: '', |
|||
market: '', |
|||
user_role: '' |
|||
}); |
|||
|
|||
// DeepMate排序参数 |
|||
const sortOrderDM = ref(null); |
|||
|
|||
// DeepMate表格数据 |
|||
const tableDataDM = ref([]); |
|||
const tableLoadingDM = ref(false); |
|||
const datatotalDM = ref(0) |
|||
|
|||
// DeepMate分页参数 |
|||
const currentPageDM = ref(1); |
|||
const pageSizeDM = ref(10); |
|||
|
|||
// DeepMate获取表格数据 |
|||
const DMTableData = async () => { |
|||
try { |
|||
tableLoadingDM.value = true; |
|||
const requestParams = { |
|||
token: token, |
|||
dccode: searchFormDM.dccode, |
|||
dcname: searchFormDM.dcname, |
|||
market: searchFormDM.market, |
|||
user_role: searchFormDM.user_role, |
|||
sort_order: sortOrderDM.value, |
|||
page: currentPageDM.value, |
|||
page_size: pageSizeDM.value |
|||
}; |
|||
const data = await userDMListApi(requestParams); |
|||
tableDataDM.value = data.list |
|||
datatotalDM.value = data.total |
|||
} catch (error) { |
|||
console.error('获取表格数据失败:', error); |
|||
tableDataDM.value = []; |
|||
datatotalDM.value = 0 |
|||
} finally { |
|||
tableLoadingDM.value = false; |
|||
} |
|||
}; |
|||
|
|||
// DeepMate分页方法 |
|||
const handleSizeChangeDM = (val) => { |
|||
pageSizeDM.value = val; |
|||
DMTableData(); |
|||
console.log(`每页 ${val} 条`); |
|||
}; |
|||
|
|||
const handleCurrentChangeDM = (val) => { |
|||
currentPageDM.value = val; |
|||
DMTableData(); |
|||
console.log(`当前页: ${val}`); |
|||
}; |
|||
|
|||
// DeepMate排序事件 |
|||
const handleSortChangeDM = (sort) => { |
|||
const { order } = sort; |
|||
sortOrderDM.value = order; // 保存当前排序方式 |
|||
DMTableData(); |
|||
}; |
|||
|
|||
// DeepMate搜索按钮 |
|||
const searchDM = () => { |
|||
currentPageDM.value = 1; |
|||
DMTableData(); |
|||
}; |
|||
|
|||
// DeepMate重置按钮 |
|||
const resetBnDM = () => { |
|||
searchFormDM.dccode = ''; |
|||
searchFormDM.dcname = ''; |
|||
searchFormDM.market = ''; |
|||
searchFormDM.user_role = ''; |
|||
sortOrderDM.value = null; |
|||
currentPageDM.value = 1; |
|||
pageSizeDM.value = 10; |
|||
DMTableData(); |
|||
}; |
|||
|
|||
// DeepMate开通权限按钮 |
|||
const enableAccessDM = () => { |
|||
dialogVisibleDM.value = true; |
|||
addOrUpdataDM.value = 1; |
|||
}; |
|||
|
|||
// DeepMate导出Excel列表按钮 |
|||
const exportExcelDM = async () => { |
|||
const requestParams = { |
|||
token: token, |
|||
dccode: searchFormDM.dccode, |
|||
dcname: searchFormDM.dcname, |
|||
market: searchFormDM.market, |
|||
user_role: searchFormDM.user_role, |
|||
sort_order: sortOrderDM.value |
|||
}; |
|||
const data = await exportDeepMateApi(requestParams); |
|||
if (data != '') { |
|||
ElMessage.success('已导出'); |
|||
} |
|||
}; |
|||
|
|||
// DeepMate查看导出列表按钮 |
|||
const exportListDM = () => { |
|||
router.push({ |
|||
path: "/userPermissions/export" |
|||
}); |
|||
}; |
|||
|
|||
// 编辑按钮 |
|||
const handleEditDM = (row) => { |
|||
dialogVisibleDM.value = true; |
|||
hlidsInput.value = row.dccode; |
|||
deadtoken.value = row.token_num; |
|||
}; |
|||
|
|||
// 操作日志按钮 |
|||
const handleLogDM = (dccode) => { |
|||
router.push({ |
|||
path: "/userPermissions/logDeepMate", |
|||
query: { dccode: dccode } |
|||
}); |
|||
}; |
|||
|
|||
// DeepMate弹框显隐控制 |
|||
const dialogVisibleDM = ref(false); |
|||
|
|||
// DeepMate开通权限表单 |
|||
const hlidsInput = ref(''); |
|||
const dmText = ref('Deep Mate'); |
|||
const token_num = ref(''); |
|||
|
|||
// DeepMate编辑回显内容 |
|||
const deadtoken = ref(''); |
|||
|
|||
// DeepMate判断开通还是编辑 |
|||
const addOrUpdataDM = ref(0); |
|||
|
|||
// 校验HLid |
|||
const checkHlids = () => { |
|||
// 非空 |
|||
if (!hlidsInput.value.trim()) { |
|||
ElMessage.error('请输入HLid'); |
|||
return false; |
|||
} |
|||
// 处理输入:去空、去重,转数组 |
|||
const hlidList = hlidsInput.value.split('\n') |
|||
.map(item => item.trim()) |
|||
.filter(item => item) |
|||
.filter((item, index, self) => self.indexOf(item) === index); // 去重 |
|||
// 数量校验(最多1000个) |
|||
if (hlidList.length > 1000) { |
|||
ElMessage.error('HLid数量不能超过1000个'); |
|||
return false; |
|||
} |
|||
// 格式校验(8位数字) |
|||
const hlidReg = /^\d{8}$/; |
|||
for (const hlid of hlidList) { |
|||
if (!hlidReg.test(hlid)) { |
|||
ElMessage.error(`有HLid格式错误:${hlid},请重新输入`); |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
// 校验token数量 |
|||
const checkTokenNum = () => { |
|||
// 添加权限场景 |
|||
if (addOrUpdataDM.value === 1) { |
|||
if (token_num.value === null || token_num.value === '') { |
|||
ElMessage.error('请输入token数量'); |
|||
return false; |
|||
} |
|||
if (!Number.isInteger(token_num.value) || token_num.value <= 0) { |
|||
ElMessage.error('token数量必须为正整数'); |
|||
return false; |
|||
} |
|||
} |
|||
// 修改场景 |
|||
else if (addOrUpdataDM.value === 0) { |
|||
if (token_num.value === null || token_num.value === '') { |
|||
ElMessage.error('请输入token数量'); |
|||
return false; |
|||
} |
|||
if (!Number.isInteger(token_num.value)) { |
|||
ElMessage.error('token数量必须为整数'); |
|||
return false; |
|||
} |
|||
if (token_num.value < 0 && Math.abs(token_num.value) > deadtoken.value) { |
|||
ElMessage.error('扣除次数大于当前总次数,请重新输入次数'); |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
// 提交表单 |
|||
const submitFormDM = async () => { |
|||
// 表单校验 |
|||
if (!checkHlids() || !checkTokenNum()) { |
|||
return; |
|||
} |
|||
|
|||
try { |
|||
const requestParams = { |
|||
token: token, |
|||
// HLid |
|||
hlids: hlidsInput.value.split('\n') |
|||
.map(item => item.trim()) |
|||
.filter(item => item) |
|||
.join('\n'), |
|||
// token数量 |
|||
token_num: token_num.value |
|||
}; |
|||
console.log('传给后端的参数:', requestParams); |
|||
|
|||
// 调用后端接口 |
|||
await exitDMApi(requestParams); |
|||
ElMessage.success(addOrUpdataDM.value === 1 ? '用户次数设置成功' : '用户次数修改成功'); |
|||
|
|||
<script> |
|||
export default { |
|||
// 重置表单并关闭弹框 |
|||
resetFormDM(); |
|||
dialogVisibleDM.value = false; |
|||
addOrUpdataDM.value = 0; |
|||
|
|||
// 重新获取表格 |
|||
DMTableData(); |
|||
} catch (error) { |
|||
ElMessage.error('添加权限失败,请重试'); |
|||
} |
|||
}; |
|||
|
|||
// DeepMate取消表单 |
|||
const cancelDM = () => { |
|||
resetFormDM(); |
|||
dialogVisibleDM.value = false; |
|||
addOrUpdataDM.value = 0; |
|||
}; |
|||
|
|||
// DeepMate重置表单数据 |
|||
const resetFormDM = () => { |
|||
hlidsInput.value = ''; |
|||
token_num.value = ''; |
|||
}; |
|||
</script> |
|||
|
|||
<style> |
|||
<style scoped> |
|||
/* 父容器 */ |
|||
.page-container { |
|||
position: relative; |
|||
min-height: 600px; |
|||
} |
|||
|
|||
/* 搜索区域 */ |
|||
.search-container { |
|||
display: flex; |
|||
height: 67px; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: flex-start; |
|||
gap: 10px; |
|||
align-self: stretch; |
|||
border-radius: 8px; |
|||
background: #FEFAF9; |
|||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25); |
|||
padding: 0 15px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
/* 搜索表单 */ |
|||
.search-form { |
|||
display: flex; |
|||
align-items: center; |
|||
width: 100%; |
|||
gap: 15px; |
|||
flex-wrap: nowrap; |
|||
} |
|||
|
|||
/* 单个搜索项 */ |
|||
.search-item { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 6px; |
|||
} |
|||
|
|||
/* 搜索标签文字 */ |
|||
.form-label { |
|||
font-weight: 800 !important; |
|||
font-size: 15px; |
|||
text-align: left; |
|||
color: #333; |
|||
margin-top: 13px; |
|||
} |
|||
|
|||
/* 按钮组 */ |
|||
.button-group { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 0px !important; |
|||
margin-left: auto; |
|||
} |
|||
|
|||
/* 按钮样式 */ |
|||
.button-group .el-button { |
|||
padding: 6px 10px !important; |
|||
font-size: 14px !important; |
|||
height: 36px !important; |
|||
} |
|||
|
|||
/* 表格样式 */ |
|||
.table-rounded { |
|||
border-radius: 12px !important; |
|||
overflow: hidden !important; |
|||
border: 1px solid #e4e7ed !important; |
|||
} |
|||
|
|||
.table-header { |
|||
text-align: center !important; |
|||
font-weight: 800 !important; |
|||
font-size: 15px !important; |
|||
color: #333 !important; |
|||
background-color: #f8f9fa !important; |
|||
} |
|||
|
|||
.el-table__cell { |
|||
border-right: none !important; |
|||
border-bottom: 1px solid #e4e7ed !important; |
|||
} |
|||
|
|||
.el-table__header th.el-table__cell { |
|||
border-right: none !important; |
|||
border-bottom: 1px solid #e4e7ed !important; |
|||
} |
|||
|
|||
.el-table__row:hover .el-table__cell { |
|||
background-color: #fafafa !important; |
|||
} |
|||
|
|||
/* 分页组件样式 */ |
|||
.demo-pagination-block { |
|||
display: flex; |
|||
width: 100%; |
|||
height: 44px; |
|||
padding: 0 16px; |
|||
align-items: center; |
|||
gap: 16px; |
|||
position: absolute; |
|||
margin-top: 10px; |
|||
border-radius: 0 0 3px 3px; |
|||
border-top: 1px solid #EAEAEA; |
|||
background: #FEFBFB; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
/* 添加/修改样式 */ |
|||
.form-item { |
|||
margin-bottom: 24px; |
|||
padding-left: 20px; |
|||
padding-right: 20px; |
|||
text-align: left; |
|||
} |
|||
|
|||
.form-label { |
|||
display: block; |
|||
margin-bottom: 8px; |
|||
font-weight: 500; |
|||
} |
|||
|
|||
.radio-group { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 12px; |
|||
align-items: flex-start; |
|||
} |
|||
|
|||
.radio-item { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.radio-item span { |
|||
margin-right: 8px; |
|||
} |
|||
|
|||
.tip { |
|||
font-size: 12px; |
|||
color: #909399; |
|||
margin-top: 4px; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
gap: 16px; |
|||
margin-top: 20px; |
|||
} |
|||
|
|||
.inline-form-item { |
|||
display: flex; |
|||
align-items: flex-start; |
|||
gap: 12px; |
|||
} |
|||
|
|||
.inline-form-item .form-label { |
|||
display: inline-block; |
|||
margin-bottom: 0; |
|||
width: 60px; |
|||
text-align: left; |
|||
padding-right: 12px; |
|||
} |
|||
|
|||
.info-container { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 40px; |
|||
padding: 0 20px 18px; |
|||
color: #333; |
|||
font-size: 16px; |
|||
} |
|||
|
|||
.info-item { |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
/* Tab容器 */ |
|||
.tab-group { |
|||
display: flex; |
|||
gap: 12px; |
|||
justify-content: flex-start; |
|||
margin: 4px 0; |
|||
padding-left: 2px; |
|||
} |
|||
|
|||
/* Tab按钮 */ |
|||
.tab-btn { |
|||
width: 120px; |
|||
padding: 6px 0; |
|||
text-align: center; |
|||
border: 1px solid #ff0000; |
|||
border-radius: 4px; |
|||
background-color: #ffffff; |
|||
color: #ff0000; |
|||
font-size: 14px; |
|||
cursor: pointer; |
|||
transition: all 0.2s; |
|||
outline: none; |
|||
} |
|||
|
|||
/* Tab选中样式 */ |
|||
.tab-btn.active { |
|||
background-color: #ff0000; |
|||
color: #ffffff; |
|||
} |
|||
|
|||
/* hover效果优化 */ |
|||
.tab-btn:not(.active):hover { |
|||
background-color: #fff5f5; |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue