Commit 4655fb4b by renyizhao

用户资源包列表修改

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