u
This commit is contained in:
1 parent
0ab2796dd4
commit
f7b0c6ad2f
26 files changed
+1881
-342
No files matched your search
@@ -26,6 +26,7 @@
|
|||||||
"dayjs": "^1.11.19",
|
"dayjs": "^1.11.19",
|
||||||
"expo": "~54.0.23",
|
"expo": "~54.0.23",
|
||||||
"expo-blur": "~15.0.7",
|
"expo-blur": "~15.0.7",
|
||||||
|
"expo-clipboard": "~8.0.7",
|
||||||
"expo-constants": "~18.0.10",
|
"expo-constants": "~18.0.10",
|
||||||
"expo-font": "~14.0.9",
|
"expo-font": "~14.0.9",
|
||||||
"expo-linear-gradient": "~15.0.7",
|
"expo-linear-gradient": "~15.0.7",
|
||||||
|
|||||||
+24
@@ -56,6 +56,9 @@ importers:
|
|||||||
expo-blur:
|
expo-blur:
|
||||||
specifier: ~15.0.7
|
specifier: ~15.0.7
|
||||||
version: 15.0.7(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 15.0.7(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
expo-clipboard:
|
||||||
|
specifier: ~8.0.7
|
||||||
|
version: 8.0.7(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
expo-constants:
|
expo-constants:
|
||||||
specifier: ~18.0.10
|
specifier: ~18.0.10
|
||||||
version: 18.0.10(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))
|
version: 18.0.10(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))
|
||||||
@@ -3248,6 +3251,13 @@ packages:
|
|||||||
react: '*'
|
react: '*'
|
||||||
react-native: '*'
|
react-native: '*'
|
||||||
|
|
||||||
|
expo-clipboard@8.0.7:
|
||||||
|
resolution: {integrity: sha512-zvlfFV+wB2QQrQnHWlo0EKHAkdi2tycLtE+EXFUWTPZYkgu1XcH+aiKfd4ul7Z0SDF+1IuwoiW9AA9eO35aj3Q==}
|
||||||
|
peerDependencies:
|
||||||
|
expo: '*'
|
||||||
|
react: '*'
|
||||||
|
react-native: '*'
|
||||||
|
|
||||||
expo-constants@18.0.10:
|
expo-constants@18.0.10:
|
||||||
resolution: {integrity: sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==}
|
resolution: {integrity: sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3930,48 +3940,56 @@ packages:
|
|||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-arm64-gnu@1.30.2:
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.27.0:
|
lightningcss-linux-arm64-musl@1.27.0:
|
||||||
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
|
resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-linux-arm64-musl@1.30.2:
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.27.0:
|
lightningcss-linux-x64-gnu@1.27.0:
|
||||||
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
|
resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-x64-gnu@1.30.2:
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [glibc]
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.27.0:
|
lightningcss-linux-x64-musl@1.27.0:
|
||||||
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
|
resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-linux-x64-musl@1.30.2:
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
libc: [musl]
|
||||||
|
|
||||||
lightningcss-win32-arm64-msvc@1.27.0:
|
lightningcss-win32-arm64-msvc@1.27.0:
|
||||||
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
|
resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==}
|
||||||
@@ -9832,6 +9850,12 @@ snapshots:
|
|||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
|
||||||
|
expo-clipboard@8.0.7(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
|
dependencies:
|
||||||
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)
|
||||||
|
|
||||||
expo-constants@18.0.10(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
expo-constants@18.0.10(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@expo/config': 12.0.10
|
'@expo/config': 12.0.10
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import type { AFormRef } from '@/components/common/ao'
|
||||||
|
import { useRef, useState } from 'react'
|
||||||
|
import { Text, View } from 'react-native'
|
||||||
|
import { AButton, ADivider, AForm, AFormItem, AInput } from '@/components/common/ao'
|
||||||
|
import { Link, LinkText } from '@/components/ui/link'
|
||||||
|
|
||||||
|
interface JoinSpaceProps {
|
||||||
|
onBack?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function JoinSpace({
|
||||||
|
onBack,
|
||||||
|
}: JoinSpaceProps) {
|
||||||
|
const formRef = useRef<AFormRef>(null)
|
||||||
|
const [form, setForm] = useState({
|
||||||
|
code: '',
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<View className="px-4 items-center">
|
||||||
|
<AForm ref={formRef} form={form}>
|
||||||
|
<AFormItem
|
||||||
|
name="username"
|
||||||
|
label="邀请码"
|
||||||
|
>
|
||||||
|
<AInput placeholder="请输入邀请码"></AInput>
|
||||||
|
</AFormItem>
|
||||||
|
</AForm>
|
||||||
|
|
||||||
|
<AButton className="w-full">加入空间</AButton>
|
||||||
|
<View
|
||||||
|
className="flex-row items-center w-full"
|
||||||
|
style={{
|
||||||
|
marginTop: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View className="flex-1">
|
||||||
|
<ADivider />
|
||||||
|
</View>
|
||||||
|
<Text className="mx-3 text-gray-500 text-sm">或</Text>
|
||||||
|
<View className="flex-1">
|
||||||
|
<ADivider />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<AButton variant="outline" className="w-full">扫码加入</AButton>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
className="mt-4"
|
||||||
|
onPress={() => {
|
||||||
|
onBack?.()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LinkText>返回</LinkText>
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Text, View } from 'react-native'
|
||||||
|
import { AButton, ADivider, LucideIcon } from '@/components/common/ao'
|
||||||
|
|
||||||
|
interface SpaceHomeProps {
|
||||||
|
onCreate?: () => void
|
||||||
|
onJoin?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SpaceHome({
|
||||||
|
onCreate,
|
||||||
|
onJoin,
|
||||||
|
}: SpaceHomeProps) {
|
||||||
|
return (
|
||||||
|
<View className="p-4">
|
||||||
|
<View className="flex-col gap-4 justify-center items-center">
|
||||||
|
<LucideIcon icon="Earth" size={48} strokeWidth={1.5} />
|
||||||
|
<Text className="font-semibold text-xl">创建共享空间</Text>
|
||||||
|
<Text className="text-base text-center">创建一个专属空间,邀请朋友加入,共享文件、聊天和协作</Text>
|
||||||
|
<AButton
|
||||||
|
className="w-full"
|
||||||
|
onPress={() => onCreate?.()}
|
||||||
|
>
|
||||||
|
创建我的空间
|
||||||
|
</AButton>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ADivider text="或" />
|
||||||
|
|
||||||
|
<AButton
|
||||||
|
variant="outline"
|
||||||
|
onPress={() => onJoin?.()}
|
||||||
|
>
|
||||||
|
加入已有空间
|
||||||
|
</AButton>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
import * as Clipboard from 'expo-clipboard'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { FlatList, Pressable, TouchableOpacity, View } from 'react-native'
|
||||||
|
import QRCode from 'react-native-qrcode-svg'
|
||||||
|
import { AButton, ADivider, LucideIcon } from '@/components/common/ao'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionHeader,
|
||||||
|
AccordionIcon,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTitleText,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from '@/components/ui/accordion'
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
AvatarBadge,
|
||||||
|
AvatarFallbackText,
|
||||||
|
} from '@/components/ui/avatar'
|
||||||
|
import { Badge, BadgeText } from '@/components/ui/badge'
|
||||||
|
import { Heading } from '@/components/ui/heading'
|
||||||
|
import { HStack } from '@/components/ui/hstack'
|
||||||
|
import { ChevronDownIcon, ChevronUpIcon } from '@/components/ui/icon'
|
||||||
|
import { Menu, MenuItem, MenuItemLabel } from '@/components/ui/menu'
|
||||||
|
import { Text } from '@/components/ui/text'
|
||||||
|
import { VStack } from '@/components/ui/vstack'
|
||||||
|
import { toast } from '@/utils/toast'
|
||||||
|
|
||||||
|
export default function SpaceInviteAndMembers() {
|
||||||
|
const [accordion, setAccordion] = useState(['a'])
|
||||||
|
|
||||||
|
const members = [
|
||||||
|
{ id: 1, name: '张三' },
|
||||||
|
{ id: 2, name: '李四' },
|
||||||
|
{ id: 3, name: '王五' },
|
||||||
|
]
|
||||||
|
|
||||||
|
async function copyInviteCode() {
|
||||||
|
await Clipboard.setStringAsync('hello world')
|
||||||
|
|
||||||
|
toast.show({
|
||||||
|
title: '复制成功',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className="px-4 flex-1">
|
||||||
|
<Accordion
|
||||||
|
size="md"
|
||||||
|
variant="unfilled"
|
||||||
|
type="multiple"
|
||||||
|
isCollapsible={true}
|
||||||
|
isDisabled={false}
|
||||||
|
value={accordion}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
setAccordion(value)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccordionItem value="a">
|
||||||
|
<AccordionHeader>
|
||||||
|
<AccordionTrigger
|
||||||
|
style={{
|
||||||
|
paddingLeft: 0,
|
||||||
|
paddingRight: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ isExpanded }: { isExpanded: boolean }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AccordionTitleText className="font-semibold text-lg">
|
||||||
|
我的邀请码
|
||||||
|
</AccordionTitleText>
|
||||||
|
{isExpanded
|
||||||
|
? (
|
||||||
|
<AccordionIcon as={ChevronUpIcon} className="ml-3" />
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<AccordionIcon as={ChevronDownIcon} className="ml-3" />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</AccordionTrigger>
|
||||||
|
</AccordionHeader>
|
||||||
|
<AccordionContent style={{
|
||||||
|
marginBottom: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TouchableOpacity
|
||||||
|
className="flex-row items-center justify-center"
|
||||||
|
onPress={() => {
|
||||||
|
copyInviteCode()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className="font-bold text-3xl tracking-[4px] mr-3">123456</Text>
|
||||||
|
<LucideIcon icon="Copy" size={16} color="blue" clickable={false} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<View className="items-center justify-center">
|
||||||
|
<ADivider direction="horizontal" text="扫描二维码" />
|
||||||
|
<QRCode
|
||||||
|
size={120}
|
||||||
|
value="http://awesome.link.qr"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
<View className="mt-4 flex-1">
|
||||||
|
<View className="flex flex-row items-center justify-between">
|
||||||
|
<Text className="font-semibold text-lg">空间成员</Text>
|
||||||
|
<Badge size="lg" variant="solid" action="muted">
|
||||||
|
<BadgeText>3 人</BadgeText>
|
||||||
|
</Badge>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View>
|
||||||
|
<FlatList
|
||||||
|
data={members}
|
||||||
|
keyExtractor={item => item.id.toString()}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<TouchableOpacity>
|
||||||
|
<HStack space="md" className="my-2 items-center">
|
||||||
|
<Avatar className="bg-indigo-600">
|
||||||
|
<AvatarFallbackText className="text-white text-lg">
|
||||||
|
{item.name}
|
||||||
|
</AvatarFallbackText>
|
||||||
|
<AvatarBadge />
|
||||||
|
</Avatar>
|
||||||
|
<VStack>
|
||||||
|
<HStack space="sm">
|
||||||
|
<Heading size="sm">{item.name}</Heading>
|
||||||
|
<Badge size="sm" variant="solid" action="muted">
|
||||||
|
<BadgeText>管理员</BadgeText>
|
||||||
|
</Badge>
|
||||||
|
</HStack>
|
||||||
|
<Text size="sm">Marketing Coordinator</Text>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
<View className="ml-auto">
|
||||||
|
<Menu
|
||||||
|
placement="top"
|
||||||
|
offset={5}
|
||||||
|
trigger={triggerProps => (
|
||||||
|
<Pressable
|
||||||
|
{...triggerProps}
|
||||||
|
style={{
|
||||||
|
padding: 8,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LucideIcon icon="EllipsisVertical" size={20} clickable={false} />
|
||||||
|
</Pressable>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<MenuItem key="Add account" textValue="Add account">
|
||||||
|
<MenuItemLabel size="sm">添加为管理员</MenuItemLabel>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key="Community" textValue="Community">
|
||||||
|
<MenuItemLabel size="sm">移出空间</MenuItemLabel>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</View>
|
||||||
|
</HStack>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<AButton size="sm" className="mb-8 mt-4">退出该空间</AButton>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'
|
||||||
|
|
||||||
|
interface StepFadeProps {
|
||||||
|
visible: boolean
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StepFade({ visible, children }: StepFadeProps) {
|
||||||
|
if (!visible)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
entering={FadeIn.duration(200)}
|
||||||
|
exiting={FadeOut.duration(200)}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Animated.View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,241 +1,41 @@
|
|||||||
import type { AFormRef } from '@/components/common/ao'
|
import { useState } from 'react'
|
||||||
import * as React from 'react'
|
import { View } from 'react-native'
|
||||||
import { useRef, useState } from 'react'
|
|
||||||
import { FlatList, Pressable, TouchableOpacity, View } from 'react-native'
|
|
||||||
import QRCode from 'react-native-qrcode-svg'
|
|
||||||
import { AButton, ADivider, AForm, AFormItem, AInput, LucideIcon } from '@/components/common/ao'
|
|
||||||
import CustomHeader from '@/components/custom/Header'
|
import CustomHeader from '@/components/custom/Header'
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionHeader,
|
|
||||||
AccordionIcon,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTitleText,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from '@/components/ui/accordion'
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
AvatarBadge,
|
|
||||||
AvatarFallbackText,
|
|
||||||
AvatarImage,
|
|
||||||
} from '@/components/ui/avatar'
|
|
||||||
import { Badge, BadgeText } from '@/components/ui/badge'
|
|
||||||
|
|
||||||
import { Heading } from '@/components/ui/heading'
|
import JoinSpace from './components/JoinSpace'
|
||||||
import { HStack } from '@/components/ui/hstack'
|
import SpaceHome from './components/SpaceHome'
|
||||||
import { ChevronDownIcon, ChevronUpIcon } from '@/components/ui/icon'
|
import SpaceInviteAndMembers from './components/SpaceInviteAndMembers'
|
||||||
import { Link, LinkText } from '@/components/ui/link'
|
import StepFade from './components/StepFade'
|
||||||
import { Menu, MenuItem, MenuItemLabel } from '@/components/ui/menu'
|
|
||||||
import { Text } from '@/components/ui/text'
|
|
||||||
import { VStack } from '@/components/ui/vstack'
|
|
||||||
|
|
||||||
export default function PagerWithTab() {
|
export default function PagerWithTab() {
|
||||||
const formRef = useRef<AFormRef>(null)
|
const [step, setStep] = useState<'join' | 'invite' | 'home'>('home')
|
||||||
const [form, setForm] = useState({
|
|
||||||
code: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const [accordion, setAccordion] = useState(['a'])
|
|
||||||
|
|
||||||
function EnterSapce() {
|
|
||||||
return (
|
|
||||||
<View className="px-4 items-center">
|
|
||||||
<AForm ref={formRef} form={form}>
|
|
||||||
<AFormItem
|
|
||||||
name="username"
|
|
||||||
label="邀请码"
|
|
||||||
>
|
|
||||||
<AInput placeholder="请输入邀请码"></AInput>
|
|
||||||
</AFormItem>
|
|
||||||
</AForm>
|
|
||||||
|
|
||||||
<AButton className="w-full">加入空间</AButton>
|
|
||||||
<View
|
|
||||||
className="flex-row items-center w-full"
|
|
||||||
style={{
|
|
||||||
marginTop: 16,
|
|
||||||
marginBottom: 16,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View className="flex-1">
|
|
||||||
<ADivider />
|
|
||||||
</View>
|
|
||||||
<Text className="mx-3 text-gray-500 text-sm">或</Text>
|
|
||||||
<View className="flex-1">
|
|
||||||
<ADivider />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<AButton variant="outline" className="w-full">扫码加入</AButton>
|
|
||||||
|
|
||||||
<Link className="mt-4">
|
|
||||||
<LinkText>返回</LinkText>
|
|
||||||
</Link>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const members = [
|
|
||||||
{ id: 1, name: '张三' },
|
|
||||||
{ id: 2, name: '李四' },
|
|
||||||
{ id: 3, name: '王五' },
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="flex-1">
|
<View className="flex-1">
|
||||||
<CustomHeader title="共享空间" />
|
<CustomHeader title="共享空间" />
|
||||||
<View className="flex-1">
|
<View className="flex-1">
|
||||||
{/* <View className="p-4">
|
<StepFade visible={step === 'home'}>
|
||||||
<View className="flex-col gap-4 justify-center items-center">
|
<SpaceHome
|
||||||
<LucideIcon icon="Earth" size={48} strokeWidth={1.5} />
|
onCreate={() => {
|
||||||
<Text className="font-semibold text-xl">创建共享空间</Text>
|
setStep('invite')
|
||||||
<Text className="text-base text-center">创建一个专属空间,邀请朋友加入,共享文件、聊天和协作</Text>
|
|
||||||
<AButton className="w-full">创建我的空间</AButton>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
className="flex-row items-center w-full"
|
|
||||||
style={{
|
|
||||||
marginTop: 16,
|
|
||||||
marginBottom: 16,
|
|
||||||
}}
|
}}
|
||||||
>
|
onJoin={() => {
|
||||||
<View className="flex-1">
|
setStep('join')
|
||||||
<Divider />
|
|
||||||
</View>
|
|
||||||
<Text className="mx-3 text-gray-500 text-sm">或</Text>
|
|
||||||
<View className="flex-1">
|
|
||||||
<Divider />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<AButton variant="outline">加入已有空间</AButton>
|
|
||||||
</View> */}
|
|
||||||
|
|
||||||
{/* <View className="px-4 flex-1">
|
|
||||||
<Accordion
|
|
||||||
size="md"
|
|
||||||
variant="unfilled"
|
|
||||||
type="multiple"
|
|
||||||
isCollapsible={true}
|
|
||||||
isDisabled={false}
|
|
||||||
value={accordion}
|
|
||||||
onValueChange={(value) => {
|
|
||||||
setAccordion(value)
|
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
<AccordionItem value="a">
|
|
||||||
<AccordionHeader>
|
|
||||||
<AccordionTrigger
|
|
||||||
style={{
|
|
||||||
paddingLeft: 0,
|
|
||||||
paddingRight: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ isExpanded }: { isExpanded: boolean }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AccordionTitleText className="font-semibold text-lg">
|
|
||||||
我的邀请码
|
|
||||||
</AccordionTitleText>
|
|
||||||
{isExpanded
|
|
||||||
? (
|
|
||||||
<AccordionIcon as={ChevronUpIcon} className="ml-3" />
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
<AccordionIcon as={ChevronDownIcon} className="ml-3" />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</AccordionTrigger>
|
|
||||||
</AccordionHeader>
|
|
||||||
<AccordionContent style={{
|
|
||||||
marginBottom: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TouchableOpacity className="flex-row items-center justify-center ">
|
|
||||||
<Text className="font-bold text-3xl tracking-[4px] mr-3">123456</Text>
|
|
||||||
<LucideIcon icon="Copy" size={16} color="blue" clickable={false} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<View className="items-center justify-center">
|
|
||||||
<ADivider direction="horizontal" text="扫描二维码" />
|
|
||||||
<QRCode
|
|
||||||
size={120}
|
|
||||||
value="http://awesome.link.qr"
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</StepFade>
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
</Accordion>
|
|
||||||
<View className="mt-4 flex-1">
|
|
||||||
<View className="flex flex-row items-center justify-between">
|
|
||||||
<Text className="font-semibold text-lg">空间成员</Text>
|
|
||||||
<Badge size="lg" variant="solid" action="muted">
|
|
||||||
<BadgeText>3 人</BadgeText>
|
|
||||||
</Badge>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View>
|
<StepFade visible={step === 'join'}>
|
||||||
<FlatList
|
<JoinSpace
|
||||||
data={members}
|
onBack={() => {
|
||||||
keyExtractor={item => item.id.toString()}
|
setStep('home')
|
||||||
renderItem={({ item }) => (
|
|
||||||
<TouchableOpacity>
|
|
||||||
<HStack space="md" className="my-2 items-center">
|
|
||||||
<Avatar className="bg-indigo-600">
|
|
||||||
<AvatarFallbackText className="text-white text-lg">
|
|
||||||
{item.name}
|
|
||||||
</AvatarFallbackText>
|
|
||||||
<AvatarBadge />
|
|
||||||
</Avatar>
|
|
||||||
<VStack>
|
|
||||||
<HStack space="sm">
|
|
||||||
<Heading size="sm">{item.name}</Heading>
|
|
||||||
<Badge size="sm" variant="solid" action="muted">
|
|
||||||
<BadgeText>管理员</BadgeText>
|
|
||||||
</Badge>
|
|
||||||
</HStack>
|
|
||||||
<Text size="sm">Marketing Coordinator</Text>
|
|
||||||
</VStack>
|
|
||||||
|
|
||||||
<View className="ml-auto">
|
|
||||||
<Menu
|
|
||||||
placement="top"
|
|
||||||
offset={5}
|
|
||||||
trigger={triggerProps => (
|
|
||||||
<Pressable
|
|
||||||
{...triggerProps}
|
|
||||||
style={{
|
|
||||||
padding: 8,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
<LucideIcon icon="EllipsisVertical" size={20} clickable={false} />
|
|
||||||
</Pressable>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<MenuItem key="Add account" textValue="Add account">
|
|
||||||
<MenuItemLabel size="sm">添加为管理员</MenuItemLabel>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem key="Community" textValue="Community">
|
|
||||||
<MenuItemLabel size="sm">移出空间</MenuItemLabel>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</View>
|
|
||||||
</HStack>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</StepFade>
|
||||||
<AButton size="sm" className="mb-8 mt-4">退出该空间</AButton>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
</View> */}
|
<StepFade visible={step === 'invite'}>
|
||||||
|
<SpaceInviteAndMembers />
|
||||||
<EnterSapce />
|
</StepFade>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ function isWhiteListed(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const alovaInstance = createAlova({
|
const alovaInstance = createAlova({
|
||||||
baseURL: 'http://192.168.5.6:8086/app',
|
// baseURL: 'http://192.168.5.6:8086/app',
|
||||||
// baseURL: 'http://192.168.1.136:8086/app',
|
baseURL: 'http://192.168.1.136:8086/app',
|
||||||
requestAdapter: axiosRequestAdapter(),
|
requestAdapter: axiosRequestAdapter(),
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
cacheFor: null,
|
cacheFor: null,
|
||||||
|
|||||||
@@ -1,148 +1,219 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh">
|
<html lang="zh-CN">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8">
|
||||||
<title>高级邀请页面</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<style>
|
<title>初次登录引导页</title>
|
||||||
body {
|
<style>
|
||||||
|
/* 重置样式 */
|
||||||
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: "Inter", sans-serif;
|
padding: 0;
|
||||||
background: #f3f4f7;
|
box-sizing: border-box;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 顶部渐变 Header */
|
body {
|
||||||
.header {
|
|
||||||
width: 100%;
|
|
||||||
padding: 40px 24px;
|
|
||||||
background: linear-gradient(135deg, #4d8dff, #6fa5ff);
|
|
||||||
color: white;
|
|
||||||
font-size: 26px;
|
|
||||||
font-weight: 600;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 内容卡片 */
|
|
||||||
.container {
|
|
||||||
margin-top: -32px;
|
|
||||||
padding: 0 24px 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background: white;
|
|
||||||
padding: 24px;
|
|
||||||
border-radius: 20px;
|
|
||||||
box-shadow: 0 6px 20px rgba(0,0,0,0.06);
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invite-code {
|
|
||||||
font-size: 40px;
|
|
||||||
font-weight: 700;
|
|
||||||
letter-spacing: 4px;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy-btn {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 8px;
|
align-items: center;
|
||||||
font-size: 14px;
|
height: 100vh;
|
||||||
color: #4d8dff;
|
background: #f7f7f7;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 二维码卡片设计 */
|
.onboarding-container {
|
||||||
.qr-card {
|
width: 90%;
|
||||||
background: white;
|
max-width: 400px;
|
||||||
padding: 20px;
|
background: #fff;
|
||||||
border-radius: 20px;
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: 0 4px 14px rgba(0,0,0,0.05);
|
padding: 24px;
|
||||||
|
animation: fadeIn 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.onboarding-step {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.onboarding-step.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ccc;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-img {
|
.buttons {
|
||||||
width: 190px;
|
display: flex;
|
||||||
height: 190px;
|
justify-content: space-between;
|
||||||
border-radius: 12px;
|
width: 100%;
|
||||||
border: 1px solid #eee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.btn {
|
||||||
background: #eef1ff;
|
padding: 10px 20px;
|
||||||
padding: 6px 14px;
|
border-radius: 8px;
|
||||||
border-radius: 14px;
|
border: none;
|
||||||
font-size: 14px;
|
cursor: pointer;
|
||||||
color: #4d5bff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.member-item {
|
|
||||||
padding: 14px 0;
|
|
||||||
border-bottom: 1px solid #f0f0f0;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member-item:last-child {
|
.btn-primary {
|
||||||
border-bottom: none;
|
background: #4CAF50;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #e0e0e0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: #ddd;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0 4px;
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot.active {
|
||||||
|
background: #4CAF50;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- Header -->
|
<div class="onboarding-container">
|
||||||
<div class="header">邀请好友加入空间</div>
|
<!-- 步骤 1 -->
|
||||||
|
<div class="onboarding-step active" id="step-1">
|
||||||
<!-- 内容 -->
|
<div class="avatar">
|
||||||
<div class="container">
|
<img src="https://placekitten.com/200/200" alt="头像">
|
||||||
|
</div>
|
||||||
<!-- 邀请码卡片 -->
|
<div class="username">张三</div>
|
||||||
<div class="card">
|
<div class="info-text">欢迎加入我们的平台!让我们来完成一些设置吧。</div>
|
||||||
<div class="title-row">
|
<div class="buttons">
|
||||||
<div class="title">我的邀请码</div>
|
<button class="btn btn-secondary" disabled>上一步</button>
|
||||||
|
<button class="btn btn-primary" onclick="nextStep()">下一步</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="invite-code">123456</div>
|
<!-- 步骤 2 -->
|
||||||
<div class="copy-btn">点击复制邀请码</div>
|
<div class="onboarding-step" id="step-2">
|
||||||
|
<div class="username">选择你的兴趣</div>
|
||||||
|
<div class="info-text">帮助我们推荐更适合你的内容</div>
|
||||||
|
<div class="buttons">
|
||||||
|
<button class="btn btn-secondary" onclick="prevStep()">上一步</button>
|
||||||
|
<button class="btn btn-primary" onclick="nextStep()">下一步</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 二维码卡片 -->
|
<!-- 步骤 3 -->
|
||||||
<div class="qr-card">
|
<div class="onboarding-step" id="step-3">
|
||||||
<img
|
<div class="username">完成!</div>
|
||||||
src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=demo"
|
<div class="info-text">你已经准备好开始使用了</div>
|
||||||
class="qr-img"
|
<div class="buttons">
|
||||||
alt="二维码"
|
<button class="btn btn-secondary" onclick="prevStep()">上一步</button>
|
||||||
/>
|
<button class="btn btn-primary" onclick="finishOnboarding()">开始使用</button>
|
||||||
<p style="margin-top: 12px; color: #666; font-size: 14px;">
|
</div>
|
||||||
扫码加入我的共享空间
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 成员卡片 -->
|
<!-- 进度指示器 -->
|
||||||
<div class="card">
|
<div class="progress">
|
||||||
<div class="title-row">
|
<div class="dot active" id="dot-1"></div>
|
||||||
<div class="title">空间成员</div>
|
<div class="dot" id="dot-2"></div>
|
||||||
<div class="badge">3 人</div>
|
<div class="dot" id="dot-3"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="member-item">成员 A</div>
|
<script>
|
||||||
<div class="member-item">成员 B</div>
|
let currentStep = 1;
|
||||||
<div class="member-item">成员 C</div>
|
const totalSteps = 3;
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
function showStep(step) {
|
||||||
|
for (let i = 1; i <= totalSteps; i++) {
|
||||||
|
const s = document.getElementById(`step-${i}`);
|
||||||
|
const d = document.getElementById(`dot-${i}`);
|
||||||
|
if (i === step) {
|
||||||
|
s.classList.add('active');
|
||||||
|
d.classList.add('active');
|
||||||
|
} else {
|
||||||
|
s.classList.remove('active');
|
||||||
|
d.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextStep() {
|
||||||
|
if (currentStep < totalSteps) {
|
||||||
|
currentStep++;
|
||||||
|
showStep(currentStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevStep() {
|
||||||
|
if (currentStep > 1) {
|
||||||
|
currentStep--;
|
||||||
|
showStep(currentStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishOnboarding() {
|
||||||
|
alert('初始化完成,进入应用!');
|
||||||
|
// 这里可以跳转到首页或关闭引导页
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// Code generated by hertz generator.
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cn/oneao/base-go/biz/router/middleware"
|
||||||
|
"cn/oneao/base-go/db"
|
||||||
|
"cn/oneao/base-go/db/repo"
|
||||||
|
"cn/oneao/base-go/utils"
|
||||||
|
"cn/oneao/base-go/utils/errorx"
|
||||||
|
"cn/oneao/base-go/utils/idgen"
|
||||||
|
"cn/oneao/base-go/utils/response"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
space "cn/oneao/base-go/biz/model/space"
|
||||||
|
"github.com/cloudwego/hertz/pkg/app"
|
||||||
|
"github.com/cloudwego/hertz/pkg/protocol/consts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// InsertSpace .
|
||||||
|
// @router /space/insert [POST]
|
||||||
|
func InsertSpace(ctx context.Context, c *app.RequestContext) {
|
||||||
|
var err error
|
||||||
|
var req space.InsertSpaceParams
|
||||||
|
err = c.BindAndValidate(&req)
|
||||||
|
if err != nil {
|
||||||
|
c.String(consts.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userID := middleware.GetUserID(ctx)
|
||||||
|
|
||||||
|
// 检查该用户是否已经加入空间了
|
||||||
|
_, err = db.Queries.GetSpaceByUserId(ctx, userID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if errorx.IsNotFound(err) {
|
||||||
|
// 忽略
|
||||||
|
} else {
|
||||||
|
errorx.AddError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.Fail(c).Message("请先退出已加入的空间").Send()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成邀请码
|
||||||
|
var inviteCode string
|
||||||
|
|
||||||
|
for {
|
||||||
|
// 生成邀请码
|
||||||
|
code, err := utils.GenerateCode(6)
|
||||||
|
if err != nil {
|
||||||
|
errorx.AddError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据库是否存在
|
||||||
|
_, err = db.Queries.GetSpaceByInviteCode(ctx, code)
|
||||||
|
if err != nil {
|
||||||
|
if errorx.IsNotFound(err) {
|
||||||
|
// 不存在,唯一,直接使用
|
||||||
|
inviteCode = code
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
// 系统错误
|
||||||
|
errorx.AddError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果存在,继续循环重新生成
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建空间
|
||||||
|
spaceId := idgen.NextId()
|
||||||
|
params := repo.InsertSpaceParams{
|
||||||
|
ID: spaceId,
|
||||||
|
InviteCode: inviteCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Queries.InsertSpace(ctx, params)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errorx.AddError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp space.InsertSpaceResult
|
||||||
|
resp.Id = spaceId
|
||||||
|
resp.InviteCode = inviteCode
|
||||||
|
|
||||||
|
response.Success(c).Data(resp).Send()
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.0
|
||||||
|
// protoc v4.25.3
|
||||||
|
// source: index.proto
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "cn/oneao/base-go/biz/model/api"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
var File_index_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_index_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x73,
|
||||||
|
0x70, 0x61, 0x63, 0x65, 0x1a, 0x09, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||||
|
0x17, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70,
|
||||||
|
0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x64, 0x0a, 0x0c, 0x53, 0x70, 0x61, 0x63,
|
||||||
|
0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x49, 0x6e, 0x73, 0x65,
|
||||||
|
0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e,
|
||||||
|
0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
|
||||||
|
0x73, 0x1a, 0x18, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74,
|
||||||
|
0x53, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x11, 0xd2, 0xc1, 0x18,
|
||||||
|
0x0d, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x42, 0x22,
|
||||||
|
0x5a, 0x20, 0x63, 0x6e, 0x2f, 0x6f, 0x6e, 0x65, 0x61, 0x6f, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2d,
|
||||||
|
0x67, 0x6f, 0x2f, 0x62, 0x69, 0x7a, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x73, 0x70, 0x61,
|
||||||
|
0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_index_proto_goTypes = []interface{}{
|
||||||
|
(*InsertSpaceParams)(nil), // 0: space.InsertSpaceParams
|
||||||
|
(*InsertSpaceResult)(nil), // 1: space.InsertSpaceResult
|
||||||
|
}
|
||||||
|
var file_index_proto_depIdxs = []int32{
|
||||||
|
0, // 0: space.SpaceService.InsertSpace:input_type -> space.InsertSpaceParams
|
||||||
|
1, // 1: space.SpaceService.InsertSpace:output_type -> space.InsertSpaceResult
|
||||||
|
1, // [1:2] is the sub-list for method output_type
|
||||||
|
0, // [0:1] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_index_proto_init() }
|
||||||
|
func file_index_proto_init() {
|
||||||
|
if File_index_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_init()
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_index_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_index_proto_goTypes,
|
||||||
|
DependencyIndexes: file_index_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_index_proto = out.File
|
||||||
|
file_index_proto_rawDesc = nil
|
||||||
|
file_index_proto_goTypes = nil
|
||||||
|
file_index_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,486 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.0
|
||||||
|
// protoc v4.25.3
|
||||||
|
// source: space/space_types.proto
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "cn/oneao/base-go/biz/model/api"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 创建空间
|
||||||
|
type InsertSpaceParams struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceParams) Reset() {
|
||||||
|
*x = InsertSpaceParams{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceParams) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*InsertSpaceParams) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *InsertSpaceParams) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use InsertSpaceParams.ProtoReflect.Descriptor instead.
|
||||||
|
func (*InsertSpaceParams) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type InsertSpaceResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Id int64 `protobuf:"varint,1,opt,name=Id,proto3" form:"id" json:"id"`
|
||||||
|
InviteCode string `protobuf:"bytes,2,opt,name=InviteCode,proto3" form:"invite_code" json:"invite_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceResult) Reset() {
|
||||||
|
*x = InsertSpaceResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*InsertSpaceResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *InsertSpaceResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use InsertSpaceResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*InsertSpaceResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceResult) GetId() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Id
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceResult) GetInviteCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.InviteCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解散空间
|
||||||
|
type DeleteSpaceParams struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceParams) Reset() {
|
||||||
|
*x = DeleteSpaceParams{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceParams) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DeleteSpaceParams) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceParams) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DeleteSpaceParams.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DeleteSpaceParams) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteSpaceResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceResult) Reset() {
|
||||||
|
*x = DeleteSpaceResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DeleteSpaceResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DeleteSpaceResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DeleteSpaceResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DeleteSpaceResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取空间下的所有用户
|
||||||
|
type QuerySpaceUsersParams struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
SpaceId int64 `protobuf:"varint,1,opt,name=SpaceId,proto3" form:"space_id" json:"space_id" vd:"$ != 0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersParams) Reset() {
|
||||||
|
*x = QuerySpaceUsersParams{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersParams) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*QuerySpaceUsersParams) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersParams) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use QuerySpaceUsersParams.ProtoReflect.Descriptor instead.
|
||||||
|
func (*QuerySpaceUsersParams) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersParams) GetSpaceId() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.SpaceId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpaceUser struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SpaceUser) Reset() {
|
||||||
|
*x = SpaceUser{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SpaceUser) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SpaceUser) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *SpaceUser) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[5]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use SpaceUser.ProtoReflect.Descriptor instead.
|
||||||
|
func (*SpaceUser) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuerySpaceUsersResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersResult) Reset() {
|
||||||
|
*x = QuerySpaceUsersResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*QuerySpaceUsersResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *QuerySpaceUsersResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_types_proto_msgTypes[6]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use QuerySpaceUsersResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*QuerySpaceUsersResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_types_proto_rawDescGZIP(), []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_space_space_types_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_space_space_types_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x17, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x79,
|
||||||
|
0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||||
|
0x1a, 0x09, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x49,
|
||||||
|
0x6e, 0x73, 0x65, 0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
|
||||||
|
0x22, 0x5c, 0x0a, 0x11, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x52,
|
||||||
|
0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x03, 0x42, 0x06, 0xca, 0xbb, 0x18, 0x02, 0x69, 0x64, 0x52, 0x02, 0x49, 0x64, 0x12, 0x2f, 0x0a,
|
||||||
|
0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x42, 0x0f, 0xca, 0xbb, 0x18, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f,
|
||||||
|
0x64, 0x65, 0x52, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x13,
|
||||||
|
0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x73, 0x22, 0x13, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x70, 0x61,
|
||||||
|
0x63, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x49, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72,
|
||||||
|
0x79, 0x53, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d,
|
||||||
|
0x73, 0x12, 0x30, 0x0a, 0x07, 0x53, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x03, 0x42, 0x16, 0xca, 0xbb, 0x18, 0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64,
|
||||||
|
0xda, 0xbb, 0x18, 0x06, 0x24, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x52, 0x07, 0x53, 0x70, 0x61, 0x63,
|
||||||
|
0x65, 0x49, 0x64, 0x22, 0x0b, 0x0a, 0x09, 0x53, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73, 0x65, 0x72,
|
||||||
|
0x22, 0x17, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73,
|
||||||
|
0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x22, 0x5a, 0x20, 0x63, 0x6e, 0x2f,
|
||||||
|
0x6f, 0x6e, 0x65, 0x61, 0x6f, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2d, 0x67, 0x6f, 0x2f, 0x62, 0x69,
|
||||||
|
0x7a, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_space_space_types_proto_rawDescOnce sync.Once
|
||||||
|
file_space_space_types_proto_rawDescData = file_space_space_types_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_space_space_types_proto_rawDescGZIP() []byte {
|
||||||
|
file_space_space_types_proto_rawDescOnce.Do(func() {
|
||||||
|
file_space_space_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_space_space_types_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_space_space_types_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_space_space_types_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||||
|
var file_space_space_types_proto_goTypes = []interface{}{
|
||||||
|
(*InsertSpaceParams)(nil), // 0: space.InsertSpaceParams
|
||||||
|
(*InsertSpaceResult)(nil), // 1: space.InsertSpaceResult
|
||||||
|
(*DeleteSpaceParams)(nil), // 2: space.DeleteSpaceParams
|
||||||
|
(*DeleteSpaceResult)(nil), // 3: space.DeleteSpaceResult
|
||||||
|
(*QuerySpaceUsersParams)(nil), // 4: space.QuerySpaceUsersParams
|
||||||
|
(*SpaceUser)(nil), // 5: space.SpaceUser
|
||||||
|
(*QuerySpaceUsersResult)(nil), // 6: space.QuerySpaceUsersResult
|
||||||
|
}
|
||||||
|
var file_space_space_types_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_space_space_types_proto_init() }
|
||||||
|
func file_space_space_types_proto_init() {
|
||||||
|
if File_space_space_types_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_space_space_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*InsertSpaceParams); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*InsertSpaceResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*DeleteSpaceParams); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*DeleteSpaceResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*QuerySpaceUsersParams); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*SpaceUser); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*QuerySpaceUsersResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_space_space_types_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 7,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_space_space_types_proto_goTypes,
|
||||||
|
DependencyIndexes: file_space_space_types_proto_depIdxs,
|
||||||
|
MessageInfos: file_space_space_types_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_space_space_types_proto = out.File
|
||||||
|
file_space_space_types_proto_rawDesc = nil
|
||||||
|
file_space_space_types_proto_goTypes = nil
|
||||||
|
file_space_space_types_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.0
|
||||||
|
// protoc v4.25.3
|
||||||
|
// source: space/space_user_types.proto
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "cn/oneao/base-go/biz/model/api"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 加入空间
|
||||||
|
type InsertSpaceUserParams struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
InviteCode int64 `protobuf:"varint,1,opt,name=InviteCode,proto3" form:"invite_code" json:"invite_code"` // 邀请码
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserParams) Reset() {
|
||||||
|
*x = InsertSpaceUserParams{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_user_types_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserParams) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*InsertSpaceUserParams) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserParams) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_user_types_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use InsertSpaceUserParams.ProtoReflect.Descriptor instead.
|
||||||
|
func (*InsertSpaceUserParams) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_user_types_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserParams) GetInviteCode() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.InviteCode
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type InsertSpaceUserResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
SpaceId int64 `protobuf:"varint,1,opt,name=SpaceId,proto3" form:"space_id" json:"space_id"`
|
||||||
|
InviteCode string `protobuf:"bytes,2,opt,name=InviteCode,proto3" form:"invite_code" json:"invite_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserResult) Reset() {
|
||||||
|
*x = InsertSpaceUserResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_space_space_user_types_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*InsertSpaceUserResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_space_space_user_types_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use InsertSpaceUserResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*InsertSpaceUserResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_space_space_user_types_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserResult) GetSpaceId() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.SpaceId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *InsertSpaceUserResult) GetInviteCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.InviteCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_space_space_user_types_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_space_space_user_types_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x1c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x73,
|
||||||
|
0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05,
|
||||||
|
0x73, 0x70, 0x61, 0x63, 0x65, 0x1a, 0x09, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x22, 0x48, 0x0a, 0x15, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x55,
|
||||||
|
0x73, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2f, 0x0a, 0x0a, 0x49, 0x6e, 0x76,
|
||||||
|
0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x0f, 0xca,
|
||||||
|
0xbb, 0x18, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x0a,
|
||||||
|
0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x70, 0x0a, 0x15, 0x49, 0x6e,
|
||||||
|
0x73, 0x65, 0x72, 0x74, 0x53, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73,
|
||||||
|
0x75, 0x6c, 0x74, 0x12, 0x26, 0x0a, 0x07, 0x53, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x18, 0x01,
|
||||||
|
0x20, 0x01, 0x28, 0x03, 0x42, 0x0c, 0xca, 0xbb, 0x18, 0x08, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f,
|
||||||
|
0x69, 0x64, 0x52, 0x07, 0x53, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0a, 0x49,
|
||||||
|
0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||||
|
0x0f, 0xca, 0xbb, 0x18, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65,
|
||||||
|
0x52, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x22, 0x5a, 0x20,
|
||||||
|
0x63, 0x6e, 0x2f, 0x6f, 0x6e, 0x65, 0x61, 0x6f, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2d, 0x67, 0x6f,
|
||||||
|
0x2f, 0x62, 0x69, 0x7a, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_space_space_user_types_proto_rawDescOnce sync.Once
|
||||||
|
file_space_space_user_types_proto_rawDescData = file_space_space_user_types_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_space_space_user_types_proto_rawDescGZIP() []byte {
|
||||||
|
file_space_space_user_types_proto_rawDescOnce.Do(func() {
|
||||||
|
file_space_space_user_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_space_space_user_types_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_space_space_user_types_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_space_space_user_types_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_space_space_user_types_proto_goTypes = []interface{}{
|
||||||
|
(*InsertSpaceUserParams)(nil), // 0: space.InsertSpaceUserParams
|
||||||
|
(*InsertSpaceUserResult)(nil), // 1: space.InsertSpaceUserResult
|
||||||
|
}
|
||||||
|
var file_space_space_user_types_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_space_space_user_types_proto_init() }
|
||||||
|
func file_space_space_user_types_proto_init() {
|
||||||
|
if File_space_space_user_types_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_space_space_user_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*InsertSpaceUserParams); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_space_space_user_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*InsertSpaceUserResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_space_space_user_types_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_space_space_user_types_proto_goTypes,
|
||||||
|
DependencyIndexes: file_space_space_user_types_proto_depIdxs,
|
||||||
|
MessageInfos: file_space_space_user_types_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_space_space_user_types_proto = out.File
|
||||||
|
file_space_space_user_types_proto_rawDesc = nil
|
||||||
|
file_space_space_user_types_proto_goTypes = nil
|
||||||
|
file_space_space_user_types_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -5,12 +5,15 @@ package router
|
|||||||
import (
|
import (
|
||||||
auth "cn/oneao/base-go/biz/router/auth"
|
auth "cn/oneao/base-go/biz/router/auth"
|
||||||
money "cn/oneao/base-go/biz/router/money"
|
money "cn/oneao/base-go/biz/router/money"
|
||||||
|
space "cn/oneao/base-go/biz/router/space"
|
||||||
"github.com/cloudwego/hertz/pkg/app/server"
|
"github.com/cloudwego/hertz/pkg/app/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GeneratedRegister registers routers generated by IDL.
|
// GeneratedRegister registers routers generated by IDL.
|
||||||
func GeneratedRegister(r *server.Hertz) {
|
func GeneratedRegister(r *server.Hertz) {
|
||||||
//INSERT_POINT: DO NOT DELETE THIS LINE!
|
//INSERT_POINT: DO NOT DELETE THIS LINE!
|
||||||
|
space.Register(r)
|
||||||
|
|
||||||
auth.Register(r)
|
auth.Register(r)
|
||||||
money.Register(r)
|
money.Register(r)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Code generated by hertz generator. DO NOT EDIT.
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
space "cn/oneao/base-go/biz/handler/space"
|
||||||
|
"github.com/cloudwego/hertz/pkg/app/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file will register all the routes of the services in the master idl.
|
||||||
|
And it will update automatically when you use the "update" command for the idl.
|
||||||
|
So don't modify the contents of the file, or your code will be deleted when it is updated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Register register routes based on the IDL 'api.${HTTP Method}' annotation.
|
||||||
|
func Register(r *server.Hertz) {
|
||||||
|
|
||||||
|
root := r.Group("/", rootMw()...)
|
||||||
|
{
|
||||||
|
_space := root.Group("/space", _spaceMw()...)
|
||||||
|
_space.POST("/insert", append(_insertspaceMw(), space.InsertSpace)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Code generated by hertz generator.
|
||||||
|
|
||||||
|
package space
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cloudwego/hertz/pkg/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
func rootMw() []app.HandlerFunc {
|
||||||
|
// your code...
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _spaceMw() []app.HandlerFunc {
|
||||||
|
// your code...
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _insertspaceMw() []app.HandlerFunc {
|
||||||
|
// your code...
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-- 新增分享空间
|
||||||
|
-- name: InsertSpace :exec
|
||||||
|
INSERT INTO space (id,invite_code) VALUES ($1,$2);
|
||||||
|
|
||||||
|
-- 删除分享空间
|
||||||
|
-- name: DeleteSpace :exec
|
||||||
|
DELETE FROM space WHERE id = $1;
|
||||||
|
|
||||||
|
-- 根据id获取分享空间信息
|
||||||
|
-- name: GetSpaceById :one
|
||||||
|
SELECT * FROM space WHERE id = $1;
|
||||||
|
|
||||||
|
-- 查询用户所在的空间信息
|
||||||
|
-- name: GetSpaceByUserId :one
|
||||||
|
SELECT s.*
|
||||||
|
FROM space s
|
||||||
|
JOIN space_user m
|
||||||
|
ON s.id = m.space_id
|
||||||
|
WHERE m.user_id = $1;
|
||||||
|
|
||||||
|
-- 获取空间下的所有用户信息
|
||||||
|
-- name: GetSpaceUsers :many
|
||||||
|
SELECT
|
||||||
|
u.id as user_id,
|
||||||
|
u.username,
|
||||||
|
su.role,
|
||||||
|
su.join_time
|
||||||
|
FROM space_user su
|
||||||
|
JOIN space s ON su.space_id = s.id
|
||||||
|
JOIN user_info u ON su.user_id = u.id
|
||||||
|
WHERE s.id = $1
|
||||||
|
ORDER BY su.join_time ASC;
|
||||||
|
|
||||||
|
-- 根据验证码获取空间
|
||||||
|
-- name: GetSpaceByInviteCode :one
|
||||||
|
SELECT * FROM space WHERE invite_code = $1;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
-- 加入空间
|
||||||
|
-- name: InsertSpaceUser :exec
|
||||||
|
INSERT INTO space_user(id,space_id,user_id,role)
|
||||||
|
VALUES ($1,$2,$3,$4);
|
||||||
|
|
||||||
|
-- 删除空间下的单个用户
|
||||||
|
-- name: DeleteSpaceUser :exec
|
||||||
|
DELETE FROM space_user WHERE user_id = $1;
|
||||||
|
|
||||||
|
-- 删除空间下的所有用户
|
||||||
|
-- name: DeleteSpaceUserAll :exec
|
||||||
|
DELETE FROM space_user WHERE space_id = $1;
|
||||||
|
|
||||||
|
-- 修改角色
|
||||||
|
-- name: UpdateSpaceUserRole :exec
|
||||||
|
UPDATE space_user
|
||||||
|
SET role = $1
|
||||||
|
WHERE user_id = $2
|
||||||
|
AND space_id = $3;
|
||||||
@@ -38,6 +38,34 @@ type MoneyUserCategory struct {
|
|||||||
CreateTime pgtype.Timestamp
|
CreateTime pgtype.Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 共享空间(一个空间包含多个成员)
|
||||||
|
type Space struct {
|
||||||
|
// 空间ID
|
||||||
|
ID int64
|
||||||
|
// 空间名称
|
||||||
|
Name pgtype.Text
|
||||||
|
// 空间邀请码
|
||||||
|
InviteCode string
|
||||||
|
// 空间创建时间
|
||||||
|
CreateTime pgtype.Timestamp
|
||||||
|
// 空间更新时间
|
||||||
|
UpdateTime pgtype.Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// 共享空间成员表
|
||||||
|
type SpaceUser struct {
|
||||||
|
// 主键ID
|
||||||
|
ID int64
|
||||||
|
// 所属空间ID
|
||||||
|
SpaceID int64
|
||||||
|
// 用户ID(唯一,每用户只加入一个空间)
|
||||||
|
UserID int64
|
||||||
|
// 成员角色:0创建者 1管理员 2普通
|
||||||
|
Role int32
|
||||||
|
// 加入空间时间
|
||||||
|
JoinTime pgtype.Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
ID int64
|
ID int64
|
||||||
SeqNo pgtype.Int4
|
SeqNo pgtype.Int4
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.30.0
|
||||||
|
// source: space.sql
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
const deleteSpace = `-- name: DeleteSpace :exec
|
||||||
|
DELETE FROM space WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 删除分享空间
|
||||||
|
func (q *Queries) DeleteSpace(ctx context.Context, id int64) error {
|
||||||
|
_, err := q.db.Exec(ctx, deleteSpace, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSpaceById = `-- name: GetSpaceById :one
|
||||||
|
SELECT id, name, invite_code, create_time, update_time FROM space WHERE id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 根据id获取分享空间信息
|
||||||
|
func (q *Queries) GetSpaceById(ctx context.Context, id int64) (Space, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getSpaceById, id)
|
||||||
|
var i Space
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.InviteCode,
|
||||||
|
&i.CreateTime,
|
||||||
|
&i.UpdateTime,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSpaceByInviteCode = `-- name: GetSpaceByInviteCode :one
|
||||||
|
SELECT id, name, invite_code, create_time, update_time FROM space WHERE invite_code = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 根据验证码获取空间
|
||||||
|
func (q *Queries) GetSpaceByInviteCode(ctx context.Context, inviteCode string) (Space, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getSpaceByInviteCode, inviteCode)
|
||||||
|
var i Space
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.InviteCode,
|
||||||
|
&i.CreateTime,
|
||||||
|
&i.UpdateTime,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSpaceByUserId = `-- name: GetSpaceByUserId :one
|
||||||
|
SELECT s.id, s.name, s.invite_code, s.create_time, s.update_time
|
||||||
|
FROM space s
|
||||||
|
JOIN space_user m
|
||||||
|
ON s.id = m.space_id
|
||||||
|
WHERE m.user_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 查询用户所在的空间信息
|
||||||
|
func (q *Queries) GetSpaceByUserId(ctx context.Context, userID int64) (Space, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getSpaceByUserId, userID)
|
||||||
|
var i Space
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.InviteCode,
|
||||||
|
&i.CreateTime,
|
||||||
|
&i.UpdateTime,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSpaceUsers = `-- name: GetSpaceUsers :many
|
||||||
|
SELECT
|
||||||
|
u.id as user_id,
|
||||||
|
u.username,
|
||||||
|
su.role,
|
||||||
|
su.join_time
|
||||||
|
FROM space_user su
|
||||||
|
JOIN space s ON su.space_id = s.id
|
||||||
|
JOIN user_info u ON su.user_id = u.id
|
||||||
|
WHERE s.id = $1
|
||||||
|
ORDER BY su.join_time ASC
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetSpaceUsersRow struct {
|
||||||
|
UserID int64
|
||||||
|
Username pgtype.Text
|
||||||
|
Role int32
|
||||||
|
JoinTime pgtype.Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取空间下的所有用户信息
|
||||||
|
func (q *Queries) GetSpaceUsers(ctx context.Context, id int64) ([]GetSpaceUsersRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, getSpaceUsers, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetSpaceUsersRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetSpaceUsersRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.UserID,
|
||||||
|
&i.Username,
|
||||||
|
&i.Role,
|
||||||
|
&i.JoinTime,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertSpace = `-- name: InsertSpace :exec
|
||||||
|
INSERT INTO space (id,invite_code) VALUES ($1,$2)
|
||||||
|
`
|
||||||
|
|
||||||
|
type InsertSpaceParams struct {
|
||||||
|
ID int64
|
||||||
|
InviteCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增分享空间
|
||||||
|
func (q *Queries) InsertSpace(ctx context.Context, arg InsertSpaceParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, insertSpace, arg.ID, arg.InviteCode)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// sqlc v1.30.0
|
||||||
|
// source: space_user.sql
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
const deleteSpaceUser = `-- name: DeleteSpaceUser :exec
|
||||||
|
DELETE FROM space_user WHERE user_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 删除空间下的单个用户
|
||||||
|
func (q *Queries) DeleteSpaceUser(ctx context.Context, userID int64) error {
|
||||||
|
_, err := q.db.Exec(ctx, deleteSpaceUser, userID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteSpaceUserAll = `-- name: DeleteSpaceUserAll :exec
|
||||||
|
DELETE FROM space_user WHERE space_id = $1
|
||||||
|
`
|
||||||
|
|
||||||
|
// 删除空间下的所有用户
|
||||||
|
func (q *Queries) DeleteSpaceUserAll(ctx context.Context, spaceID int64) error {
|
||||||
|
_, err := q.db.Exec(ctx, deleteSpaceUserAll, spaceID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertSpaceUser = `-- name: InsertSpaceUser :exec
|
||||||
|
INSERT INTO space_user(id,space_id,user_id,role)
|
||||||
|
VALUES ($1,$2,$3,$4)
|
||||||
|
`
|
||||||
|
|
||||||
|
type InsertSpaceUserParams struct {
|
||||||
|
ID int64
|
||||||
|
SpaceID int64
|
||||||
|
UserID int64
|
||||||
|
Role int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加入空间
|
||||||
|
func (q *Queries) InsertSpaceUser(ctx context.Context, arg InsertSpaceUserParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, insertSpaceUser,
|
||||||
|
arg.ID,
|
||||||
|
arg.SpaceID,
|
||||||
|
arg.UserID,
|
||||||
|
arg.Role,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateSpaceUserRole = `-- name: UpdateSpaceUserRole :exec
|
||||||
|
UPDATE space_user
|
||||||
|
SET role = $1
|
||||||
|
WHERE user_id = $2
|
||||||
|
AND space_id = $3
|
||||||
|
`
|
||||||
|
|
||||||
|
type UpdateSpaceUserRoleParams struct {
|
||||||
|
Role int32
|
||||||
|
UserID int64
|
||||||
|
SpaceID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改角色
|
||||||
|
func (q *Queries) UpdateSpaceUserRole(ctx context.Context, arg UpdateSpaceUserRoleParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, updateSpaceUserRole, arg.Role, arg.UserID, arg.SpaceID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -41,8 +41,37 @@ CREATE TABLE money_user_category(
|
|||||||
create_time timestamp DEFAULT CURRENT_TIMESTAMP
|
create_time timestamp DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE share_space(
|
-- 共享空间表
|
||||||
id BIGINT PRIMARY KEY,
|
CREATE TABLE space (
|
||||||
name VARCHAR(100) NOT NULL
|
id BIGSERIAL PRIMARY KEY,
|
||||||
)
|
name VARCHAR(100) DEFAULT '',
|
||||||
|
invite_code VARCHAR(30) NOT NULL,
|
||||||
|
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 注释
|
||||||
|
COMMENT ON TABLE space IS '共享空间(一个空间包含多个成员)';
|
||||||
|
COMMENT ON COLUMN space.id IS '空间ID';
|
||||||
|
COMMENT ON COLUMN space.name IS '空间名称';
|
||||||
|
COMMENT ON COLUMN space.invite_code IS '空间邀请码';
|
||||||
|
COMMENT ON COLUMN space.create_time IS '空间创建时间';
|
||||||
|
COMMENT ON COLUMN space.update_time IS '空间更新时间';
|
||||||
|
|
||||||
|
|
||||||
|
-- 空间成员表(每个用户只能加入一个空间)
|
||||||
|
CREATE TABLE space_user (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
space_id BIGINT NOT NULL,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
role INT NOT NULL DEFAULT 2,
|
||||||
|
join_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 注释
|
||||||
|
COMMENT ON TABLE space_user IS '共享空间成员表';
|
||||||
|
COMMENT ON COLUMN space_user.id IS '主键ID';
|
||||||
|
COMMENT ON COLUMN space_user.space_id IS '所属空间ID';
|
||||||
|
COMMENT ON COLUMN space_user.user_id IS '用户ID(唯一,每用户只加入一个空间)';
|
||||||
|
COMMENT ON COLUMN space_user.role IS '成员角色:0创建者 1管理员 2普通';
|
||||||
|
COMMENT ON COLUMN space_user.join_time IS '加入空间时间';
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package space;
|
||||||
|
|
||||||
|
option go_package = "space";
|
||||||
|
|
||||||
|
import "api.proto";
|
||||||
|
|
||||||
|
import "space/space_types.proto";
|
||||||
|
//import "space/space_user_types.proto";
|
||||||
|
|
||||||
|
service SpaceService {
|
||||||
|
rpc InsertSpace(InsertSpaceParams) returns (InsertSpaceResult){
|
||||||
|
option (api.post) = '/space/insert';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package space;
|
||||||
|
|
||||||
|
option go_package = "space";
|
||||||
|
|
||||||
|
import "api.proto";
|
||||||
|
|
||||||
|
// 创建空间
|
||||||
|
message InsertSpaceParams {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message InsertSpaceResult {
|
||||||
|
int64 Id = 1 [(api.body)="id"];
|
||||||
|
string InviteCode = 2 [(api.body)="invite_code"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解散空间
|
||||||
|
message DeleteSpaceParams {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteSpaceResult {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取空间下的所有用户
|
||||||
|
message QuerySpaceUsersParams{
|
||||||
|
int64 SpaceId = 1 [(api.body)="space_id", (api.vd)="$ != 0"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message SpaceUser {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message QuerySpaceUsersResult{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package space;
|
||||||
|
|
||||||
|
option go_package = "space";
|
||||||
|
|
||||||
|
import "api.proto";
|
||||||
|
|
||||||
|
// 加入空间
|
||||||
|
message InsertSpaceUserParams {
|
||||||
|
int64 InviteCode = 1 [(api.body)="invite_code"]; // 邀请码
|
||||||
|
}
|
||||||
|
|
||||||
|
message InsertSpaceUserResult {
|
||||||
|
int64 SpaceId = 1 [(api.body)="space_id"];
|
||||||
|
string InviteCode = 2 [(api.body)="invite_code"];
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenerateCode 生成指定长度的随机邀请码(大写字母+数字)
|
||||||
|
func GenerateCode(length int) (string, error) {
|
||||||
|
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
code := make([]byte, length)
|
||||||
|
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
code[i] = charset[num.Int64()]
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(code), nil
|
||||||
|
}
|
||||||
Reference in new issue
Block a user