卡密 会员
This commit is contained in:
parent
2b2a4dd8d7
commit
68fbee5b68
20
src/api/modules/cards.js
Normal file
20
src/api/modules/cards.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import instance from '../../utils/axios.js'
|
||||||
|
|
||||||
|
const cardsApi = {
|
||||||
|
// 获取卡密列表(分页)
|
||||||
|
pageQueryCard: (params) => instance.get('/cards/pageQueryCard', { params }),
|
||||||
|
|
||||||
|
// 删除卡密
|
||||||
|
deleteCard: (id) => instance.post('/cards/delete', null, { params: { id } }),
|
||||||
|
|
||||||
|
// 获取卡密
|
||||||
|
createCardSecret: () => instance.get('http://146.56.227.42:8089/cards/createCardSecret'),
|
||||||
|
|
||||||
|
// 批量生成卡密
|
||||||
|
batchCreateCards: (data) => instance.post('/cards/batchCreate', data),
|
||||||
|
|
||||||
|
// 修改卡密状态
|
||||||
|
updateCardStatus: (data) => instance.put('/cards/updateStatus', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { cardsApi }
|
||||||
20
src/api/modules/settledMemberRecord.js
Normal file
20
src/api/modules/settledMemberRecord.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import instance from '../../utils/axios.js'
|
||||||
|
|
||||||
|
const settledMemberRecordApi = {
|
||||||
|
// 获取入驻会员开通记录列表
|
||||||
|
getSettledMemberRecordList: (params) => instance.get('/settledMember/record/list', { params }),
|
||||||
|
|
||||||
|
// 删除入驻会员开通记录
|
||||||
|
deleteSettledMemberRecord: (id) => instance.post('/settledMember/record/delete', null, { params: { id } }),
|
||||||
|
|
||||||
|
// 新增入驻会员开通记录
|
||||||
|
addSettledMemberRecord: (data) => instance.post('/settledMember/record/add', data),
|
||||||
|
|
||||||
|
// 更新入驻会员开通记录
|
||||||
|
updateSettledMemberRecord: (data) => instance.put('/settledMember/record/update', data),
|
||||||
|
|
||||||
|
// 搜索入驻会员开通记录(分页+条件)
|
||||||
|
searchSettledMemberRecord: (params) => instance.get('/settledMember/record/search', { params }),
|
||||||
|
}
|
||||||
|
|
||||||
|
export { settledMemberRecordApi }
|
||||||
@ -37,6 +37,10 @@
|
|||||||
title: '配置列表',
|
title: '配置列表',
|
||||||
path: '/settledConfig/list'
|
path: '/settledConfig/list'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '会员开通记录',
|
||||||
|
path: '/settledConfig/memberRecord'
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -67,6 +71,19 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '工具管理',
|
||||||
|
path: '/tools',
|
||||||
|
icon: DocIcon,
|
||||||
|
children: [{
|
||||||
|
title: '卡密管理',
|
||||||
|
path: '/tools/cards',
|
||||||
|
children: [{
|
||||||
|
title: '卡密列表',
|
||||||
|
path: '/tools/cards/list'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
// 更多菜单...
|
// 更多菜单...
|
||||||
])
|
])
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -18,6 +18,11 @@ const routes = [{
|
|||||||
component: () => import('@/views/SettledConfig/List.vue'),
|
component: () => import('@/views/SettledConfig/List.vue'),
|
||||||
meta: { title: '配置列表' }
|
meta: { title: '配置列表' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/SettledConfig/memberRecord',
|
||||||
|
component: () => import('@/views/SettledConfig/MemberRecord.vue'),
|
||||||
|
meta: { title: '会员开通记录' }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/user/list',
|
path: '/user/list',
|
||||||
component: () => import('@/views/User/List.vue'),
|
component: () => import('@/views/User/List.vue'),
|
||||||
@ -27,6 +32,11 @@ const routes = [{
|
|||||||
path: '/user/edit',
|
path: '/user/edit',
|
||||||
component: () => import('@/views/User/Edit.vue'),
|
component: () => import('@/views/User/Edit.vue'),
|
||||||
meta: { title: '新增用户' }
|
meta: { title: '新增用户' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tools/cards/list',
|
||||||
|
component: () => import('@/views/Tools/Cards/List.vue'),
|
||||||
|
meta: { title: '卡密列表' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
|
|||||||
@ -2,10 +2,36 @@ import axios from 'axios'
|
|||||||
// 创建 axios
|
// 创建 axios
|
||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
baseURL: '/api',
|
baseURL: '/api',
|
||||||
timeout: 5000,
|
timeout: 30000, // 增加超时时间到30秒
|
||||||
// headers: {
|
// headers: {
|
||||||
// 'Content-Type': 'multipart/form-data'
|
// 'Content-Type': 'multipart/form-data'
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
config => {
|
||||||
|
// 在发送请求之前做些什么
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
// 对请求错误做些什么
|
||||||
|
console.error('请求错误:', error)
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
response => {
|
||||||
|
// 对响应数据做点什么
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
// 对响应错误做点什么
|
||||||
|
console.error('响应错误:', error)
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
export default instance
|
export default instance
|
||||||
709
src/views/SettledConfig/MemberRecord.vue
Normal file
709
src/views/SettledConfig/MemberRecord.vue
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
<template>
|
||||||
|
<div class="list-container">
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-area">
|
||||||
|
<el-form :inline="true" :model="searchForm">
|
||||||
|
<el-form-item label="会员ID">
|
||||||
|
<el-input v-model="searchForm.userId" placeholder="请输入会员ID" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="会员名称">
|
||||||
|
<el-input v-model="searchForm.memberName" placeholder="请输入会员名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开通时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchForm.timeRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期1"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
:shortcuts="dateShortcuts"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||||
|
<el-button @click="resetSearch">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="action-bar">
|
||||||
|
<el-button type="primary" @click="handleAdd">新增</el-button>
|
||||||
|
<el-button @click="refreshData">刷新</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
style="width: 100%;"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
row-key="id"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" align="center" width="55" />
|
||||||
|
<el-table-column prop="id" align="center" label="记录ID" width="80" />
|
||||||
|
<el-table-column prop="userId" align="center" label="用户ID" width="100" />
|
||||||
|
<el-table-column prop="title" align="center" label="会员名称" width="120" />
|
||||||
|
<el-table-column prop="settledCostKey" align="center" label="入驻标识" width="150" />
|
||||||
|
<el-table-column align="center" label="到期时间" width="180">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.expirationDate) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="佣金设置" width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ getKickbackTypeText(row.kickbackType) }}:
|
||||||
|
{{ formatValue(row.kickbackValue, row.kickbackType) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="资源占用费" width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ getResourceCostTypeText(row.resourceCostType) }}:
|
||||||
|
{{ formatValue(row.resourceCostValue, row.resourceCostType) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="serviceRate" align="center" label="服务费比例" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ (row.serviceRate / 10000).toFixed(2) }}%
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="price" align="center" label="购买价格(元)" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ (row.price / 100).toFixed(2) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="state" align="center" label="状态" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="getStatusType(row.state)">{{ getStatusText(row.state) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="操作" fixed="right" width="220">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button size="small" type="primary" @click="handleEdit(row)">编辑</el-button>
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(row)"
|
||||||
|
:disabled="row.state === 0"
|
||||||
|
>删除</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="row.state === 1"
|
||||||
|
size="small"
|
||||||
|
type="warning"
|
||||||
|
@click="handleChangeStatus(row, 0)"
|
||||||
|
>停用</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="row.state === 0"
|
||||||
|
size="small"
|
||||||
|
type="success"
|
||||||
|
@click="handleChangeStatus(row, 1)"
|
||||||
|
>启用</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="pagination.current"
|
||||||
|
v-model:page-size="pagination.size"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="pagination.total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增/编辑对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
:title="dialogType === 'add' ? '新增入驻会员开通记录' : '编辑入驻会员开通记录'"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="formRules"
|
||||||
|
label-width="120px"
|
||||||
|
label-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item label="会员ID" prop="userId">
|
||||||
|
<el-input v-model="formData.userId" placeholder="请输入会员ID" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="会员名称" prop="title">
|
||||||
|
<el-input v-model="formData.title" placeholder="请输入会员名称" maxlength="20" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="配置选择" prop="settledCostConfigId">
|
||||||
|
<el-select v-model="formData.settledCostConfigId" placeholder="请选择配置" @change="handleConfigChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in configOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.title"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开通时间" prop="openTime">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.openTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择开通时间"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="到期时间" prop="expirationDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.expirationDate"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="选择到期时间"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付金额(元)" prop="price">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.price"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
:step="10"
|
||||||
|
placeholder="请输入支付金额"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="state">
|
||||||
|
<el-select v-model="formData.state" placeholder="请选择状态">
|
||||||
|
<el-option label="已停用" :value="0" />
|
||||||
|
<el-option label="已启用" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="佣金类型" prop="kickbackType">
|
||||||
|
<el-select v-model="formData.kickbackType" placeholder="请选择佣金类型">
|
||||||
|
<el-option label="预留" :value="0" />
|
||||||
|
<el-option label="提点" :value="1" />
|
||||||
|
<el-option label="固定费用" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="佣金值" prop="kickbackValue">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.kickbackValue"
|
||||||
|
:min="0"
|
||||||
|
:precision="formData.kickbackType === 1 ? 2 : 0"
|
||||||
|
:step="formData.kickbackType === 1 ? 0.01 : 1"
|
||||||
|
placeholder="请输入佣金值"
|
||||||
|
/>
|
||||||
|
<span class="form-tip">{{ formData.kickbackType === 1 ? '万分比' : '分' }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="资源占用费类型" prop="resourceCostType">
|
||||||
|
<el-select v-model="formData.resourceCostType" placeholder="请选择资源占用费类型">
|
||||||
|
<el-option label="预留" :value="0" />
|
||||||
|
<el-option label="提点" :value="1" />
|
||||||
|
<el-option label="固定费用" :value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="资源占用费值" prop="resourceCostValue">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.resourceCostValue"
|
||||||
|
:min="0"
|
||||||
|
:precision="formData.resourceCostType === 1 ? 2 : 0"
|
||||||
|
:step="formData.resourceCostType === 1 ? 0.01 : 1"
|
||||||
|
placeholder="请输入资源占用费值"
|
||||||
|
/>
|
||||||
|
<span class="form-tip">{{ formData.resourceCostType === 1 ? '万分比' : '分' }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="服务费比例" prop="serviceRate">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.serviceRate"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
:step="0.01"
|
||||||
|
placeholder="请输入服务费比例"
|
||||||
|
/>
|
||||||
|
<span class="form-tip">万分比</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="会员限制" prop="constraintJson">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.constraintJson"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入会员限制JSON格式数据"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="note">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.note"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入备注信息"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { settledMemberRecordApi } from '@/api/modules/settledMemberRecord'
|
||||||
|
import { settledCostConfigApi } from '@/api/modules/settledCostConfig'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const tableRef = ref(null)
|
||||||
|
|
||||||
|
// 多选数据
|
||||||
|
const multipleSelection = ref([])
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
userId: '',
|
||||||
|
memberName: '',
|
||||||
|
timeRange: []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 日期快捷选项
|
||||||
|
const dateShortcuts = [
|
||||||
|
{
|
||||||
|
text: '最近一周',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最近一个月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最近三个月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
size: 10,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 入驻配置选项
|
||||||
|
const configOptions = ref([])
|
||||||
|
|
||||||
|
// 对话框相关
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const dialogType = ref('add')
|
||||||
|
const formRef = ref(null)
|
||||||
|
const submitLoading = ref(false)
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formData = reactive({
|
||||||
|
id: null,
|
||||||
|
userId: '',
|
||||||
|
settledCostConfigId: null,
|
||||||
|
title: '',
|
||||||
|
settledCostKey: '',
|
||||||
|
constraintJson: '{}',
|
||||||
|
expirationDate: '',
|
||||||
|
kickbackType: 1,
|
||||||
|
kickbackValue: 0,
|
||||||
|
resourceCostType: 1,
|
||||||
|
resourceCostValue: 0,
|
||||||
|
serviceRate: 0,
|
||||||
|
price: 0,
|
||||||
|
state: 1,
|
||||||
|
note: '',
|
||||||
|
createdBy: 0,
|
||||||
|
updatedBy: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const formRules = {
|
||||||
|
userId: [
|
||||||
|
{ required: true, message: '请输入用户ID', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
settledCostConfigId: [
|
||||||
|
{ required: true, message: '请选择配置', trigger: 'change' },
|
||||||
|
],
|
||||||
|
title: [
|
||||||
|
{ required: true, message: '请输入标题', trigger: 'blur' },
|
||||||
|
{ max: 20, message: '标题长度不能超过20个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
expirationDate: [
|
||||||
|
{ required: true, message: '请选择到期时间', trigger: 'change' },
|
||||||
|
],
|
||||||
|
kickbackType: [
|
||||||
|
{ required: true, message: '请选择佣金类型', trigger: 'change' },
|
||||||
|
],
|
||||||
|
kickbackValue: [
|
||||||
|
{ required: true, message: '请输入佣金值', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
resourceCostType: [
|
||||||
|
{ required: true, message: '请选择资源占用费类型', trigger: 'change' },
|
||||||
|
],
|
||||||
|
resourceCostValue: [
|
||||||
|
{ required: true, message: '请输入资源占用费值', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
serviceRate: [
|
||||||
|
{ required: true, message: '请输入服务费比例', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
price: [
|
||||||
|
{ required: true, message: '请输入购买价格', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
state: [
|
||||||
|
{ required: true, message: '请选择状态', trigger: 'change' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData()
|
||||||
|
fetchConfigOptions()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取入驻配置选项
|
||||||
|
const fetchConfigOptions = async () => {
|
||||||
|
try {
|
||||||
|
const res = await settledCostConfigApi.getSettledCostConfigList()
|
||||||
|
console.log("res",res)
|
||||||
|
// API返回的数据已经是驼峰命名,直接使用
|
||||||
|
configOptions.value = res.data || []
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取配置选项失败:', error)
|
||||||
|
ElMessage.error('获取配置选项失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取表格数据
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// 构建请求参数
|
||||||
|
const params = {
|
||||||
|
page: pagination.current,
|
||||||
|
size: pagination.size,
|
||||||
|
userId: searchForm.userId,
|
||||||
|
memberName: searchForm.memberName
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加时间范围参数
|
||||||
|
if (searchForm.timeRange && searchForm.timeRange.length === 2) {
|
||||||
|
params.startTime = searchForm.timeRange[0]
|
||||||
|
params.endTime = searchForm.timeRange[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await settledMemberRecordApi.getSettledMemberRecordList(params)
|
||||||
|
// API返回的数据已经是驼峰命名,直接使用
|
||||||
|
tableData.value = res.data.records || []
|
||||||
|
pagination.total = res.data.total || 0
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error)
|
||||||
|
ElMessage.error('获取数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = () => {
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.current = 1 // 重置到第一页
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置搜索
|
||||||
|
const resetSearch = () => {
|
||||||
|
searchForm.userId = ''
|
||||||
|
searchForm.memberName = ''
|
||||||
|
searchForm.timeRange = []
|
||||||
|
pagination.current = 1 // 重置到第一页
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页大小变化
|
||||||
|
const handleSizeChange = (size) => {
|
||||||
|
pagination.size = size
|
||||||
|
pagination.current = 1 // 切换每页条数时,重置到第一页
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页码变化
|
||||||
|
const handleCurrentChange = (current) => {
|
||||||
|
pagination.current = current
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多选处理
|
||||||
|
const handleSelectionChange = (val) => {
|
||||||
|
multipleSelection.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增
|
||||||
|
const handleAdd = () => {
|
||||||
|
resetForm()
|
||||||
|
dialogType.value = 'add'
|
||||||
|
dialogVisible.value = true
|
||||||
|
// 设置默认开通时间为当前时间
|
||||||
|
const now = new Date()
|
||||||
|
formData.openTime = now.toISOString().substring(0, 19).replace('T', ' ')
|
||||||
|
|
||||||
|
// 设置默认到期时间为一年后
|
||||||
|
const nextYear = new Date()
|
||||||
|
nextYear.setFullYear(nextYear.getFullYear() + 1)
|
||||||
|
formData.expirationDate = nextYear.toISOString().substring(0, 19).replace('T', ' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
resetForm()
|
||||||
|
dialogType.value = 'edit'
|
||||||
|
// 直接使用行数据
|
||||||
|
Object.assign(formData, row)
|
||||||
|
// 转换为元
|
||||||
|
formData.price = row.price / 100
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = (row) => {
|
||||||
|
ElMessageBox.confirm('确定要删除该记录吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
await settledMemberRecordApi.deleteSettledMemberRecord(row.id)
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
fetchData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除失败:', error)
|
||||||
|
ElMessage.error('删除失败')
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改变状态
|
||||||
|
const handleChangeStatus = async (row, newState) => {
|
||||||
|
const stateTip = newState === 1 ? '启用' : '停用'
|
||||||
|
ElMessageBox.confirm(`确定要${stateTip}该记录吗?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
await settledMemberRecordApi.updateSettledMemberRecord({
|
||||||
|
id: row.id,
|
||||||
|
state: newState
|
||||||
|
})
|
||||||
|
ElMessage.success(`${stateTip}成功`)
|
||||||
|
fetchData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`${stateTip}失败:`, error)
|
||||||
|
ElMessage.error(`${stateTip}失败`)
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理配置改变
|
||||||
|
const handleConfigChange = (configId) => {
|
||||||
|
const selectedConfig = configOptions.value.find(item => item.id === configId)
|
||||||
|
if (selectedConfig) {
|
||||||
|
formData.title = selectedConfig.title
|
||||||
|
formData.settledCostKey = selectedConfig.settledCostKey
|
||||||
|
formData.price = selectedConfig.price / 100 // 转换为元
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!formRef.value) return
|
||||||
|
|
||||||
|
await formRef.value.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
submitLoading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// API接收驼峰命名的数据,直接提交表单数据
|
||||||
|
const submitData = { ...formData }
|
||||||
|
// 价格转换为分
|
||||||
|
submitData.price = Math.round(submitData.price * 100)
|
||||||
|
|
||||||
|
if (dialogType.value === 'add') {
|
||||||
|
// 新增
|
||||||
|
await settledMemberRecordApi.addSettledMemberRecord(submitData)
|
||||||
|
ElMessage.success('创建成功')
|
||||||
|
} else {
|
||||||
|
// 编辑
|
||||||
|
await settledMemberRecordApi.updateSettledMemberRecord(submitData)
|
||||||
|
ElMessage.success('更新成功')
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogVisible.value = false
|
||||||
|
fetchData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交失败:', error)
|
||||||
|
ElMessage.error('提交失败: ' + (error.message || '未知错误'))
|
||||||
|
} finally {
|
||||||
|
submitLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
if (formRef.value) {
|
||||||
|
formRef.value.resetFields()
|
||||||
|
}
|
||||||
|
Object.assign(formData, {
|
||||||
|
id: null,
|
||||||
|
userId: '',
|
||||||
|
settledCostConfigId: null,
|
||||||
|
title: '',
|
||||||
|
settledCostKey: '',
|
||||||
|
constraintJson: '{}',
|
||||||
|
expirationDate: '',
|
||||||
|
kickbackType: 1,
|
||||||
|
kickbackValue: 0,
|
||||||
|
resourceCostType: 1,
|
||||||
|
resourceCostValue: 0,
|
||||||
|
serviceRate: 0,
|
||||||
|
price: 0,
|
||||||
|
state: 1,
|
||||||
|
note: '',
|
||||||
|
createdBy: 0,
|
||||||
|
updatedBy: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatDateTime = (timestamp) => {
|
||||||
|
if (!timestamp) return '-'
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
return date.toLocaleString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态类型
|
||||||
|
const getStatusType = (state) => {
|
||||||
|
const map = {
|
||||||
|
0: 'danger',
|
||||||
|
1: 'success'
|
||||||
|
}
|
||||||
|
return map[state] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (state) => {
|
||||||
|
const map = {
|
||||||
|
0: '已停用',
|
||||||
|
1: '已启用'
|
||||||
|
}
|
||||||
|
return map[state] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取佣金类型文本
|
||||||
|
const getKickbackTypeText = (type) => {
|
||||||
|
const map = {
|
||||||
|
0: '预留',
|
||||||
|
1: '提点',
|
||||||
|
2: '固定费用'
|
||||||
|
}
|
||||||
|
return map[type] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取资源占用费类型文本
|
||||||
|
const getResourceCostTypeText = (type) => {
|
||||||
|
const map = {
|
||||||
|
0: '预留',
|
||||||
|
1: '提点',
|
||||||
|
2: '固定费用'
|
||||||
|
}
|
||||||
|
return map[type] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化值(根据类型)
|
||||||
|
const formatValue = (value, type) => {
|
||||||
|
if (type === 1) {
|
||||||
|
// 提点 - 显示为百分比
|
||||||
|
return (value / 10000).toFixed(2) + '%'
|
||||||
|
} else if (type === 2) {
|
||||||
|
// 固定费用 - 显示为元
|
||||||
|
return (value / 100).toFixed(2) + '元'
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-area {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 18px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-row-item {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
margin-left: 8px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
385
src/views/Tools/Cards/List.vue
Normal file
385
src/views/Tools/Cards/List.vue
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
<template>
|
||||||
|
<div class="list-container">
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<div class="search-area">
|
||||||
|
<el-form :inline="true" :model="searchForm">
|
||||||
|
<el-form-item label="卡密账号">
|
||||||
|
<el-input v-model="searchForm.cardId" placeholder="请输入卡密账号" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="卡密密码">
|
||||||
|
<el-input v-model="searchForm.cardSecret" placeholder="请输入卡密密码" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
|
||||||
|
<el-option label="未激活" :value="0" />
|
||||||
|
<el-option label="未使用" :value="1" />
|
||||||
|
<el-option label="已使用" :value="2" />
|
||||||
|
<el-option label="已冻结" :value="3" />
|
||||||
|
<el-option label="已过期" :value="4" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||||
|
<el-button @click="resetSearch">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="action-bar">
|
||||||
|
<el-button type="primary" @click="handleGetCardSecret">获取卡密</el-button>
|
||||||
|
<el-button @click="refreshData">刷新</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
style="width: 100%;"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" align="center" width="55" />
|
||||||
|
<el-table-column prop="cardId" label="卡密账号" min-width="180" />
|
||||||
|
<el-table-column prop="cardSecret" label="卡密密码" min-width="180" />
|
||||||
|
<el-table-column prop="cardType" label="卡密类型" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ getCardTypeText(row.cardType) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="faceValue" label="面值" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.faceValue }}元
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="balance" label="当前余额" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.balance }}元
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="effectiveDays" label="有效期" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.effectiveDays }}天
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="activateTime" label="激活时间" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.activateTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="expireTime" label="过期时间" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.expireTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="useTime" label="使用时间" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.useTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="memo" label="备注" min-width="120" />
|
||||||
|
<el-table-column label="操作" fixed="right" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="danger"
|
||||||
|
@click="handleDelete(row)"
|
||||||
|
:disabled="row.status !== 0"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="pagination.current"
|
||||||
|
v-model:page-size="pagination.size"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="pagination.total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 获取卡密对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
title="卡密信息"
|
||||||
|
v-model="cardSecretDialogVisible"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<div class="card-secret-content">
|
||||||
|
<p>您的卡密为:</p>
|
||||||
|
<el-input
|
||||||
|
v-model="cardSecretValue"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="cardSecretDialogVisible = false">关闭</el-button>
|
||||||
|
<el-button type="primary" @click="handleCopyCardSecret">复制</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { cardsApi } from '@/api/modules/cards'
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const tableRef = ref(null)
|
||||||
|
|
||||||
|
// 搜索表单
|
||||||
|
const searchForm = reactive({
|
||||||
|
cardId: '',
|
||||||
|
cardSecret: '',
|
||||||
|
status: null
|
||||||
|
})
|
||||||
|
|
||||||
|
// 分页配置
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1,
|
||||||
|
size: 10,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 卡密对话框
|
||||||
|
const cardSecretDialogVisible = ref(false)
|
||||||
|
const cardSecretValue = ref('')
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取表格数据
|
||||||
|
const fetchData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// 使用API模块获取数据
|
||||||
|
const res = await cardsApi.pageQueryCard({
|
||||||
|
page: pagination.current,
|
||||||
|
size: pagination.size,
|
||||||
|
cardId: searchForm.cardId || undefined,
|
||||||
|
cardSecret: searchForm.cardSecret || undefined,
|
||||||
|
status: searchForm.status !== null ? searchForm.status : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
// 由于响应拦截器已经提取了response.data,所以直接使用res
|
||||||
|
if (res.code === 200) {
|
||||||
|
tableData.value = res.data.records || []
|
||||||
|
pagination.total = res.data.total || 0
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message || '获取数据失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error)
|
||||||
|
// 显示更具体的错误信息
|
||||||
|
if (error.code === 'ECONNABORTED') {
|
||||||
|
ElMessage.error('请求超时,请检查网络连接或联系管理员')
|
||||||
|
} else if (error.response) {
|
||||||
|
ElMessage.error(`请求失败: ${error.response.status} ${error.response.statusText}`)
|
||||||
|
} else if (error.request) {
|
||||||
|
ElMessage.error('服务器未响应,请稍后再试')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(`请求错误: ${error.message}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置空数据
|
||||||
|
tableData.value = []
|
||||||
|
pagination.total = 0
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取卡密
|
||||||
|
const handleGetCardSecret = async () => {
|
||||||
|
try {
|
||||||
|
const res = await cardsApi.createCardSecret()
|
||||||
|
// 由于createCardSecret方法已经处理了响应,所以直接使用res
|
||||||
|
if (res.code === 200) {
|
||||||
|
cardSecretValue.value = res.data
|
||||||
|
cardSecretDialogVisible.value = true
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message || '获取卡密失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取卡密失败:', error)
|
||||||
|
ElMessage.error('获取卡密失败: ' + (error.message || '未知错误'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制卡密
|
||||||
|
const handleCopyCardSecret = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(cardSecretValue.value)
|
||||||
|
ElMessage.success('复制成功')
|
||||||
|
cardSecretDialogVisible.value = false
|
||||||
|
} catch (error) {
|
||||||
|
console.error('复制失败:', error)
|
||||||
|
ElMessage.error('复制失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = () => {
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理搜索
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.current = 1
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置搜索
|
||||||
|
const resetSearch = () => {
|
||||||
|
searchForm.cardId = ''
|
||||||
|
searchForm.cardSecret = ''
|
||||||
|
searchForm.status = null
|
||||||
|
pagination.current = 1
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页大小变化
|
||||||
|
const handleSizeChange = (size) => {
|
||||||
|
pagination.size = size
|
||||||
|
pagination.current = 1
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页码变化
|
||||||
|
const handleCurrentChange = (current) => {
|
||||||
|
pagination.current = current
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
const handleDelete = (row) => {
|
||||||
|
ElMessageBox.confirm('确定要删除该卡密吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await cardsApi.deleteCard(row.id)
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
fetchData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message || '删除失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除失败:', error)
|
||||||
|
// 显示更具体的错误信息
|
||||||
|
if (error.code === 'ECONNABORTED') {
|
||||||
|
ElMessage.error('请求超时,请稍后再试')
|
||||||
|
} else if (error.response) {
|
||||||
|
ElMessage.error(`删除失败: ${error.response.status} ${error.response.statusText}`)
|
||||||
|
} else {
|
||||||
|
ElMessage.error(`删除失败: ${error.message || '未知错误'}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消操作,不做处理
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态类型
|
||||||
|
const getStatusType = (status) => {
|
||||||
|
const map = {
|
||||||
|
0: 'info',
|
||||||
|
1: 'success',
|
||||||
|
2: 'warning',
|
||||||
|
3: 'danger',
|
||||||
|
4: 'info'
|
||||||
|
}
|
||||||
|
return map[status] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
const map = {
|
||||||
|
0: '未激活',
|
||||||
|
1: '未使用',
|
||||||
|
2: '已使用',
|
||||||
|
3: '已冻结',
|
||||||
|
4: '已过期'
|
||||||
|
}
|
||||||
|
return map[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取卡密类型文本
|
||||||
|
const getCardTypeText = (type) => {
|
||||||
|
const map = {
|
||||||
|
'verifyPriceCredential': '使用核价凭证'
|
||||||
|
}
|
||||||
|
return map[type] || type
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatDateTime = (timestamp) => {
|
||||||
|
if (!timestamp) return '-'
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
return date.toLocaleString()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-area {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 18px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-secret-content {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -41,17 +41,17 @@ export default defineConfig({
|
|||||||
__VUE_OPTIONS_API__: JSON.stringify(false),
|
__VUE_OPTIONS_API__: JSON.stringify(false),
|
||||||
// 关闭生产环境 devtools(可选)
|
// 关闭生产环境 devtools(可选)
|
||||||
__VUE_PROD_DEVTOOLS__: JSON.stringify(false)
|
__VUE_PROD_DEVTOOLS__: JSON.stringify(false)
|
||||||
}
|
},
|
||||||
// server: {
|
server: {
|
||||||
// proxy: {
|
proxy: {
|
||||||
// '/api': {
|
'/api': {
|
||||||
// // target: 'http://127.0.0.1:8080',
|
target: 'http://127.0.0.1:8089',
|
||||||
// target: 'http://146.56.227.42',
|
// target: 'http://146.56.227.42',
|
||||||
// changeOrigin: true,
|
changeOrigin: true,
|
||||||
// rewrite: (path) => path.replace(/^\/api/,''),
|
rewrite: (path) => path.replace(/^\/api/,''),
|
||||||
// // 如需处理WebSocket
|
// 如需处理WebSocket
|
||||||
// ws: true
|
ws: true
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
})
|
})
|
||||||
Loading…
Reference in New Issue
Block a user