This commit is contained in:
张成
2026-04-01 13:22:56 +08:00
parent 82432cdba8
commit fa9abf83ae
6 changed files with 179 additions and 196 deletions

View File

@@ -11,8 +11,12 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多 <Icon type="ios-arrow-down" /></Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -94,6 +98,9 @@ export default {
this.param.pageOption.pageSize = s this.param.pageOption.pageSize = s
this.load(1) this.load(1)
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
async doExport() { async doExport() {
const res = await auditServer.exportRows({ param: this.param }) const res = await auditServer.exportRows({ param: this.param })
if (res && res.code === 0 && res.data && res.data.rows) { if (res && res.code === 0 && res.data && res.data.rows) {
@@ -107,10 +114,6 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
resetQuery() {
this.param.seachOption = { key: 'action', value: '' }
this.load(1)
},
}, },
} }
</script> </script>

View File

@@ -1,11 +1,10 @@
<template> <template>
<div class="content-view"> <div class="content-view">
<div class="table-head-tool"> <div class="table-head-tool">
<div class="table-title-row">
<Button type="primary" @click="openEdit(null)">新增套餐</Button>
</div>
<Form ref="formInline" :model="param.seachOption" inline :label-width="80"> <Form ref="formInline" :model="param.seachOption" inline :label-width="80">
<FormItem>
<Button type="primary" @click="openEdit(null)">新增套餐</Button>
</FormItem>
<FormItem label="条件"> <FormItem label="条件">
<Select v-model="param.seachOption.key" style="width: 140px"> <Select v-model="param.seachOption.key" style="width: 140px">
<Option value="plan_code">编码</Option> <Option value="plan_code">编码</Option>
@@ -22,8 +21,12 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多 <Icon type="ios-arrow-down" /></Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -132,12 +135,38 @@ export default {
{ {
title: '操作', title: '操作',
key: 'a', key: 'a',
width: 260, width: 180,
render: (h, p) => render: (h, p) =>
h('div', [ h('div', [
h('Button', { props: { type: 'info', size: 'small' }, on: { click: () => this.openEdit(p.row) } }, '编辑'), h('Button', { props: { type: 'info', size: 'small' }, on: { click: () => this.openEdit(p.row) } }, '编辑'),
h('Button', { props: { type: 'warning', size: 'small' }, class: { ml8: true }, on: { click: () => this.toggle(p.row) } }, '上下线'), h(
h('Button', { props: { type: 'error', size: 'small' }, class: { ml8: true }, on: { click: () => this.doDel(p.row) } }, '删除'), 'Dropdown',
{
props: { trigger: 'click', transfer: true },
class: { ml8: true },
on: {
'on-click': (name) => {
if (name === 'toggle') this.toggle(p.row)
else if (name === 'del') this.doDel(p.row)
},
},
},
[
h(
'Button',
{ props: { size: 'small' } },
['更多 ', h('Icon', { props: { type: 'ios-arrow-down' } })]
),
h(
'DropdownMenu',
{ slot: 'list' },
[
h('DropdownItem', { props: { name: 'toggle' } }, '上下线'),
h('DropdownItem', { props: { name: 'del' } }, '删除'),
]
),
]
),
]), ]),
}, },
] ]
@@ -249,6 +278,9 @@ export default {
} }
}) })
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
async toggle(row) { async toggle(row) {
const res = await planServer.toggle({ id: row.id }) const res = await planServer.toggle({ id: row.id })
if (res && res.code === 0) { if (res && res.code === 0) {
@@ -282,10 +314,6 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
resetQuery() {
this.param.seachOption = { key: 'plan_code', value: '' }
this.load(1)
},
}, },
} }
</script> </script>
@@ -303,13 +331,6 @@ export default {
margin-bottom: 16px; margin-bottom: 16px;
} }
.table-title-row {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 12px;
}
.ml10 { .ml10 {
margin-left: 10px; margin-left: 10px;
} }

View File

@@ -1,11 +1,10 @@
<template> <template>
<div class="content-view"> <div class="content-view">
<div class="table-head-tool"> <div class="table-head-tool">
<div class="table-title-row">
<Button type="primary" @click="openOpen">开通订阅</Button>
</div>
<Form ref="formInline" :model="param.seachOption" inline :label-width="80"> <Form ref="formInline" :model="param.seachOption" inline :label-width="80">
<FormItem>
<Button type="primary" @click="openOpen">开通订阅</Button>
</FormItem>
<FormItem label="筛选"> <FormItem label="筛选">
<Select v-model="param.seachOption.key" style="width: 120px" @on-change="onSearchKeyChange"> <Select v-model="param.seachOption.key" style="width: 120px" @on-change="onSearchKeyChange">
<Option value="user_id">用户</Option> <Option value="user_id">用户</Option>
@@ -29,8 +28,12 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多 <Icon type="ios-arrow-down" /></Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -137,13 +140,37 @@ export default {
{ {
title: '操作', title: '操作',
key: 'a', key: 'a',
width: 200, width: 120,
render: (h, p) => render: (h, p) =>
h('div', [ h(
h('Button', { props: { size: 'small' }, on: { click: () => this.openRenew(p.row) } }, '续费'), 'Dropdown',
h('Button', { props: { size: 'small' }, class: { ml8: true }, on: { click: () => this.openUpgrade(p.row) } }, '编辑'), {
h('Button', { props: { type: 'error', size: 'small' }, class: { ml8: true }, on: { click: () => this.doCancel(p.row) } }, '取消'), props: { trigger: 'click', transfer: true },
]), on: {
'on-click': (name) => {
if (name === 'renew') this.openRenew(p.row)
else if (name === 'edit') this.openUpgrade(p.row)
else if (name === 'cancel') this.doCancel(p.row)
},
},
},
[
h(
'Button',
{ props: { type: 'primary', size: 'small' } },
['操作 ', h('Icon', { props: { type: 'ios-arrow-down' } })]
),
h(
'DropdownMenu',
{ slot: 'list' },
[
h('DropdownItem', { props: { name: 'renew' } }, '续费'),
h('DropdownItem', { props: { name: 'edit' } }, '编辑订阅'),
h('DropdownItem', { props: { name: 'cancel' } }, '取消订阅'),
]
),
]
),
}, },
] ]
}, },
@@ -314,6 +341,9 @@ export default {
}, },
}) })
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
async doExport() { async doExport() {
const res = await subscriptionsServer.exportRows({ param: this.param }) const res = await subscriptionsServer.exportRows({ param: this.param })
if (res && res.code === 0 && res.data && res.data.rows) { if (res && res.code === 0 && res.data && res.data.rows) {
@@ -323,10 +353,6 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
resetQuery() {
this.param.seachOption = { key: 'user_id', value: '' }
this.load(1)
},
}, },
} }
</script> </script>
@@ -344,13 +370,6 @@ export default {
margin-bottom: 16px; margin-bottom: 16px;
} }
.table-title-row {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 12px;
}
.ml10 { .ml10 {
margin-left: 10px; margin-left: 10px;
} }

View File

@@ -1,11 +1,10 @@
<template> <template>
<div class="content-view"> <div class="content-view">
<div class="table-head-tool"> <div class="table-head-tool">
<div class="table-title-row">
<Button type="primary" @click="openCreate">创建 Token</Button>
</div>
<Form ref="formInline" :model="param.seachOption" inline :label-width="80"> <Form ref="formInline" :model="param.seachOption" inline :label-width="80">
<FormItem>
<Button type="primary" @click="openCreate">创建 Token</Button>
</FormItem>
<FormItem label="筛选"> <FormItem label="筛选">
<Select v-model="param.seachOption.key" style="width: 120px" @on-change="onSearchKeyChange"> <Select v-model="param.seachOption.key" style="width: 120px" @on-change="onSearchKeyChange">
<Option value="user_id">用户</Option> <Option value="user_id">用户</Option>
@@ -29,8 +28,12 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多 <Icon type="ios-arrow-down" /></Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -205,6 +208,9 @@ export default {
}, },
}) })
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
async doExport() { async doExport() {
const res = await tokenServer.exportRows({ param: this.param }) const res = await tokenServer.exportRows({ param: this.param })
if (res && res.code === 0 && res.data && res.data.rows) { if (res && res.code === 0 && res.data && res.data.rows) {
@@ -214,10 +220,6 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
resetQuery() {
this.param.seachOption = { key: 'user_id', value: '' }
this.load(1)
},
}, },
} }
</script> </script>
@@ -235,13 +237,6 @@ export default {
margin-bottom: 16px; margin-bottom: 16px;
} }
.table-title-row {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 12px;
}
.ml10 { .ml10 {
margin-left: 10px; margin-left: 10px;
} }

View File

@@ -1,11 +1,10 @@
<template> <template>
<div class="content-view"> <div class="content-view">
<div class="table-head-tool"> <div class="table-head-tool">
<div class="table-title-row">
<Button type="primary" @click="openEdit(null)">新增</Button>
</div>
<Form ref="formInline" :model="param.seachOption" inline :label-width="80" class="usage-query-form"> <Form ref="formInline" :model="param.seachOption" inline :label-width="80" class="usage-query-form">
<FormItem>
<Button type="primary" @click="openEdit(null)">新增</Button>
</FormItem>
<FormItem label="条件"> <FormItem label="条件">
<Select v-model="param.seachOption.key" class="usage-select" @on-change="onSearchKeyChange"> <Select v-model="param.seachOption.key" class="usage-select" @on-change="onSearchKeyChange">
<Option value="user_id">用户</Option> <Option value="user_id">用户</Option>
@@ -41,8 +40,12 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多 <Icon type="ios-arrow-down" /></Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -224,6 +227,9 @@ export default {
}, },
}) })
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
async doExport() { async doExport() {
const res = await usageServer.exportRows({ param: this.param }) const res = await usageServer.exportRows({ param: this.param })
if (res && res.code === 0 && res.data && res.data.rows) { if (res && res.code === 0 && res.data && res.data.rows) {
@@ -233,10 +239,6 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
resetQuery() {
this.param.seachOption = { key: 'stat_month', value: '' }
this.load(1)
},
}, },
} }
</script> </script>
@@ -281,13 +283,6 @@ export default {
margin-bottom: 16px; margin-bottom: 16px;
} }
.table-title-row {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 14px;
}
.ml10 { .ml10 {
margin-left: 10px; margin-left: 10px;
} }

View File

@@ -1,11 +1,10 @@
<template> <template>
<div class="content-view"> <div class="content-view">
<div class="table-head-tool"> <div class="table-head-tool">
<div class="table-title-row">
<Button type="primary" @click="openEdit(null)">新增</Button>
</div>
<Form ref="formInline" :model="param.seachOption" inline :label-width="80"> <Form ref="formInline" :model="param.seachOption" inline :label-width="80">
<FormItem>
<Button type="primary" @click="openEdit(null)">新增</Button>
</FormItem>
<FormItem label="条件"> <FormItem label="条件">
<Select v-model="param.seachOption.key" style="width: 140px"> <Select v-model="param.seachOption.key" style="width: 140px">
<Option value="mobile">手机</Option> <Option value="mobile">手机</Option>
@@ -17,8 +16,14 @@
</FormItem> </FormItem>
<FormItem> <FormItem>
<Button type="primary" @click="load(1)">查询</Button> <Button type="primary" @click="load(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button> <Dropdown trigger="click" class="ml10" @on-click="on_toolbar_more">
<Button type="default" @click="doExport" class="ml10">导出 CSV</Button> <Button type="default">更多
<Icon type="ios-arrow-down" />
</Button>
<DropdownMenu slot="list">
<DropdownItem name="export">导出 CSV</DropdownItem>
</DropdownMenu>
</Dropdown>
</FormItem> </FormItem>
</Form> </Form>
</div> </div>
@@ -57,16 +62,8 @@
<Modal v-model="detailVisible" title="用户详情" width="800" footer-hide> <Modal v-model="detailVisible" title="用户详情" width="800" footer-hide>
<p v-if="detail" class="mb8">Token 数量{{ detail.tokenCount }}</p> <p v-if="detail" class="mb8">Token 数量{{ detail.tokenCount }}</p>
<p v-if="detail && detail.tokens && detail.tokens.length" class="sub-title">API Token</p> <p v-if="detail && detail.tokens && detail.tokens.length" class="sub-title">API Token</p>
<Table <Table v-if="detail && detail.tokens && detail.tokens.length" :columns="tokenCols" :data="detail.tokens"
v-if="detail && detail.tokens && detail.tokens.length" size="small" border highlight-row class="mb16" @on-row-click="onTokenRowClick" />
:columns="tokenCols"
:data="detail.tokens"
size="small"
border
highlight-row
class="mb16"
@on-row-click="onTokenRowClick"
/>
<p v-if="detail && detail.subscriptions && detail.subscriptions.length" class="sub-title">订阅记录</p> <p v-if="detail && detail.subscriptions && detail.subscriptions.length" class="sub-title">订阅记录</p>
<Table v-if="detail && detail.subscriptions" :columns="subCols" :data="detail.subscriptions" size="small" <Table v-if="detail && detail.subscriptions" :columns="subCols" :data="detail.subscriptions" size="small"
border /> border />
@@ -74,15 +71,8 @@
<Modal v-model="tokenListVisible" :title="tokenListTitle" width="820" footer-hide> <Modal v-model="tokenListVisible" :title="tokenListTitle" width="820" footer-hide>
<p v-if="tokenListRows.length" class="text-muted mb8">点击表格某一行查看该 Token 详情明文不可查需重新创建</p> <p v-if="tokenListRows.length" class="text-muted mb8">点击表格某一行查看该 Token 详情明文不可查需重新创建</p>
<Table <Table v-if="tokenListRows.length" :columns="tokenCols" :data="tokenListRows" size="small" border highlight-row
v-if="tokenListRows.length" @on-row-click="onTokenRowClick" />
:columns="tokenCols"
:data="tokenListRows"
size="small"
border
highlight-row
@on-row-click="onTokenRowClick"
/>
<p v-else class="text-muted">暂无 Token</p> <p v-else class="text-muted">暂无 Token</p>
</Modal> </Modal>
@@ -148,26 +138,29 @@ export default {
{ {
title: 'API Token', title: 'API Token',
key: 'token_count', key: 'token_count',
width: 130, width: 100,
render: (h, p) => { render: (h, p) => {
const n = p.row.token_count != null ? Number(p.row.token_count) : 0 const n = p.row.token_count != null ? Number(p.row.token_count) : 0
return h('div', [ return h(
h('span', { class: { mr8: true } }, String(n)), 'a',
h( {
'Button', class: 'table-action-link',
{ attrs: { href: 'javascript:void(0)' },
props: { type: 'primary', size: 'small', ghost: true }, on: {
on: { click: () => this.openTokenList(p.row) }, click: (e) => {
e.preventDefault()
this.openTokenList(p.row)
},
}, },
'查看' },
), n > 0 ? `${n} · 列表` : String(n)
]) )
}, },
}, },
{ {
title: '操作', title: '操作',
key: 'a', key: 'a',
width: 380, width: 240,
render: (h, p) => { render: (h, p) => {
return h('div', [ return h('div', [
h( h(
@@ -187,42 +180,32 @@ export default {
}, },
'详情' '详情'
), ),
p.row.status === 'disabled' h(
? h( 'Dropdown',
'Button', {
{ props: { trigger: 'click', transfer: true },
props: { type: 'success', size: 'small' }, on: {
class: { ml8: true }, 'on-click': (name) => {
on: { click: () => this.doEnable(p.row) }, if (name === 'revoke_all') this.revokeAllTokens(p.row)
else if (name === 'del') this.doDel(p.row)
}, },
'启用' },
) },
: h( [
h(
'Button', 'Button',
{ { props: { size: 'small' }, class: { ml8: true } },
props: { type: 'warning', size: 'small' }, ['更多 ', h('Icon', { props: { type: 'ios-arrow-down' } })]
class: { ml8: true },
on: { click: () => this.doDisable(p.row) },
},
'禁用'
), ),
h( h(
'Button', 'DropdownMenu',
{ { slot: 'list' },
props: { type: 'default', size: 'small' }, [
class: { ml8: true }, h('DropdownItem', { props: { name: 'revoke_all' } }, '吊销全部 Token'),
on: { click: () => this.revokeAllTokens(p.row) }, h('DropdownItem', { props: { name: 'del' } }, '删除'),
}, ]
'吊销全部Token' ),
), ]
h(
'Button',
{
props: { type: 'error', size: 'small' },
class: { ml8: true },
on: { click: () => this.doDel(p.row) },
},
'删除'
), ),
]) ])
}, },
@@ -320,36 +303,6 @@ export default {
this.selectedToken = row this.selectedToken = row
this.tokenDetailVisible = true this.tokenDetailVisible = true
}, },
doDisable(row) {
this.$Modal.confirm({
title: '禁用用户',
content: '确认禁用该用户?',
onOk: async () => {
const res = await userServer.disable({ id: row.id })
if (res && res.code === 0) {
this.$Message.success('已禁用')
this.load(1)
} else {
this.$Message.error((res && res.message) || '操作失败')
}
},
})
},
doEnable(row) {
this.$Modal.confirm({
title: '启用用户',
content: '确认重新启用该用户?',
onOk: async () => {
const res = await userServer.enable({ id: row.id })
if (res && res.code === 0) {
this.$Message.success('已启用')
this.load(1)
} else {
this.$Message.error((res && res.message) || '操作失败')
}
},
})
},
doDel(row) { doDel(row) {
this.$Modal.confirm({ this.$Modal.confirm({
title: '删除用户', title: '删除用户',
@@ -374,6 +327,9 @@ export default {
this.$Message.error((res && res.message) || '导出失败') this.$Message.error((res && res.message) || '导出失败')
} }
}, },
on_toolbar_more(name) {
if (name === 'export') this.doExport()
},
revokeAllTokens(row) { revokeAllTokens(row) {
this.$Modal.confirm({ this.$Modal.confirm({
title: '吊销全部 Token', title: '吊销全部 Token',
@@ -390,10 +346,6 @@ export default {
}, },
}) })
}, },
resetQuery() {
this.param.seachOption = { key: 'mobile', value: '' }
this.load(1)
},
}, },
} }
</script> </script>
@@ -411,13 +363,6 @@ export default {
margin-bottom: 16px; margin-bottom: 16px;
} }
.table-title-row {
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 12px;
}
.ml10 { .ml10 {
margin-left: 10px; margin-left: 10px;
} }
@@ -448,8 +393,13 @@ export default {
color: #808695; color: #808695;
} }
.mr8 { .table-action-link {
margin-right: 8px; color: #2d8cf0;
cursor: pointer;
}
.table-action-link:hover {
text-decoration: underline;
} }
.token-detail .label { .token-detail .label {