This commit is contained in:
2025-12-15 17:55:32 +08:00
commit 28ab17324d
170 changed files with 18373 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
<template>
<main style="padding: 16px">
<h1 style="font-size: 18px; font-weight: 600">统计</h1>
<pre style="margin-top: 12px; background: #f7f7f7; padding: 12px; border-radius: 8px">{{ data }}</pre>
</main>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { api } from '../api'
const data = ref<any>(null)
onMounted(async () => {
const resp = await api.get('/statistics')
data.value = resp.data
})
</script>

View File

@@ -0,0 +1,76 @@
<template>
<main style="padding: 16px">
<h1 style="font-size: 18px; font-weight: 600">角色类型</h1>
<p style="margin-top: 6px; color: #666">仅管理固定角色<code>user</code> / <code>tenant_admin</code> / <code>super_admin</code></p>
<table style="margin-top: 12px; width: 100%; border-collapse: collapse">
<thead>
<tr>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Code</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Name</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Status</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Updated</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Action</th>
</tr>
</thead>
<tbody>
<tr v-for="it in items" :key="it.code">
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.code }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">
<input v-model="it._editName" style="width: 240px" />
</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">
<select v-model.number="it._editStatus">
<option :value="0">0 (enabled)</option>
<option :value="1">1 (disabled)</option>
</select>
</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.updated_at }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">
<button @click="save(it)">保存</button>
</td>
</tr>
</tbody>
</table>
</main>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { api } from '../api'
type Role = {
code: string
name: string
status: number
updated_at: string
_editName: string
_editStatus: number
}
const items = ref<Role[]>([])
async function load() {
const resp = await api.get('/roles')
const list = (resp.data.items || []) as any[]
items.value = list.map((it) => ({
code: it.code,
name: it.name,
status: it.status,
updated_at: it.updated_at,
_editName: it.name,
_editStatus: it.status,
}))
}
async function save(it: Role) {
await api.put(`/roles/${encodeURIComponent(it.code)}`, {
name: it._editName,
status: it._editStatus,
})
await load()
}
onMounted(load)
</script>

View File

@@ -0,0 +1,47 @@
<template>
<main style="padding: 16px">
<h1 style="font-size: 18px; font-weight: 600">租户</h1>
<div style="margin-top: 12px; display: flex; gap: 8px">
<input v-model="keyword" placeholder="keyword" />
<button @click="load">查询</button>
</div>
<table style="margin-top: 12px; width: 100%; border-collapse: collapse">
<thead>
<tr>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">ID</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Code</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Name</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Admins</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Admin Expire At(max)</th>
<th style="text-align: left; border-bottom: 1px solid #eee; padding: 8px">Status</th>
</tr>
</thead>
<tbody>
<tr v-for="it in items" :key="it.id">
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.id }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.tenant_code }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.name }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.admin_count }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.admin_expire_at || '-' }}</td>
<td style="border-bottom: 1px solid #f2f2f2; padding: 8px">{{ it.status }}</td>
</tr>
</tbody>
</table>
</main>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { api } from '../api'
const keyword = ref('')
const items = ref<any[]>([])
async function load() {
const resp = await api.get('/tenants', { params: { page: 1, limit: 50, keyword: keyword.value } })
items.value = resp.data.items || []
}
onMounted(load)
</script>