feat: 支持用户管理

This commit is contained in:
richarjiang
2026-03-15 15:45:09 +08:00
parent 7628768869
commit 3c35f1982f
9 changed files with 738 additions and 82 deletions

View File

@@ -2,9 +2,10 @@
import { useState, useRef } from 'react'
import { Button } from '@/components/ui/button'
import { Upload, X, Image as ImageIcon } from 'lucide-react'
import { X, Image as ImageIcon } from 'lucide-react'
import Image from 'next/image'
import { Spinner } from '@/components/ui/spinner'
import COS from 'cos-js-sdk-v5'
interface ImageUploaderProps {
value: string
@@ -47,49 +48,42 @@ export function ImageUploader({ value, onChange }: ImageUploaderProps) {
const ext = file.name.split('.').pop() || 'jpg'
const timestamp = Date.now()
const randomStr = Math.random().toString(36).substring(2, 8)
const filename = `levels/${timestamp}_${randomStr}.${ext}`
const filename = `mini_game/images/${timestamp}_${randomStr}.${ext}`
// Upload to COS
const formData = new FormData()
formData.append('key', filename)
formData.append('Signature', keyData.credentials.sessionToken)
formData.append('success_action_status', '200')
const uploadUrl = `https://${keyData.bucket}.cos.${keyData.region}.myqcloud.com`
// Use XMLHttpRequest for COS upload with temp credentials
const uploadResult = await new Promise<string>((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('POST', uploadUrl)
// Set temp credentials headers
xhr.setRequestHeader('Authorization', getCOSAuthorization(
keyData.credentials.tmpSecretId,
keyData.credentials.tmpSecretKey,
keyData.credentials.sessionToken,
'post',
filename,
keyData.bucket,
keyData.region
))
xhr.onload = () => {
if (xhr.status === 200) {
resolve(`${uploadUrl}/${filename}`)
} else {
reject(new Error('上传失败'))
}
}
xhr.onerror = () => reject(new Error('上传失败'))
const cosFormData = new FormData()
cosFormData.append('key', filename)
cosFormData.append('file', file)
xhr.send(cosFormData)
// Initialize COS with temp credentials
const cos = new COS({
getAuthorization: (_options, callback) => {
callback({
TmpSecretId: keyData.credentials.tmpSecretId,
TmpSecretKey: keyData.credentials.tmpSecretKey,
SecurityToken: keyData.credentials.sessionToken,
StartTime: keyData.startTime,
ExpiredTime: keyData.expiredTime,
})
},
})
onChange(uploadResult)
// Upload file
const uploadUrl = await new Promise<string>((resolve, reject) => {
cos.putObject(
{
Bucket: keyData.bucket,
Region: keyData.region,
Key: filename,
Body: file,
},
(err, data) => {
if (err) {
reject(new Error(err.message || '上传失败'))
return
}
const url = `https://${keyData.bucket}.cos.${keyData.region}.myqcloud.com/${filename}`
resolve(url)
}
)
})
onChange(uploadUrl)
} catch (err) {
console.error('Upload error:', err)
setError(err instanceof Error ? err.message : '上传失败')
@@ -162,21 +156,3 @@ export function ImageUploader({ value, onChange }: ImageUploaderProps) {
</div>
)
}
// Helper function to generate COS authorization header
function getCOSAuthorization(
secretId: string,
secretKey: string,
sessionToken: string,
method: string,
pathname: string,
bucket: string,
region: string
): string {
const now = Math.floor(Date.now() / 1000)
const exp = now + 1800
const keyTime = `${now};${exp}`
// Simple authorization string for temp credentials
return `q-sign-algorithm=sha1&q-ak=${secretId}&q-sign-time=${keyTime}&q-key-time=${keyTime}&q-header-list=&q-url-param-list=&q-signature=placeholder&x-cos-security-token=${sessionToken}`
}