Files
opc-web/src/views/user/models/ApiKeyListView.vue
xujl 8e18e77747 开发了多角色登录功能:实现了普通用户、企业用户和管理员可以分别通过不同入口登录系统,并且支持用账号、邮箱或手机号登录。
开发了权限分配功能:实现了一个可以在后台勾选页面的功能,通过给角色勾选菜单,就能直接控制不同身份的人登录后能看到哪些页面。
开发了实名认证功能:实现了企业可以提交营业执照认证,个人可以提交身份证件和技能认证的功能,管理员在后台可以进行审核。
开发了任务大厅功能:实现了企业可以发布需要做的任务,个人用户能在任务大厅里看到这些任务,并且可以点击申请接单,大家都能看到任务是“进行中”还是“已完成”状态。
开发了专家库与邀约功能:实现了企业可以去专家库里搜索合适的人才,并且可以直接给他们发送工作邀约。
开发了平台数据大屏展示功能:实现了在首页和各自的工作台页面,展示任务数量、收益金额等核心数据的概览面板。
2026-04-28 16:22:50 +08:00

94 lines
3.4 KiB
Vue

<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { onMounted, ref } from 'vue';
import api from '@/api';
import { Key, Copy, Check, Trash2 } from 'lucide-vue-next';
const apiKeys = ref<any[]>([]);
const fetchKeys = async () => {
try {
const res: any = await api.get('/tokens/');
apiKeys.value = res;
} catch (error) { console.error('Fetch keys failed', error); }
};
onMounted(fetchKeys);
const copiedId = ref<string | null>(null);
const copyKey = (id: string, key: string) => {
navigator.clipboard.writeText(key);
copiedId.value = id;
ElMessage.success('已复制到剪贴板');
setTimeout(() => { copiedId.value = null; }, 2000);
};
const revokeKey = async (id: string) => {
try {
await api.delete(`/tokens/${id}/`);
await fetchKeys();
ElMessage.success('凭证已注销');
} catch (error) { ElMessage.error('操作失败'); }
};
</script>
<template>
<div class="space-y-5">
<div class="flex items-center justify-between">
<div>
<h1 class="text-xl font-bold text-gray-800">API 管理</h1>
<p class="text-sm text-gray-400">您申请的所有模型访问凭证</p>
</div>
<router-link to="/user/models">
<el-button type="primary">申请新模型</el-button>
</router-link>
</div>
<el-table :data="apiKeys" stripe v-if="apiKeys.length > 0">
<el-table-column label="模型" min-width="200">
<template #default="{ row }">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-lg bg-gray-50 flex items-center justify-center text-gray-400">
<Key class="w-4 h-4" />
</div>
<div>
<div class="font-semibold">{{ row.model_name }} Access</div>
<div class="text-xs text-gray-400">模型: {{ row.model_name }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="状态" width="100">
<template #default><el-tag type="success" size="small">Active</el-tag></template>
</el-table-column>
<el-table-column label="Token" min-width="280">
<template #default="{ row }">
<div class="flex items-center gap-2">
<code class="text-xs font-mono text-gray-600 bg-gray-50 px-2 py-1 rounded flex-1 overflow-hidden text-ellipsis">{{ row.token_value }}</code>
<el-button text size="small" @click="copyKey(row.id, row.token_value)">
<Check v-if="copiedId === row.id" class="w-4 h-4 text-green-500" />
<Copy v-else class="w-4 h-4" />
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="创建时间" width="130">
<template #default="{ row }">{{ new Date(row.created_at).toLocaleDateString() }}</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template #default="{ row }">
<el-popconfirm title="确定要注销此凭证吗?" @confirm="revokeKey(row.id)">
<template #reference>
<el-button text type="danger" size="small"><Trash2 class="w-4 h-4" /></el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-empty v-else description="暂无可用凭证" :image-size="80">
<el-button type="primary" @click="$router.push('/user/models')">前往模型市场申请</el-button>
</el-empty>
</div>
</template>