Browse Source

合计数ok

zhangrenyuan/feature-20250728113353-金币前端三期
lihuilin 2 weeks ago
parent
commit
9ea40369e0
  1. 3
      .env.development
  2. 14
      src/router/index.js
  3. 5
      src/utils/menuTreePermission.js
  4. 403
      src/views/audit/beanAudit.vue
  5. 173
      src/views/usergold/userbean.vue

3
.env.development

@ -3,10 +3,11 @@
# VITE_API_BASE='http://18.143.76.3:10704/'
# VITE_API_BASE='http://192.168.9.52:10705/'
VITE_UPLOAD_URL=http://39.101.133.168:8828/hljw/api/aws/upload
VITE_API_BASE='http://192.168.9.28:8081/'
# VITE_API_BASE='http://192.168.9.28:8081/'
# sunjiabei
# VITE_API_BASE='http://192.168.9.28:8081/'
# VITE_API_BASE='http://192.168.5.92:8081/'
# zhangyong
# VITE_API_BASE='http://192.168.3.83:8081/'
# 李慧琳
VITE_API_BASE='http://localhost:8081/'

14
src/router/index.js

@ -52,6 +52,11 @@ const routes = [
meta: {permissionId: [13, 14]} // 对应"查看退款审核"id=13、"退款审批"id=14
},
]
},{
path: 'beanAudit',
name: "beanAudit",
component: () => import("../views/audit/beanAudit.vue"),
meta: {permissionId: [54,55]}
},
@ -229,6 +234,13 @@ const routes = [
},
]
},
{
path: 'userbean',
name: "userbean",
component: () => import("../views/usergold/userbean.vue"),
meta:{ permissionId: 45 }
},
// 权限管理
{
path: '/permissions',
@ -313,7 +325,7 @@ router.beforeEach(async (to, from, next) => {
// 获取管理员信息
let roleId = null;
console.log('adminData:', adminData)
console.log('路由的adminData:', adminData.value)
try {
roleId = adminData.value.roleId;
if (!roleId) {

5
src/utils/menuTreePermission.js

@ -51,6 +51,11 @@ export const permissionMapping = {
Recharge_Audit: 31, // 充值审核
Refund_Audit: 32, // 退款审核
Bean_Audit_Select: 54, // 查看金豆审核
Bean_Audit_Approval: 55, // 金豆审核
View_Bean_Details: 56, // 查看金豆明细
};
// 递归查找菜单中是否存在目标id

403
src/views/audit/beanAudit.vue

@ -1,11 +1,404 @@
<script setup lang="ts">
<template>
<el-card style="margin-bottom: 5px">
<el-row style="margin-bottom: 10px">
<el-col :span="6">
<el-text size="large">精网号</el-text>
<el-input v-model="searchForm.jwcode" placeholder="请输入精网号" style="width: 240px" clearable />
</el-col>
<el-col :span="6">
<el-text size="large">所属地区</el-text>
<el-select v-model="searchForm.market" placeholder="请选择" style="width: 240px" clearable>
<el-option v-for="item in marketOptions" :key="item" :label="item" :value="item" />
</el-select>
</el-col>
</el-row>
<el-row>
<el-col :span="15">
<div class="time-controls">
<div class="time-group">
<el-text size="large" style="width: 80px">充值时间</el-text>
<el-date-picker v-model="dateRange" type="datetimerange" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" style="width: 400px"
@change="handleDatePickerChange" />
<el-button @click="getToday()" style="margin-left: 10px"
:type="activeTimeRange === 'today' ? 'primary' : ''"> </el-button>
<el-button @click="getYesterday()" style="margin-left: 10px"
:type="activeTimeRange === 'yesterday' ? 'primary' : ''"> </el-button>
<el-button @click="get7Days()" style="margin-left: 10px"
:type="activeTimeRange === '7days' ? 'primary' : ''"> 近7天</el-button>
<el-button type="success" @click="resetSearch">重置</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
</div>
</div>
</el-col>
</el-row>
</el-card>
</script>
<el-card>
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="待审核" name="wait"></el-tab-pane>
<el-tab-pane label="已通过" name="pass"></el-tab-pane>
<el-tab-pane label="已驳回" name="reject"></el-tab-pane>
</el-tabs>
<template>
<div>
总条数{{ stats.num }}&nbsp;&nbsp;&nbsp;&nbsp;
总金豆数{{ stats.beanNum}}金豆&nbsp;&nbsp;&nbsp;&nbsp;
永久金豆{{ stats.permanentBean }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
免费金豆{{ stats.freeBean }}金豆
</div>
<el-table :data="tableData" height="540px" @sort-change="handleSortChange">
<el-table-column prop="id" label="序号" width="80" />
<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="scope.row.status === 1 || scope.row.status === 2" type="primary"
text>
通过
</el-button>
</template>
</el-popconfirm>
<el-button :disabled="scope.row.status === 1 || scope.row.status === 2" 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="rejectDialogVisible" 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="rejectDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleReject()">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import API from '@/util/http'
import moment from 'moment'
import { useAdminStore } from "@/store/index.js";
import { storeToRefs } from "pinia";
const adminStore = useAdminStore();
const { adminData, menuTree } = storeToRefs(adminStore);
import { permissionMapping, findMenuById } from "@/utils/menuTreePermission.js"
<style scoped>
const tableData = ref([])
const marketOptions = ref([])
const dateRange = ref<Date[]>([])
const activeTimeRange = ref('')
const activeName = ref('wait')
const sortField = ref('')
const sortOrder = ref('')
const checkTab = ref('pending')
const rejectDialogVisible = ref(false)
const reason = ref('')
const rejectRow = ref({
id:null
})//
//
const STATUS = {
PENDING: 0, //
APPROVED: 1, //
REJECTED: 2 //
}
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 showRejectDialog = (row) => {
rejectRow.value.id = row.id
reason.value = ''
rejectDialogVisible.value = true
}
const getmarkets = async () => {
try {
const result = await API({ url: '/beanConsume/getDept', data: {} })
marketOptions.value = result.data || []
} catch (error) {
console.error('获取地区列表失败', error)
}
}
const handleSortChange = (column) => {
if (column.prop === 'sumGold') {
sortField.value = 'sum_gold'
} else if (column.prop === 'permanentGold') {
sortField.value = 'permanent_gold'
} else if (column.prop === 'freeGold') {
sortField.value = 'freeGold'
} else if (column.prop === 'taskGold') {
sortField.value = 'task_gold'
} else if (column.prop === 'createTime') {
sortField.value = 'create_time'
} else if (column.prop === 'auditTime') {
sortField.value = 'audit_time'
} else {
sortField.value = ''
}
sortOrder.value = column.order === 'ascending' ? 'asc' : 'desc'
console.log('排序字段:', sortField.value)
console.log('排序方式:', sortOrder.value)
get()
}
const handleSearch = function () {
get()
getStats()
}
const get = async function () {
if (findMenuById(menuTree.value, permissionMapping.Bean_Audit_Select)) {
try {
if (dateRange.value && dateRange.value.length === 2) {
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.createStartTime = ''
searchForm.value.createEndTime = ''
}
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)
}
}
}
const getStats = async () => {
if (findMenuById(menuTree.value, permissionMapping.Bean_Audit_Select)) {
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)
}
}
}
//
const handleApprove = async (row) => {
if (findMenuById(menuTree.value, permissionMapping.Bean_Audit_Approval)) {
try {
const params = {
id: row.id,
auditName: adminData.value.name,
}
await API({ url: '/beanAudit/status1', data: params })
ElMessage.success('审核通过成功')
get()
getStats()
} catch (error) {
console.error('审核通过失败', error)
ElMessage.error('操作失败')
}
}
}
//
const handleReject = async () => {
if (findMenuById(menuTree.value, permissionMapping.Bean_Audit_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('驳回成功')
rejectDialogVisible.value = false
get()
getStats()
} catch (error) {
console.error('驳回失败', error)
ElMessage.error('操作失败')
}
}
}
const getToday = function () {
const today = new Date()
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate())
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1)
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = 'today'
get()
getStats()
}
const getYesterday = function () {
const yesterday = new Date()
yesterday.setDate(yesterday.getDate() - 1)
const startTime = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate())
const endTime = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate() + 1)
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = 'yesterday'
get()
getStats()
}
const get7Days = function () {
const today = new Date()
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 6)
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1)
dateRange.value = [startTime, endTime]
console.log('dateRange', dateRange.value)
activeTimeRange.value = '7days'
get()
getStats()
}
const resetSearch = function () {
const status = searchForm.value.status;
searchForm.value = {
jwcode: '',
market: '',
createStartTime: '',
createEndTime: '',
status: status,
auditStartTime: '',
auditEndTime: ''
}
dateRange.value = []
activeTimeRange.value = '' //
}
const handleClick = function (tab) {
activeName.value = tab.props.name
if (tab.props.name === 'wait') {
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()
}
//
const adminPass = async function () {
checkTab.value = 'pass'
searchForm.value.status = STATUS.APPROVED
await get()
await getStats()
}
//
const adminReject = async function () {
checkTab.value = 'reject'
searchForm.value.status = STATUS.REJECTED
await get()
await getStats()
}
const handleDatePickerChange = () => {
activeTimeRange.value = ''
}
const handlePageSizeChange = function (val) {
pagination.value.pageSize = val
get()
}
const handleCurrentChange = function (val) {
pagination.value.pageNum = val
get()
}
onMounted(async () => {
getmarkets()
get()
getStats()
console.log("看看通信来的用户身份", adminData.value)
})
</script>
</style>
<style scoped></style>

173
src/views/usergold/userbean.vue

@ -1,11 +1,176 @@
<script setup lang="ts">
<template>
<el-card style="margin-bottom: 20px;">
<el-text size="large">精网号</el-text>
<el-input v-model="searchObj.jwcode" placeholder="请输入精网号" style="width: 240px" clearable />
<el-text size="large" style="margin-left:20px">地区</el-text>
<el-select v-model="searchObj.dept" placeholder="请选择地区" style="width: 240px" clearable>
<el-option v-for="item in marketOptions" :key="item" :label="item" :value="item" />
</el-select>
</script>
<div style="float: right;">
<el-button type="success" @click="reset">重置</el-button>
<el-button type="primary" @click="get">查询</el-button>
</div>
</el-card>
<template>
<el-card>
<div class="stats-card">
现有金豆数{{ stats.sumBean }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
付费金豆数{{ stats.permanentBean }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
免费金豆数{{ stats.freeBean }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
消费金豆总数{{ stats.consumeSum }}金豆&nbsp;&nbsp;&nbsp;&nbsp;
</div>
<el-table :data="tableData" height="650px" @sort-change="handleSortChange" :row-style="{ height: '60px' }">
<el-table-column label="ID" style="width: 120px" prop="id" />
<el-table-column label="姓名" style="width: 120px;" prop="name" show-overflow-tooltip />
<el-table-column label="精网号" style="width: 120px;" prop="jwcode" />
<el-table-column label="所属地区" style="width: 120px;" prop="dept" />
<el-table-column label="现有金豆" style="width: 120px;" prop="beanNum" sortable="custom" />
<el-table-column label="免费金豆" style="width: 120px;" prop="freeBean" sortable="custom" />
<el-table-column label="付费金豆" style="width: 120px;" prop="buyBean" sortable="custom" />
<el-table-column label="历史消费" style="width: 120px;" prop="totalCostBean" sortable="custom" />
</el-table>
<el-pagination class="pagination" v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total" @size-change="handlePageSizeChange"
@current-change="handleCurrentChange"></el-pagination>
</el-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import API from '@/util/http'
import { useAdminStore } from "@/store/index.js";
import { storeToRefs } from "pinia";
const adminStore = useAdminStore();
const { adminData, menuTree } = storeToRefs(adminStore);
import { permissionMapping, findMenuById } from "@/utils/menuTreePermission.js"
<style scoped>
const tableData = ref([])
const marketOptions = ref([])
const searchObj = ref({
jwcode: '',
dept: '',
sortField: '',
sortOrder: ''
})
const stats = ref({
sumBean: 0,
permanentBean: 0,
freeBean: 0,
consumeSum: 0
})
const pagination = ref({
pageNum: 1,
pageSize: 50,
total: 0
})
const get = async function () {
try {
trim()
const params = {
beanUser: { //
jwcode: searchObj.value.jwcode, //
dept: searchObj.value.dept, //
sortField: searchObj.value.sortField,//
sortOrder: searchObj.value.sortOrder//
},
pageNum: pagination.value.pageNum,
pageSize: pagination.value.pageSize
}
const res = await API({
url: '/beanUser/userBean',
data: params
})
if (res.code === 200) {
tableData.value = res.data.list
pagination.value.total = res.data.total
}
} catch (error) {
console.log(error)
}
}
const getStats = async () => {
if (findMenuById(menuTree.value, permissionMapping.Bean_Audit_Select)) {
try {
const params = {
beanUser:{
jwcode: searchObj.value.jwcode,
dept: searchObj.value.dept
}
}
const res = await API({
url: '/beanUser/userBeanSum',
data: params
})
stats.value.sumBean = res.data.sumBean
stats.value.permanentBean = res.data.permanentBean
stats.value.freeBean = res.data.freeBean
stats.value.consumeSum = res.data.consumeSum
console.log('see see stats和搜索对象', stats.value, params)
} catch (error) {
console.log('请求失败', error)
}
}
}
const handleSortChange = (column) => {
if (column.prop === 'beanNum') {
searchObj.value.sortField = 'jinbi'
} else if (column.prop === 'freeBean') {
searchObj.value.sortField = 'jinbi_free'
} else if (column.prop === 'buyBean') {
searchObj.value.sortField = 'jinbi_buy'
} else if (column.prop === 'totalCostBean') {
searchObj.value.sortField = 'jinbi_cost_total'
} else {
searchObj.value.sortField = ''
}
searchObj.value.sortOrder = column.order === 'ascending' ? 'asc' : 'desc'
console.log('排序字段:', searchObj.value.sortField,'排序方式:', searchObj.value.sortOrder)
get()
}
const getmarkets = async () => {
try {
const result = await API({ url: '/beanConsume/getDept', data: {} })
marketOptions.value = result.data || []
} catch (error) {
console.error('获取地区列表失败', error)
}
}
//
const trim = () => {
if (searchObj.value.jwcode) {
searchObj.value.jwcode = searchObj.value.jwcode.replace(/\s/g, '');
}
}
const reset = function () {
searchObj.value.jwcode = ''
searchObj.value.dept = ''
}
const handlePageSizeChange = function (val) {
pagination.value.pageSize = val
get()
}
const handleCurrentChange = function (val) {
pagination.value.pageNum = val
get()
}
onMounted(() => {
get()
getmarkets()
getStats()
console.log('页面接收到的adminData:', adminData.value)
})
</script>
<style scoped>
.stats-card {
background-color: #EBEEF5;
padding: 5px;
}
</style>
Loading…
Cancel
Save