feat(developer): 完成小程序开发者中心和企业控制台改造
- 设计并实现了开发者中心与企业控制台两大模块 - 按用户角色区分开发者和企业客户,支持多项目类型及成员管理 - 新增项目管理、应用管理、API Key管理及成员邀请等多功能页面 - 实现应用版本发布、消息通知中心、权限审批与开发者申请流程 - 完成CI/CD流水线、运营监控、发票管理、SSO单点登录功能 - 搭建SDK下载中心、工单系统、FAQ系统、数据导入导出等模块 - 优化后端API,支持已登录和未注册用户不同加入应用流程 - 前端按钮统一采用微信手机号授权,完善用户授权体验 - 修复多个页面的JSX语法错误及依赖导入问题,替换部分组件库 - 增加详细的类型定义文件,提升项目类型安全 - 新增超过55个页面及60个API接口,扩展应用功能和服务体系 - 完成全面的样式设计,实现一致的视觉风格和交互体验
This commit is contained in:
139
src/developer/project/[id]/api-keys.tsx
Normal file
139
src/developer/project/[id]/api-keys.tsx
Normal file
@@ -0,0 +1,139 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { View, Text, Input, Button, actionSheet } from '@tarojs/components'
|
||||
import Taro, { useRouter } from '@tarojs/taro'
|
||||
import { usePullDownRefresh } from '@tarojs/taro'
|
||||
import { listApiKey, createApiKey, deleteApiKey } from '@/api/developer/developer'
|
||||
import type { ApiKey, ApiKeyParam } from '@/types/developer'
|
||||
import './api-keys.scss'
|
||||
|
||||
const ApiKeysPage: React.FC = () => {
|
||||
const router = useRouter()
|
||||
const projectId = Number(router.params.id)
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [list, setList] = useState<ApiKey[]>([])
|
||||
const [showCreate, setShowCreate] = useState(false)
|
||||
const [createForm, setCreateForm] = useState({ name: '', remark: '' })
|
||||
const [creating, setCreating] = useState(false)
|
||||
|
||||
const loadData = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const params: ApiKeyParam = { websiteId: projectId }
|
||||
const data = await listApiKey(params)
|
||||
setList(data || [])
|
||||
} catch (err) {
|
||||
console.error('加载失败', err)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => { loadData() }, [projectId])
|
||||
usePullDownRefresh(() => { loadData() })
|
||||
|
||||
const handleCreate = async () => {
|
||||
if (!createForm.name.trim()) {
|
||||
Taro.showToast({ title: '请输入名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
setCreating(true)
|
||||
try {
|
||||
await createApiKey({ name: createForm.name, remark: createForm.remark, websiteId: projectId } as Partial<ApiKey>)
|
||||
Taro.showToast({ title: '创建成功', icon: 'success' })
|
||||
setShowCreate(false)
|
||||
setCreateForm({ name: '', remark: '' })
|
||||
loadData()
|
||||
} catch {
|
||||
Taro.showToast({ title: '创建失败', icon: 'none' })
|
||||
} finally {
|
||||
setCreating(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDelete = (item: ApiKey) => {
|
||||
actionSheet({
|
||||
alertText: `确定删除 "${item.name}" 吗?`,
|
||||
actions: [{ name: '删除', color: '#ff4d4f', type: 'warn' as const }],
|
||||
confirmText: '取消',
|
||||
}).then(res => {
|
||||
if (res.confirm) {
|
||||
deleteApiKey(item.id!).then(() => {
|
||||
Taro.showToast({ title: '已删除', icon: 'success' })
|
||||
loadData()
|
||||
})
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
const handleCopy = (text: string) => {
|
||||
Taro.setClipboardData({ data: text, success: () => Taro.showToast({ title: '已复制', icon: 'success' }) })
|
||||
}
|
||||
|
||||
return (
|
||||
<View className="api-keys-page">
|
||||
<View className="api-keys-page__header">
|
||||
<Text className="api-keys-page__title">🔑 API Key 管理</Text>
|
||||
<Button className="api-keys-page__create-btn" size="mini" onClick={() => setShowCreate(true)}>+ 创建</Button>
|
||||
</View>
|
||||
|
||||
<View className="api-keys-page__list">
|
||||
{list.length === 0 && !loading ? (
|
||||
<View className="api-keys-page__empty"><Text>暂无 API Key</Text></View>
|
||||
) : (
|
||||
list.map((item) => (
|
||||
<View key={item.id} className="api-key-card">
|
||||
<View className="api-key-card__header">
|
||||
<Text className="api-key-card__name">{item.name}</Text>
|
||||
<Text className="api-key-card__status" style={{ color: item.status ? '#52c41a' : '#999' }}>
|
||||
{item.status ? '正常' : '禁用'}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="api-key-card__row">
|
||||
<Text className="api-key-card__label">AppId:</Text>
|
||||
<Text className="api-key-card__value api-key-card__value--monospace" onClick={() => handleCopy(item.appId || '')}>
|
||||
{item.appId || '-'}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="api-key-card__row">
|
||||
<Text className="api-key-card__label">AppSecret:</Text>
|
||||
<Text className="api-key-card__value api-key-card__value--monospace" onClick={() => handleCopy(item.appSecret || '')}>
|
||||
••••••••••••••••
|
||||
</Text>
|
||||
</View>
|
||||
<View className="api-key-card__actions">
|
||||
{item.appSecret && <Text className="api-key-card__action api-key-card__action--primary" onClick={() => handleCopy(item.appSecret || '')}>复制密钥</Text>}
|
||||
<Text className="api-key-card__action api-key-card__action--danger" onClick={() => handleDelete(item)}>删除</Text>
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
|
||||
{showCreate && (
|
||||
<View className="api-keys-page__modal">
|
||||
<View className="api-keys-page__modal-mask" onClick={() => setShowCreate(false)} />
|
||||
<View className="api-keys-page__modal-content">
|
||||
<Text className="api-keys-page__modal-title">创建 API Key</Text>
|
||||
<View className="api-keys-page__form">
|
||||
<View className="api-keys-page__form-item">
|
||||
<Text className="api-keys-page__form-label">名称 *</Text>
|
||||
<Input className="api-keys-page__form-input" placeholder="请输入 Key 名称" value={createForm.name} onInput={(e) => setCreateForm(prev => ({ ...prev, name: e.detail.value }))} />
|
||||
</View>
|
||||
<View className="api-keys-page__form-item">
|
||||
<Text className="api-keys-page__form-label">备注</Text>
|
||||
<Input className="api-keys-page__form-input" placeholder="可选" value={createForm.remark} onInput={(e) => setCreateForm(prev => ({ ...prev, remark: e.detail.value }))} />
|
||||
</View>
|
||||
</View>
|
||||
<View className="api-keys-page__modal-actions">
|
||||
<Button className="api-keys-page__modal-btn api-keys-page__modal-btn--cancel" onClick={() => setShowCreate(false)}>取消</Button>
|
||||
<Button className="api-keys-page__modal-btn api-keys-page__modal-btn--confirm" loading={creating} onClick={handleCreate}>创建</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default ApiKeysPage
|
||||
Reference in New Issue
Block a user