- 标注:AI 预标注直写 labels_json(去候选确认两阶段);重叠去重(minIoU);全量标注按钮 - 训练:脚本迁移入 server/training/(Go 化 prepare_yolo/analyze_rfdetr,保留 train_server.py);tflite 产物自检并入训练流程(check_tflite) - 数据目录/权重不进 git;.gitignore 迁移至仓库根
217 lines
6.7 KiB
Vue
217 lines
6.7 KiB
Vue
<script setup>
|
|
import { onMounted, reactive, ref } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import request from '../api/request'
|
|
|
|
const filter = reactive({ phoneNum: '' })
|
|
const loading = ref(false)
|
|
const list = ref([])
|
|
const total = ref(0)
|
|
const page = ref(1)
|
|
const size = ref(20)
|
|
|
|
const grantVisible = ref(false)
|
|
const grantForm = reactive({ phoneNum: '', planId: 'day' })
|
|
const granting = ref(false)
|
|
|
|
const remarkVisible = ref(false)
|
|
const remarkForm = reactive({ phoneNum: '', remark: '' })
|
|
const remarking = ref(false)
|
|
|
|
const planOptions = [
|
|
{ value: 'day', label: '1天' },
|
|
{ value: 'week', label: '7天' },
|
|
{ value: 'month', label: '30天' },
|
|
]
|
|
|
|
function load() {
|
|
loading.value = true
|
|
request
|
|
.get('/licenses', {
|
|
params: {
|
|
page: page.value,
|
|
size: size.value,
|
|
phoneNum: filter.phoneNum || undefined,
|
|
},
|
|
})
|
|
.then((data) => {
|
|
list.value = data.list || []
|
|
total.value = data.total || 0
|
|
})
|
|
.finally(() => {
|
|
loading.value = false
|
|
})
|
|
}
|
|
|
|
function search() {
|
|
page.value = 1
|
|
load()
|
|
}
|
|
|
|
function openGrant(row) {
|
|
grantForm.phoneNum = row.phoneNum
|
|
grantForm.planId = 'day'
|
|
grantVisible.value = true
|
|
}
|
|
|
|
function submitGrant() {
|
|
granting.value = true
|
|
request
|
|
.post('/licenses/grant', { phoneNum: grantForm.phoneNum.trim(), planId: grantForm.planId })
|
|
.then((data) => {
|
|
ElMessage.success(`授权成功,到期时间 ${data.expiresAt}`)
|
|
grantVisible.value = false
|
|
load()
|
|
})
|
|
.finally(() => {
|
|
granting.value = false
|
|
})
|
|
}
|
|
|
|
function openRemark(row) {
|
|
remarkForm.phoneNum = row.phoneNum
|
|
remarkForm.remark = row.remark || ''
|
|
remarkVisible.value = true
|
|
}
|
|
|
|
function submitRemark() {
|
|
remarking.value = true
|
|
request
|
|
.post('/licenses/remark', {
|
|
phoneNum: remarkForm.phoneNum.trim(),
|
|
remark: remarkForm.remark.trim(),
|
|
})
|
|
.then(() => {
|
|
ElMessage.success(remarkForm.remark ? '备注已保存' : '备注已清空')
|
|
remarkVisible.value = false
|
|
load()
|
|
})
|
|
.finally(() => {
|
|
remarking.value = false
|
|
})
|
|
}
|
|
|
|
function revoke(row) {
|
|
ElMessageBox.confirm(`确认撤销 ${row.phoneNum} 的授权?撤销后该账号额度立即失效,账号保留可继续登录。`, '撤销授权', {
|
|
type: 'warning',
|
|
confirmButtonText: '确认撤销',
|
|
cancelButtonText: '取消',
|
|
})
|
|
.then(() => request.post('/licenses/revoke', { phoneNum: row.phoneNum }))
|
|
.then(() => {
|
|
ElMessage.success('已撤销')
|
|
load()
|
|
})
|
|
.catch(() => {})
|
|
}
|
|
|
|
onMounted(load)
|
|
</script>
|
|
|
|
<template>
|
|
<el-card shadow="never">
|
|
<div class="toolbar">
|
|
<el-form :model="filter" inline @submit.prevent="search">
|
|
<el-form-item label="手机号">
|
|
<el-input v-model="filter.phoneNum" placeholder="模糊匹配" clearable style="width: 220px" @keyup.enter="search" />
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="search">查询</el-button>
|
|
<el-button @click="filter.phoneNum = ''; search()">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<el-table v-loading="loading" :data="list" border stripe>
|
|
<el-table-column prop="phoneNum" label="手机号" min-width="140" show-overflow-tooltip />
|
|
<el-table-column label="授权状态" width="110">
|
|
<template #default="{ row }">
|
|
<el-tag v-if="row.expiresAt" type="success" size="small">已授权</el-tag>
|
|
<el-tag v-else type="info" size="small">未充值</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="expiresAt" label="到期时间" width="180">
|
|
<template #default="{ row }">{{ row.expiresAt || '-' }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="createdAt" label="注册时间" width="180">
|
|
<template #default="{ row }">{{ row.createdAt || '-' }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="updatedAt" label="更新时间" width="180">
|
|
<template #default="{ row }">{{ row.updatedAt || '-' }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip>
|
|
<template #default="{ row }">{{ row.remark || '-' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="180" fixed="right">
|
|
<template #default="{ row }">
|
|
<el-button type="primary" link size="small" @click="openGrant(row)">授权</el-button>
|
|
<el-button type="warning" link size="small" @click="openRemark(row)">备注</el-button>
|
|
<el-button type="danger" link size="small" :disabled="!row.expiresAt" @click="revoke(row)">撤销</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<el-pagination
|
|
class="pager"
|
|
v-model:current-page="page"
|
|
v-model:page-size="size"
|
|
:total="total"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
layout="total, sizes, prev, pager, next"
|
|
@change="load"
|
|
/>
|
|
|
|
<el-dialog v-model="grantVisible" title="手动授权" width="min(420px, 92vw)">
|
|
<el-form label-width="80px">
|
|
<el-form-item label="手机号">
|
|
<el-input :model-value="grantForm.phoneNum" disabled />
|
|
</el-form-item>
|
|
<el-form-item label="套餐">
|
|
<el-select v-model="grantForm.planId" style="width: 100%">
|
|
<el-option v-for="p in planOptions" :key="p.value" :label="p.label" :value="p.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="grantVisible = false">取消</el-button>
|
|
<el-button type="primary" :loading="granting" @click="submitGrant">确认授权</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="remarkVisible" title="账号备注" width="min(420px, 92vw)">
|
|
<el-form label-width="80px">
|
|
<el-form-item label="手机号">
|
|
<el-input :model-value="remarkForm.phoneNum" disabled />
|
|
</el-form-item>
|
|
<el-form-item label="备注">
|
|
<el-input
|
|
v-model="remarkForm.remark"
|
|
type="textarea"
|
|
:rows="3"
|
|
maxlength="200"
|
|
show-word-limit
|
|
placeholder="运营备注(如发卡渠道/人工记录),留空提交即清空"
|
|
/>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="remarkVisible = false">取消</el-button>
|
|
<el-button type="primary" :loading="remarking" @click="submitRemark">保存</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</el-card>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.toolbar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 14px;
|
|
}
|
|
.pager {
|
|
margin-top: 14px;
|
|
justify-content: flex-end;
|
|
}
|
|
</style>
|