|
|
<template> <div class="page-container"> <!-- 搜索区域 --> <div class="search-container"> <div class="search-form"> <div class="search-item"> <span class="form-label">账号</span> <el-input v-model="searchForm.dccode" placeholder="请输入账号" clearable style="height: 36px; width: 140px;" /> </div> <div class="search-item"> <span class="form-label">姓名</span> <el-input v-model="searchForm.dcname" placeholder="请输入姓名" clearable style="height: 36px; width: 180px;" /> </div> <div class="search-item"> <span class="form-label">地区</span> <el-select v-model="searchForm.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="search-item"> <span class="form-label">注册方式</span> <el-input v-model="searchForm.register_type" placeholder="请输入手机号/邮箱" clearable style="height: 36px; width: 220px;" /> </div> <div class="button-group"> <el-button type="primary" @click="search">搜索</el-button> <el-button type="danger" @click="enableAccess">开通权限</el-button> <el-button type="success" @click="exportExcel">导出Excel列表</el-button> <el-button color="#626aef" @click="exportList">查看导出列表</el-button> <el-button type="primary" @click="resetBn">重置</el-button> </div> </div> </div>
<!-- 数据 --> <el-table :data="tableData" style="width: 100%; margin-top: 20px;" header-cell-class-name="table-header" @sort-change="handleSortChange" :default-sort="{ prop: null, order: null }" class="table-rounded" :loading="tableLoading" > <el-table-column prop="id" label="序号" align="center" header-align="center" type="index" width="60"/> <el-table-column prop="dccode" label="账号" align="center" header-align="center"/> <el-table-column prop="dcname" label="姓名" align="center" header-align="center" width="150"/> <el-table-column prop="market" label="地区" align="center" header-align="center"/> <el-table-column prop="phone" label="电话" align="center" header-align="center"/> <el-table-column prop="email" label="邮箱" align="center" header-align="center" width="200"/> <el-table-column prop="created_at" label="注册时间" align="center" header-align="center" sortable="custom" width="200"/> <el-table-column prop="expire_time" label="到期时间" align="center" header-align="center" sortable="custom" width="200"/> <el-table-column label="操作" width="180" align="center" header-align="center"> <template #default="scope"> <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> <el-button type="text" @click="handleLog(scope.row.dccode)">操作日志</el-button> </template> </el-table-column> </el-table>
<!-- 分页组件 --> <div class="demo-pagination-block"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[15, 20, 50, 100]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total= "datatotal" /> </div>
<el-dialog v-model="dialogVisible" :title="addOrUpdata === 1 ? '添加权限' : '设置'" width="500px" :before-close="cancel"> <!-- 设置用户 --> <div class="form-item" v-if="addOrUpdata === 1"> <label class="form-label">设置用户</label> <el-input type="textarea" v-model="hlidsInput" rows=10 placeholder="请输入HLid...示例:HL30454647HL30454648HL30454649" /> <div class="tip">支持批量输入,每次最多1000个(手动/Excel粘贴均可)</div> </div>
<!-- 编辑回显 --> <div class="info-container" v-if="addOrUpdata === 0"> <span class="info-item">HLid:{{ hlidsInput }}</span> <span class="info-item">当前到期时间:{{ deadline.split(' ')[0] }}</span> </div>
<!-- 设置权限时间 --> <div class="form-item"> <label class="form-label">设置权限时间</label> <el-radio-group v-model="timeType" class="radio-group"> <el-radio label="expire" class="radio-item"> <span>到期时间</span> <el-date-picker v-model="expireTime" type="date" placeholder="请选择到期日期" :disabled-date="disabledDate" style="width: 220px; margin-left: 8px;" /> </el-radio> <el-radio label="delay" class="radio-item"> <span>延期时间</span> <el-input v-model.number="delayValue" type="number" style="width: 60px; margin: 0 8px;" placeholder="1" @input="handleDelayInput" /> <el-select v-model="delayUnit" placeholder="请选择" style="width: 150px;"> <el-option label="年" value="year"></el-option> <el-option label="月" value="month"></el-option> <el-option label="周" value="week"></el-option> <el-option label="日" value="day"></el-option> </el-select> </el-radio> </el-radio-group> </div>
<!-- 备注--> <div class="form-item inline-form-item"> <label class="form-label">备注</label> <el-input type="textarea" v-model="remark" rows=3 placeholder="请输入备注..." maxlength="150" show-word-limit /> </div>
<!-- 操作人 --> <div class="form-item inline-form-item"> <label class="form-label">操作人</label> <el-input v-model="operator" placeholder="请填写操作人"/> </div>
<!-- 按钮区域 --> <div class="dialog-footer"> <el-button type="default" plain @click="cancel">取消</el-button> <el-button type="primary" @click="submitForm" style="background-color: #ff0000; border-color: #ff0000;">提交</el-button> </div> </el-dialog> </div></template>
<script setup>import { ref, reactive, onMounted } from 'vue';import { ElMessage } from 'element-plus';import { marketListApi, userMListApi, exportCreateApi, exitMApi } from '../../api/userPermissions'import router from '../../router';
// token
const token = localStorage.getItem('token')
// 搜索表单
const searchForm = reactive({ dccode: '', dcname: '', market: '', register_type: ''});
// 排序参数
const sortProp = ref(null);const sortOrder = ref(null);
// 表格数据
const tableData = ref([]);const tableLoading = ref(false);const datatotal = ref(0)
// 分页参数
const currentPage = ref(1);const pageSize = ref(15);
// 地区下拉框
const regionList = ref([]);const isRegionLoading = ref(false);
// 弹框显隐控制
const dialogVisible = ref(false);
// 开通权限表单
const hlidsInput = ref(''); const timeType = ref(''); const expireTime = ref(''); const delayValue = ref(''); const delayUnit = ref('');const remark = ref(''); const operator = ref('');
// 判断开通还是编辑
const addOrUpdata = ref(0);
// 编辑回显内容
const deadline = ref('');
// 禁用当前日期之前的日期(当天0点之前的时间)
const disabledDate = (time) => { return time.getTime() < new Date().getTime() - 8.64e7;};
// 格式化日期
const formatDate = (date) => { if (!date) return ''; const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}/${month}/${day}`;};
// 校验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; } // 格式校验(HL开头+8位数字)
const hlidReg = /^DC\d{8}$/; for (const hlid of hlidList) { if (!hlidReg.test(hlid)) { ElMessage.error(`HLid格式错误:${hlid},请重新输入`); return false; } } return true;};
// 校验时间
const checkTime = () => { if (timeType.value === 'expire') { // 到期时间
// 校验不为空
if (!expireTime.value) { ElMessage.error('请选择到期时间'); return false; } } else if (timeType.value === 'delay') { // 延期时间
// 校验不为空
if (!delayValue.value || !delayUnit.value) { ElMessage.error('延期时间必须填写完整(数值+单位)'); return false; } } else { ElMessage.error('请设置权限时间'); return false; } return true;};
// 禁止为小数
const handleDelayInput = () => { if (delayValue.value !== null && delayValue.value !== undefined) { delayValue.value = Math.floor(delayValue.value); }};
// 校验备注
const checkRemark = () => { if (!remark.value.trim()) { ElMessage.error('请输入备注'); return false; } return true;};
// 提交表单
const submitForm = async () => { // 表单校验
if (!checkHlids() || !checkTime() || !checkRemark()) { return; }
try { // 组装后端要求的参数格式
const requestParams = { token: token, // HLid
hlids: hlidsInput.value.split('\n') .map(item => item.trim()) .filter(item => item) .join('\n'), // 备注
remark: remark.value.trim(), // 操作人
...(operator.value.trim() && { operator: operator.value.trim() }), // 时间参数
...(timeType.value === 'expire' ? { expire_time: formatDate(expireTime.value) } : { [delayUnit.value]: Number(delayValue.value) }) };
console.log('传给后端的参数:', requestParams);
// 调用后端接口
const res = await exitMApi(requestParams); ElMessage.success('成功添加用户权限');
// 重置表单并关闭弹框
resetForm(); dialogVisible.value = false; addOrUpdata.value = 0;
// 重新获取表格
fetchTableData(); } catch (error) { ElMessage.error('添加权限失败,请重试'); }};
// 取消表单
const cancel = () => { resetForm(); dialogVisible.value = false; addOrUpdata.value = 0;};
// 重置表单数据
const resetForm = () => { hlidsInput.value = ''; timeType.value = ''; expireTime.value = ''; delayValue.value = ''; delayUnit.value = ''; remark.value = ''; operator.value = '';};
// 获取地区列表
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; }};
// 获取表格数据
const fetchTableData = async () => { try { tableLoading.value = true; const requestParams = { token: token, dccode: searchForm.dccode, dcname: searchForm.dcname, market: searchForm.market, register_type: searchForm.register_type, sort_field: sortProp.value, sort_order: sortOrder.value, page: currentPage.value, page_size: pageSize.value }; const data = await userMListApi(requestParams); tableData.value = data.list datatotal.value = data.total } catch (error) { console.error('获取表格数据失败:', error); tableData.value = []; datatotal.value = 0 } finally { tableLoading.value = false; }};
// 组件挂载时:获取地区列表 + 初始化表格数据
onMounted(() => { fetchRegionList(); fetchTableData();});
// 搜索按钮
const search = () => { currentPage.value = 1; fetchTableData();};
// 开通权限按钮
const enableAccess = () => { dialogVisible.value = true; addOrUpdata.value = 1;};
// 导出Excel列表按钮
const exportExcel = async () => { const requestParams = { token: token, dccode: searchForm.dccode, dcname: searchForm.dcname, market: searchForm.market, register_type: searchForm.register_type, sort_field: sortProp.value, sort_order: sortOrder.value }; const data = await exportCreateApi(requestParams); if (data != '') { ElMessage.success('已导出'); } };
// 查看导出列表按钮
const exportList = () => { router.push({ path: "/userPermissions/export" });};
// 重置按钮
const resetBn = () => { searchForm.dccode = ''; searchForm.dcname = ''; searchForm.market = ''; searchForm.register_type = ''; sortProp.value = null; sortOrder.value = null; currentPage.value = 1; pageSize.value = 10; fetchTableData();};
// 编辑
const handleEdit = (row) => { dialogVisible.value = true; hlidsInput.value = row.dccode; deadline.value = row.expire_time;};
// 操作日志
const handleLog = (dccode) => { router.push({ path: "/userPermissions/logMarket", query: { dccode: dccode } });};
// 分页方法
const handleSizeChange = (val) => { pageSize.value = val; fetchTableData(); console.log(`每页 ${val} 条`);};
const handleCurrentChange = (val) => { currentPage.value = val; fetchTableData(); console.log(`当前页: ${val}`);};
// 排序事件
const handleSortChange = (sort) => { const { prop, order } = sort;
// 仅允许注册时间和到期时间排序
if (!['created_at', 'expire_time'].includes(prop)) return;
// 覆盖排序状态(实现二选一)
sortProp.value = prop; // 保存当前排序字段
sortOrder.value = order; // 保存当前排序方式
fetchTableData(); // console.log(`排序字段:${sortProp.value},排序方式:${sortOrder.value}`);
};</script>
<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; }</style>
|