You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

497 lines
18 KiB

<template>
<el-card style="margin-bottom: 0.5vh;width:82vw">
<div style="margin-bottom: 1vh">
<el-text size="large">精网号</el-text>
<el-input v-model="searchForm.jwcode" placeholder="请输入精网号" style="width: 12vw;margin-right:1vw" clearable />
<el-text size="large">所属地区:</el-text>
<el-cascader v-model="selectedMarkets" :options="marketOptions" placeholder="请选择所属地区" clearable
style="width: 12vw" @change="handleMarketChange" />
</div>
<el-col>
<el-text size="large" style="width: 80px" v-show="checkTab === 'pending'">提交时间:</el-text>
<el-text size="large" style="width: 80px" v-show="checkTab === 'reject' || checkTab === 'pass'">审核时间:</el-text>
<el-date-picker v-model="dateRange" type="datetimerange" range-separator="至" start-placeholder="开始时间"
end-placeholder="结束时间" style="width: 25vw;margin-right:1vw" @change="handleDatePickerChange"
:default-time="defaultTime" />
<el-button @click="getToday()" :type="activeTimeRange === 'today' ? 'primary' : ''">今</el-button>
<el-button @click="getYesterday()" :type="activeTimeRange === 'yesterday' ? 'primary' : ''">昨</el-button>
<el-button @click="get7Days()" :type="activeTimeRange === '7days' ? 'primary' : ''">近7天</el-button>
<el-button type="success" @click="resetSearch">重置</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-col>
</el-card>
<el-card>
<el-tabs v-model="checkTab" type="card" @tab-click="handleClick">
<el-tab-pane label="待审核" name="pending"></el-tab-pane>
<el-tab-pane label="已通过" name="pass"></el-tab-pane>
<el-tab-pane label="已驳回" name="reject"></el-tab-pane>
</el-tabs>
<div>
总条数:{{ format3(stats.num) }}条&nbsp;&nbsp;&nbsp;&nbsp;
总金豆数:{{ format3(stats.beanNum) }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
付费金豆:{{ format3(stats.permanentBean) }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
免费金豆:{{ format3(stats.freeBean) }}金豆
</div>
<el-table :data="tableData" height="55vh" @sort-change="handleSortChange">
<el-table-column type="index" label="序号" width="80">
<template #default="scope">
{{ scope.$index + 1 + (pagination.pageNum - 1) * pagination.pageSize }}
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120" show-overflow-tooltip />
<el-table-column prop="jwcode" label="精网号" width="120" />
<el-table-column prop="market" label="所属地区" width="120" />
<el-table-column prop="permanentBean" label="付费金豆" width="120" sortable="custom" />
<el-table-column prop="freeBean" label="免费金豆" width="120" sortable="custom" />
<el-table-column prop="remark" label="备注" width="150" show-overflow-tooltip />
<el-table-column prop="submitName" label="提交人" width="120" />
<el-table-column v-if="checkTab === 'reject'" prop="reason" label="驳回理由" width="120" show-overflow-tooltip />
<el-table-column v-if="checkTab !== 'pending'" prop="auditName" label="审核人" width="120" />
<el-table-column prop="createTime" label="提交时间" width="180" sortable="custom">
<template #default="{ row }">
{{ moment(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</template>
</el-table-column>
<el-table-column v-if="checkTab !== 'pending'" prop="auditTime" label="审核时间" width="240" sortable="custom">
<template #default="{ row }">
{{ row.auditTime ? moment(row.auditTime).format('YYYY-MM-DD HH:mm:ss') : '--' }}
</template>
</el-table-column>
<el-table-column v-if="checkTab === 'pending'" fixed="right" prop="operation" label="操作" width="400px">
<template #default="scope">
<div class="operation">
<el-popconfirm title="确定要通过此条记录吗?" @confirm="handleApprove(scope.row)">
<template #reference>
<el-button :disabled="clicked || cancelClicked" type="primary" text>
通过
</el-button>
</template>
<template #actions="{ confirm }">
<el-button size="small">取消</el-button>
<el-button type="primary" size="small" :disabled="clicked" @click="confirm">
确认
</el-button>
</template>
</el-popconfirm>
<el-button :disabled="clicked || cancelClicked" type="primary" text @click="showRejectDialog(scope.row)">
驳回
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination style="margin-top:20px" v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="stats.num"
@size-change="handlePageSizeChange" @current-change="handleCurrentChange"></el-pagination>
</el-card>
<el-dialog v-model="rejectVisible" title="驳回理由" width="500px">
<el-form>
<el-form-item label="驳回理由" required>
<el-input v-model="reason" type="textarea" :rows="4" placeholder="请输入驳回理由" maxlength="200" show-word-limit />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="rejectVisible = false">取消</el-button>
<el-button type="primary" @click="handleReject()">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import API from '@/util/http.js'
import moment from 'moment'
import { useAdminStore } from "@/store/index.js";
import { storeToRefs } from "pinia";
import _ from 'lodash'
const defaultTime = [
new Date(2000, 1, 1, 0, 0, 0),
new Date(2000, 2, 1, 23, 59, 59),
]
const adminStore = useAdminStore();
const { adminData, menuTree } = storeToRefs(adminStore);
import { permissionMapping, findMenuById } from "@/utils/menuTreePermission.js"
import dayjs from "dayjs";
const tableData = ref([])
const marketOptions = ref("")
const dateRange = ref([])
const activeTimeRange = ref('')
const sortField = ref('')
const sortOrder = ref('')
const checkTab = ref('pending')
const rejectVisible = ref(false)
const reason = ref('')
const rejectRow = ref({
id: null
})// 驳回行数据
// 操作权限(金豆审核相关,与充值权限格式对齐)
const hasbeanWait = ref(false) // 金豆审核待审核(对应beanWait:42)
const hasbeanThrough = ref(false) // 金豆审核已通过(对应beanThrough:43)
const hasbeanReject = ref(false) // 金豆审核已驳回(对应beanReject:44)
const hasbeanWaitShow = ref(false) // 金豆审核待审核查看(对应beanWaitShow:45)
const hasbeanWaitThough = ref(false) // 金豆审核通过(对应beanWaitThough:46)
const hasbeanWaitReject = ref(false) // 金豆审核驳回(对应beanWaitReject:47)
// 初始化权限状态(补充金豆审核权限,与充值权限初始化逻辑并列)
const initPermissions = () => {
if (!menuTree.value || !menuTree.value.length) return;
// 2. 金豆审核相关权限初始化(新增,与充值权限结构一致)
hasbeanWait.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanWait);
hasbeanThrough.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanThrough);
hasbeanReject.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanReject);
hasbeanWaitShow.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanWaitShow);
hasbeanWaitThough.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanWaitThough);
hasbeanWaitReject.value = hasMenuPermission(menuTree.value, permissionMapping.hasbeanWaitReject);
};
const clicked = ref(false)
// 状态常量
const STATUS = {
PENDING: 0, // 待审核
APPROVED: 1, // 通过
REJECTED: 2 // 驳回
}
const cancelClicked = ref(false)
// 存储地区选择变化
const selectedMarkets = ref("")
const searchForm = ref({
jwcode: '',
market: '',
createStartTime: '',
createEndTime: '',
status: STATUS.PENDING,
auditStartTime: '',
auditEndTime: ''
})
const pagination = ref({
pageNum: 1,
pageSize: 50
})
// 合计数
const stats = ref({
num: 0,
beanNum: 0,
permanentBean: 0,
freeBean: 0
})
const handleSortChange = (column) => {
if (column.prop === 'permanentBean') {
sortField.value = 'permanentBean'
} else if (column.prop === 'freeBean') {
sortField.value = 'freeBean'
} else if (column.prop === 'createTime') {
sortField.value = 'createTime'
} else if (column.prop === 'auditTime') {
sortField.value = 'auditTime'
} else {
sortField.value = ''
}
sortOrder.value = column.order === 'ascending' ? 'ASC' : 'DESC'
console.log('排序字段:', sortField.value)
console.log('排序方式:', sortOrder.value)
get()
}
const handleSearch = async function () {
trimJwCode()
if (searchForm.value.jwcode) {
const numRef = /^\d{1,9}$/;
if (!numRef.test(searchForm.value.jwcode)) {
ElMessage.error('请检查精网号格式')
return
}
}
await get()
await getStats()
}
const get = async function () {
if (findMenuById(menuTree.value, permissionMapping.View_Golden_Bean_Recharge_Audit)) {
try {
if (dateRange.value && dateRange.value.length === 2) {
if (checkTab.value === 'pending') {
searchForm.value.createStartTime = moment(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss')
searchForm.value.createEndTime = moment(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
} else {
searchForm.value.auditStartTime = moment(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss')
searchForm.value.auditEndTime = moment(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
}
} else {
searchForm.value.createStartTime = ''
searchForm.value.createEndTime = ''
}
if(checkTab.value === 'pending'){
sortField.value = 'createTime'
sortOrder.value = 'desc'
}else{
sortField.value = 'auditTime'
sortOrder.value = 'desc'
}
const params = {
pageNum: pagination.value.pageNum,//页码
pageSize: pagination.value.pageSize,//页面大小
beanAuditInfo: {
jwcode: searchForm.value.jwcode,
status: searchForm.value.status,
market: searchForm.value.market,
createStartTime: searchForm.value.createStartTime,
createEndTime: searchForm.value.createEndTime,
auditStartTime: searchForm.value.auditStartTime,
auditEndTime: searchForm.value.auditEndTime,
sortField: sortField.value,
sortOrder: sortOrder.value
}
}
console.log('看看传给后端的参数:', params)
const res = await API({ url: '/beanAudit/selectBy', data: params })
tableData.value = res.data.list || []
} catch (error) {
console.error('获取数据失败', error)
}
} else {
ElMessage.error('无此权限')
}
}
const getStats = async () => {
if (findMenuById(menuTree.value, permissionMapping.View_Golden_Bean_Recharge_Audit)) {
try {
const params = {
jwcode: searchForm.value.jwcode,
status: searchForm.value.status,
market: searchForm.value.market,
createStartTime: searchForm.value.createStartTime,
createEndTime: searchForm.value.createEndTime,
auditStartTime: searchForm.value.auditStartTime,
auditEndTime: searchForm.value.auditEndTime
}
const res = await API({
url: '/beanAudit/statsBean',
data: params
})
stats.value.num = res.data.num
stats.value.permanentBean = res.data.permanentBean
stats.value.freeBean = res.data.freeBean
stats.value.beanNum = res.data.beanNum
console.log('see see stats和搜索对象', stats.value, params)
} catch (error) {
console.log('请求失败', error)
}
} else {
ElMessage.error('无此权限')
}
}
// 处理通过操作
const handleApprove = async (row) => {
clicked.value = true
if (findMenuById(menuTree.value, permissionMapping.Golden_Bean_Recharge_Approval)) {
try {
const params = {
id: row.id,
auditName: adminData.value.adminName
}
await API({ url: '/beanAudit/status1', data: params })
ElMessage.success('审核通过成功')
await get()
clicked.value = false
await getStats()
} catch (error) {
console.error('审核通过失败', error)
ElMessage.error('操作失败')
}
} else {
ElMessage.error('无此权限')
clicked.value = false
}
}
// 处理驳回操作
const handleReject = async () => {
cancelClicked.value = true
if (findMenuById(menuTree.value, permissionMapping.Golden_Bean_Recharge_Approval)) {
if (!reason.value.trim()) {
ElMessage.warning('请输入驳回理由')
return
}
try {
const params = {
id: rejectRow.value.id,
auditName: adminData.value.adminName,
reason: reason.value
}
await API({ url: '/beanAudit/status2', data: params })
ElMessage.success('驳回成功')
rejectVisible.value = false
await get()
cancelClicked.value = false
await getStats()
} catch (error) {
console.error('驳回失败', error)
ElMessage.error('操作失败')
}
} else {
ElMessage.error('无此权限')
cancelClicked.value = false
}
}
const getToday = async function () {
const today = dayjs()
const startTime = today.startOf('day').format('YYYY-MM-DD HH:mm:ss')
const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = 'today'
await get()
await getStats()
}
const getYesterday = async function () {
const today = dayjs()
const startTime = today.subtract(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
const endTime = today.subtract(1, 'day').endOf('day').format('YYYY-MM-DD HH:mm:ss')
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = 'yesterday'
await get()
await getStats()
}
const get7Days = async function () {
const today = dayjs()
const startTime = today.subtract(6, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = '7days'
await get()
await getStats()
}
const resetSearch = async function () {
const status = searchForm.value.status;
searchForm.value = {
jwcode: '',
market: '',
createStartTime: '',
createEndTime: '',
status: status,
auditStartTime: '',
auditEndTime: ''
}
selectedMarkets.value = []
dateRange.value = []
activeTimeRange.value = ''
await get()
await getStats()
}
const handleClick = async function (tab) {
checkTab.value = tab.props.name
if (tab.props.name === 'pending') {
adminWait()
} else if (tab.props.name === 'pass') {
adminPass()
} else if (tab.props.name === 'reject') {
adminReject()
}
}
// 待审核
const adminWait = async function () {
checkTab.value = 'pending'
searchForm.value.status = STATUS.PENDING
await get()
await getStats()
console.log('切换页面后:', checkTab.value, sortField.value, sortOrder.value)
}
// 已通过
const adminPass = async function () {
checkTab.value = 'pass'
searchForm.value.status = STATUS.APPROVED
await get()
await getStats()
console.log('切换页面后:', checkTab.value, sortField.value, sortOrder.value)
}
// 已驳回
const adminReject = async function () {
checkTab.value = 'reject'
searchForm.value.status = STATUS.REJECTED
await get()
await getStats()
console.log('切换页面后:', checkTab.value, sortField.value, sortOrder.value)
}
const handleMarketChange = (value) => {
if (value && value.length > 0) {
searchForm.value.market = value[value.length - 1]
} else {
searchForm.value.market = ''
}
}
const handleDatePickerChange = () => {
activeTimeRange.value = ''
}
const handlePageSizeChange = function (val) {
pagination.value.pageSize = val
get()
}
const handleCurrentChange = function (val) {
pagination.value.pageNum = val
get()
}
const format3 = (num) => {
// 每三位添加逗号
return num.toLocaleString('en-US')
}
const throttledHandleApprove = _.throttle(handleApprove, 5000, {
trailing: false
})
const showRejectDialog = (row) => {
rejectRow.value.id = row.id
reason.value = ''
rejectVisible.value = true
}
// 获取地区,修改为级联下拉框
const getmarkets = async function () {
try {
const result = await API({
url: '/market/selectMarket',
});
console.log('请求成功', result)
// 递归转换树形结构为级联选择器需要的格式(跳过第一级节点)
const transformTree = (nodes) => {
// 直接处理第一级节点的子节点
const allChildren = nodes.flatMap(node => node.children || []);
return allChildren.map(child => {
const grandchildren = child.children && child.children.length
? transformTree([child]) // 递归处理子节点
: null;
return {
value: child.name,
label: child.name,
children: grandchildren
}
})
}
marketOptions.value = transformTree(result.data)
console.log('转换后的地区树==============', marketOptions.value)
} catch (error) {
console.log('请求失败', error)
}
}
const trimJwCode = () => {
if (searchForm.value.jwcode) {
searchForm.value.jwcode = searchForm.value.jwcode.replace(/\s/g, '');
}
}
onMounted(async () => {
getmarkets()
await get()
await getStats()
console.log("看看通信来的用户身份", adminData.value)
})
</script>
<style scoped></style>