Commit 4655fb4b by renyizhao

用户资源包列表修改

parent 0bf3c8de
...@@ -5,6 +5,8 @@ import type { Dayjs } from 'dayjs'; ...@@ -5,6 +5,8 @@ import type { Dayjs } from 'dayjs';
export interface UserApiUsage { export interface UserApiUsage {
id: number; // 记录ID id: number; // 记录ID
userId?: number; // 用户ID userId?: number; // 用户ID
userMobile?: string; // 用户手机号
userNickname?: string; // 用户昵称
apiId?: number; // API ID apiId?: number; // API ID
apiName?: string; // api名称 apiName?: string; // api名称
packageId?: number; // 购买的套餐ID packageId?: number; // 购买的套餐ID
......
...@@ -15,13 +15,8 @@ ...@@ -15,13 +15,8 @@
</el-form-item> </el-form-item>
<!-- 分类选择 --> <!-- 分类选择 -->
<el-form-item label="分类" prop="categoryId"> <el-form-item label="分类" prop="categoryId">
<el-select v-model="formData.categoryId" placeholder="请选择分类" style="width: 100%;"> <el-select v-model="formData.categoryId" placeholder="请选择分类" style="width: 100%">
<el-option <el-option v-for="c in categoryList" :key="c.id" :label="c.name" :value="c.id" />
v-for="c in categoryList"
:key="c.id"
:label="c.name"
:value="c.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="API供应商" prop="vendor"> <el-form-item label="API供应商" prop="vendor">
...@@ -32,10 +27,8 @@ ...@@ -32,10 +27,8 @@
</el-form-item> </el-form-item>
<el-form-item label="关联接口"> <el-form-item label="关联接口">
<!-- 添加接口按钮独占一行 --> <!-- 添加接口按钮独占一行 -->
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px">
<el-button type="primary" size="small" @click="addApiEndpoint"> <el-button type="primary" size="small" @click="addApiEndpoint"> 添加接口 </el-button>
添加接口
</el-button>
</div> </div>
<!-- 接口表格,每个接口占一行 --> <!-- 接口表格,每个接口占一行 -->
...@@ -80,7 +73,6 @@ ...@@ -80,7 +73,6 @@
</table> </table>
</el-form-item> </el-form-item>
<el-form-item label="API 简介" prop="description"> <el-form-item label="API 简介" prop="description">
<el-input v-model="formData.description" height="350px" /> <el-input v-model="formData.description" height="350px" />
</el-form-item> </el-form-item>
...@@ -115,7 +107,7 @@ ...@@ -115,7 +107,7 @@
<el-form-item label="资源包配置" prop="apiPackages"> <el-form-item label="资源包配置" prop="apiPackages">
<el-button type="primary" @click="addApiPackages">新增</el-button> <el-button type="primary" @click="addApiPackages">新增</el-button>
<div style="padding-top: 10px;"> <div style="padding-top: 10px">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
...@@ -159,7 +151,10 @@ ...@@ -159,7 +151,10 @@
</el-form-item> </el-form-item>
</td> </td>
<td> <td>
<el-form-item :prop="'apiPackages.' + index + '.validDays'" :rules="rules.validDays"> <el-form-item
:prop="'apiPackages.' + index + '.validDays'"
:rules="rules.validDays"
>
<el-input-number <el-input-number
v-model="i.validDays" v-model="i.validDays"
:min="1" :min="1"
...@@ -169,19 +164,22 @@ ...@@ -169,19 +164,22 @@
</el-form-item> </el-form-item>
</td> </td>
<td> <td>
<el-button
<el-button type="danger" :disabled="formData.apiPackages.length === 1" @click="delapiPackage(index)"> type="danger"
:disabled="formData.apiPackages.length === 1"
@click="delapiPackage(index)"
>
删除 删除
</el-button> </el-button>
<!-- <el-button--> <!-- <el-button-->
<!-- type="primary"--> <!-- type="primary"-->
<!-- :disabled="index === 0"--> <!-- :disabled="index === 0"-->
<!-- @click="upItem(index)">上移</el-button>--> <!-- @click="upItem(index)">上移</el-button>-->
<!-- <el-button--> <!-- <el-button-->
<!-- type="primary"--> <!-- type="primary"-->
<!-- :disabled="index + 1 === formData.apiPackages.length"--> <!-- :disabled="index + 1 === formData.apiPackages.length"-->
<!-- @click="downItem(index)">下移--> <!-- @click="downItem(index)">下移-->
<!-- </el-button>--> <!-- </el-button>-->
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -196,11 +194,10 @@ ...@@ -196,11 +194,10 @@
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ApiApi, Api, ApiCategory} from '@/api/apihub/api' import { ApiApi, Api, ApiCategory } from '@/api/apihub/api'
import {DICT_TYPE, getIntDictOptions} from "@/utils/dict" import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import type { FormItemRule } from 'element-plus' import type { FormItemRule } from 'element-plus'
import {ApiEndpoint, ApiEndpointApi} from "@/api/apihub/apiendpoint"; import { ApiEndpoint, ApiEndpointApi } from '@/api/apihub/apiendpoint'
const categoryList = ref<ApiCategory[]>([]) const categoryList = ref<ApiCategory[]>([])
...@@ -223,7 +220,6 @@ const dialogTitle = ref('') // 弹窗的标题 ...@@ -223,7 +220,6 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改 const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({ const formData = ref({
id: undefined, id: undefined,
name: '', name: '',
...@@ -231,23 +227,17 @@ const formData = ref({ ...@@ -231,23 +227,17 @@ const formData = ref({
categoryId: undefined, // 新增:分类id categoryId: undefined, // 新增:分类id
vendor: undefined, vendor: undefined,
vendorContact: undefined, vendorContact: undefined,
priceInfo:'', priceInfo: '',
coverImage: undefined, coverImage: undefined,
description: '', description: '',
detail: '', detail: '',
doc: '', doc: '',
status: 1, // 默认上架 status: 1, // 默认上架
remark: '', remark: '',
apiPackages: [ apiPackages: [{ name: '套餐', times: 1, price: 1, validDays: 30, id: null }],
{ name: '套餐', times: 1, price: 1, validDays: 30, id: null } apiEndPoints: [{ name: '接口', path: 'https://', method: 'POST', id: null }]
],
apiEndPoints: [
{ name: '接口', path: 'https://', method: 'POST', id: null }
],
}) })
// 自定义校验器 // 自定义校验器
const validatePrice: FormItemRule['validator'] = (_rule, value, callback) => { const validatePrice: FormItemRule['validator'] = (_rule, value, callback) => {
if (value === undefined || value === null) { if (value === undefined || value === null) {
...@@ -269,35 +259,25 @@ const validateTimes: FormItemRule['validator'] = (_rule, value, callback) => { ...@@ -269,35 +259,25 @@ const validateTimes: FormItemRule['validator'] = (_rule, value, callback) => {
callback() callback()
} }
const rules = reactive({ const rules = reactive({
name: [ name: [{ required: true, message: '请输入套餐名称', trigger: ['blur', 'change'] }],
{ required: true, message: '请输入套餐名称', trigger: ['blur', 'change'] } price: [{ required: true, validator: validatePrice, trigger: ['blur', 'change'] }],
], times: [{ required: true, validator: validateTimes, trigger: ['blur', 'change'] }],
price: [ validDays: [{ required: true, validator: validateTimes, trigger: ['blur', 'change'] }]
{ required: true, validator: validatePrice, trigger: ['blur', 'change'] } })
],
times: [
{ required: true, validator: validateTimes, trigger: ['blur', 'change'] }
],
validDays: [
{ required: true, validator: validateTimes, trigger: ['blur', 'change'] }
]})
const formRules = reactive({ const formRules = reactive({
categoryId: [{ required: true, message: '请选择分类', trigger: 'change' }], categoryId: [{ required: true, message: '请选择分类', trigger: 'change' }],
name: [ name: [{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }]
{ required: true, message: '请输入名称', trigger: ['blur', 'change'] } })
]})
const formRef = ref() // 表单 Ref const formRef = ref() // 表单 Ref
const addApiPackages = () => { const addApiPackages = () => {
formData.value.apiPackages.push({name: '套餐', times: 1, price: 1, validDays: 30, id: null}); formData.value.apiPackages.push({ name: '套餐', times: 1, price: 1, validDays: 30, id: null })
} }
const delapiPackage = (index) => { const delapiPackage = (index) => {
formData.value.apiPackages.splice(index, 1); formData.value.apiPackages.splice(index, 1)
} }
// //
// const upItem = (index: number) => { // const upItem = (index: number) => {
...@@ -316,8 +296,6 @@ const delapiPackage = (index) => { ...@@ -316,8 +296,6 @@ const delapiPackage = (index) => {
// arr[index] = tmp // arr[index] = tmp
// } // }
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
dialogVisible.value = true dialogVisible.value = true
...@@ -335,8 +313,8 @@ const open = async (type: string, id?: number) => { ...@@ -335,8 +313,8 @@ const open = async (type: string, id?: number) => {
try { try {
// 调用 getApi 后做一次数据清洗 // 调用 getApi 后做一次数据清洗
const res = await ApiApi.getApi(id) const res = await ApiApi.getApi(id)
res.detail = res.detail ?? "" res.detail = res.detail ?? ''
res.doc = res.doc ?? "" res.doc = res.doc ?? ''
formData.value = res formData.value = res
} finally { } finally {
formLoading.value = false formLoading.value = false
...@@ -344,8 +322,6 @@ const open = async (type: string, id?: number) => { ...@@ -344,8 +322,6 @@ const open = async (type: string, id?: number) => {
} }
} }
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */ /** 提交表单 */
...@@ -384,7 +360,7 @@ const resetForm = () => { ...@@ -384,7 +360,7 @@ const resetForm = () => {
formData.value = { formData.value = {
id: undefined, id: undefined,
categoryId: undefined, categoryId: undefined,
priceInfo:'', priceInfo: '',
coverImage: undefined, coverImage: undefined,
name: '', name: '',
trialUrl: '', trialUrl: '',
...@@ -393,19 +369,13 @@ const resetForm = () => { ...@@ -393,19 +369,13 @@ const resetForm = () => {
doc: '', doc: '',
status: 1, status: 1,
remark: '', remark: '',
apiPackages: [ apiPackages: [{ name: '套餐', times: 1, price: 1, validDays: 30, id: null }],
{ name: '套餐', times: 1, price: 1, validDays: 30, id: null } apiEndPoints: [{ name: '接口', path: 'https://', method: 'POST', id: null }]
],
apiEndPoints: [
{ name: '接口', path: 'https://', method: 'POST', id: null }
],
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }
// -----------------------------------------------添加接口start----------------------------------------------------------------------------------------
// -----------------------------------------------添加接口start----------------------------------------------------------------------------------------
const apiEndPointList = ref<ApiEndpoint[]>([]) const apiEndPointList = ref<ApiEndpoint[]>([])
...@@ -421,9 +391,9 @@ const getAllApiEndPointsList = async () => { ...@@ -421,9 +391,9 @@ const getAllApiEndPointsList = async () => {
const addApiEndpoint = () => { const addApiEndpoint = () => {
formData.value.apiEndPoints.push({ formData.value.apiEndPoints.push({
id: null, id: null,
name: "", name: '',
path: "", path: '',
method: "" method: ''
}) })
} }
...@@ -434,7 +404,7 @@ const removeApiEndpoint = (index: number) => { ...@@ -434,7 +404,7 @@ const removeApiEndpoint = (index: number) => {
// 选择接口时自动填充 name、path、method // 选择接口时自动填充 name、path、method
const onApiSelected = (id: number, row: any) => { const onApiSelected = (id: number, row: any) => {
const api = apiEndPointList.value.find(item => item.id === id) const api = apiEndPointList.value.find((item) => item.id === id)
if (api) { if (api) {
row.name = api.name row.name = api.name
row.path = api.path row.path = api.path
...@@ -442,7 +412,6 @@ const onApiSelected = (id: number, row: any) => { ...@@ -442,7 +412,6 @@ const onApiSelected = (id: number, row: any) => {
} }
} }
// -----------------------------------------------添加接口End--------------------------------------------------------------------------------------- // -----------------------------------------------添加接口End---------------------------------------------------------------------------------------
</script> </script>
<style scoped> <style scoped>
...@@ -490,5 +459,4 @@ const onApiSelected = (id: number, row: any) => { ...@@ -490,5 +459,4 @@ const onApiSelected = (id: number, row: any) => {
padding: 10px 5px; padding: 10px 5px;
vertical-align: middle; vertical-align: middle;
} }
</style> </style>
<template>
<el-dialog title="资源包详情" v-model="visible" width="700px">
<el-descriptions :column="2" border v-loading="loading">
<el-descriptions-item label="用户手机号">{{ detailData.userMobile || '-' }}</el-descriptions-item>
<el-descriptions-item label="用户昵称">{{ detailData.userNickname || '-' }}</el-descriptions-item>
<el-descriptions-item label="API名称">{{ detailData.apiName || '-' }}</el-descriptions-item>
<el-descriptions-item label="套餐名称">{{ detailData.packageName || '-' }}</el-descriptions-item>
<el-descriptions-item label="套餐总量">{{ detailData.packageTimes ?? '-' }}</el-descriptions-item>
<el-descriptions-item label="有效时长">
{{ detailData.packageValidDays ? detailData.packageValidDays + ' 天' : '-' }}
</el-descriptions-item>
<el-descriptions-item label="已使用次数">{{ detailData.usedTimes ?? '-' }}</el-descriptions-item>
<el-descriptions-item label="过期时间">{{ formatDate(detailData.expireTime) }}</el-descriptions-item>
<el-descriptions-item label="购买时间">{{ formatDate(detailData.createTime) }}</el-descriptions-item>
</el-descriptions>
</el-dialog>
</template>
<script setup lang="ts">
import { UserApiUsageApi } from '@/api/apihub/userapiusage'
const visible = ref(false)
const loading = ref(false)
const detailData = ref<any>({})
const formatDate = (date: string) => {
if (!date) return '-'
const d = new Date(date)
if (isNaN(d.getTime())) return date
const pad = (n: number) => n.toString().padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}
const open = async (id: number) => {
visible.value = true
loading.value = true
try {
const data = await UserApiUsageApi.getUserApiUsage(id)
detailData.value = data
} finally {
loading.value = false
}
}
defineExpose({ open })
</script>
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
> >
<Icon icon="ep:download" class="mr-5px" /> 导出 <Icon icon="ep:download" class="mr-5px" /> 导出
</el-button> </el-button>
<el-button <!-- <el-button
type="danger" type="danger"
plain plain
:disabled="isEmpty(checkedIds)" :disabled="isEmpty(checkedIds)"
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
v-hasPermi="['apihub:user-api-usage:delete']" v-hasPermi="['apihub:user-api-usage:delete']"
> >
<Icon icon="ep:delete" class="mr-5px" /> 批量删除 <Icon icon="ep:delete" class="mr-5px" /> 批量删除
</el-button> </el-button> -->
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
...@@ -72,15 +72,15 @@ ...@@ -72,15 +72,15 @@
@selection-change="handleRowCheckboxChange" @selection-change="handleRowCheckboxChange"
> >
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="用户手机号" align="center" prop="userMobile" width="150px"/> <el-table-column label="用户手机号" align="center" prop="userMobile" width="150px" />
<el-table-column label="用户昵称" align="center" prop="userNickname" width="150px" />
<el-table-column label="api名称" align="center" prop="apiName" width="150px" /> <el-table-column label="api名称" align="center" prop="apiName" width="150px" />
<el-table-column label="套餐名称" align="center" prop="packageName" width="150px" /> <el-table-column label="套餐名称" align="center" prop="packageName" width="150px" />
<el-table-column label="套餐总量" align="center" prop="packageTimes" /> <el-table-column label="套餐总量" align="center" prop="packageTimes" />
<el-table-column label="有效时长" align="center" prop="packageValidDays"> <el-table-column label="有效时长" align="center" prop="packageValidDays">
<template #default="scope"> <template #default="scope"> {{ scope.row.packageValidDays }}</template>
{{ scope.row.packageValidDays }} </el-table-column>
</template> <el-table-column label="已使用次数" align="center" prop="usedTimes" width="150px" />
</el-table-column> <el-table-column label="已使用次数" align="center" prop="usedTimes" width="150px" />
<el-table-column <el-table-column
label="过期时间" label="过期时间"
align="center" align="center"
...@@ -95,9 +95,10 @@ ...@@ -95,9 +95,10 @@
:formatter="dateFormatter" :formatter="dateFormatter"
width="180px" width="180px"
/> />
<el-table-column label="操作" align="center" min-width="120px"> <el-table-column label="操作" align="center" min-width="180px">
<template #default="scope"> <template #default="scope">
<el-button <el-button link type="primary" @click="handleDetail(scope.row.id)"> 详情 </el-button>
<!-- <el-button
link link
type="primary" type="primary"
@click="openForm('update', scope.row.id)" @click="openForm('update', scope.row.id)"
...@@ -112,7 +113,7 @@ ...@@ -112,7 +113,7 @@
v-hasPermi="['apihub:user-api-usage:delete']" v-hasPermi="['apihub:user-api-usage:delete']"
> >
删除 删除
</el-button> </el-button> -->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -125,6 +126,9 @@ ...@@ -125,6 +126,9 @@
/> />
</ContentWrap> </ContentWrap>
<!-- 详情弹窗 -->
<UserApiUsageDetail ref="detailRef" />
<!-- 表单弹窗:添加/修改 --> <!-- 表单弹窗:添加/修改 -->
<UserApiUsageForm ref="formRef" @success="getList" /> <UserApiUsageForm ref="formRef" @success="getList" />
</template> </template>
...@@ -135,6 +139,7 @@ import { dateFormatter } from '@/utils/formatTime' ...@@ -135,6 +139,7 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { UserApiUsageApi, UserApiUsage } from '@/api/apihub/userapiusage' import { UserApiUsageApi, UserApiUsage } from '@/api/apihub/userapiusage'
import UserApiUsageForm from './UserApiUsageForm.vue' import UserApiUsageForm from './UserApiUsageForm.vue'
import UserApiUsageDetail from './UserApiUsageDetail.vue'
/** 用户API管理 列表 */ /** 用户API管理 列表 */
defineOptions({ name: 'UserApiUsage' }) defineOptions({ name: 'UserApiUsage' })
...@@ -185,6 +190,12 @@ const openForm = (type: string, id?: number) => { ...@@ -185,6 +190,12 @@ const openForm = (type: string, id?: number) => {
formRef.value.open(type, id) formRef.value.open(type, id)
} }
/** 详情操作 */
const detailRef = ref()
const handleDetail = (id: number) => {
detailRef.value.open(id)
}
/** 删除按钮操作 */ /** 删除按钮操作 */
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
try { try {
...@@ -203,15 +214,15 @@ const handleDeleteBatch = async () => { ...@@ -203,15 +214,15 @@ const handleDeleteBatch = async () => {
try { try {
// 删除的二次确认 // 删除的二次确认
await message.delConfirm() await message.delConfirm()
await UserApiUsageApi.deleteUserApiUsageList(checkedIds.value); await UserApiUsageApi.deleteUserApiUsageList(checkedIds.value)
message.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
await getList(); await getList()
} catch {} } catch {}
} }
const checkedIds = ref<number[]>([]) const checkedIds = ref<number[]>([])
const handleRowCheckboxChange = (records: UserApiUsage[]) => { const handleRowCheckboxChange = (records: UserApiUsage[]) => {
checkedIds.value = records.map((item) => item.id); checkedIds.value = records.map((item) => item.id)
} }
/** 导出按钮操作 */ /** 导出按钮操作 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment