This commit is contained in:
tsuki 2025-08-01 19:07:03 +08:00
parent b499ab853f
commit 448f71a07c
4 changed files with 86 additions and 12 deletions

View File

@ -20,6 +20,17 @@ import { cn } from '@/lib/utils';
import { useTimeline } from '@/hooks/use-timeline'; import { useTimeline } from '@/hooks/use-timeline';
import { useEffect } from 'react' import { useEffect } from 'react'
import { useRadarTile } from '@/hooks/use-radartile' import { useRadarTile } from '@/hooks/use-radartile'
import { gql, useSubscription } from '@apollo/client'
const SUBSCRIPTION_QUERY = gql`
subscription {
statusUpdates {
id
message
status
}
}
`
export default function Page() { export default function Page() {
@ -30,6 +41,14 @@ export default function Page() {
const { setTime } = useTimeline() const { setTime } = useTimeline()
const { imgBitmap, fetchRadarTile } = useRadarTile({}) const { imgBitmap, fetchRadarTile } = useRadarTile({})
const { data, loading, error } = useSubscription(SUBSCRIPTION_QUERY)
useEffect(() => {
if (data) {
console.log(data.statusUpdates)
}
}, [data])
return ( return (
<SidebarProvider> <SidebarProvider>
<AppSidebar /> <AppSidebar />

View File

@ -1,5 +1,9 @@
import { ApolloClient, InMemoryCache, createHttpLink, from } from '@apollo/client'; import { ApolloClient, InMemoryCache, createHttpLink, from, split } from '@apollo/client';
import { getMainDefinition } from '@apollo/client/utilities';
import { setContext } from '@apollo/client/link/context'; import { setContext } from '@apollo/client/link/context';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
const TOKEN_KEY = 'auth_token'; const TOKEN_KEY = 'auth_token';
@ -7,6 +11,10 @@ const httpLink = createHttpLink({
uri: "http://127.0.0.1:3050/graphql", uri: "http://127.0.0.1:3050/graphql",
}); });
const wsLink = new GraphQLWsLink(createClient({
url: "ws://127.0.0.1:3050/ws",
}));
const authLink = setContext((_, { headers }) => { const authLink = setContext((_, { headers }) => {
// 从 localStorage 获取 token // 从 localStorage 获取 token
const token = typeof window !== 'undefined' ? localStorage.getItem(TOKEN_KEY) : null; const token = typeof window !== 'undefined' ? localStorage.getItem(TOKEN_KEY) : null;
@ -29,9 +37,18 @@ const authLink = setContext((_, { headers }) => {
}; };
}); });
const link = split(
({ query }) => {
const def = getMainDefinition(query);
return def.kind === 'OperationDefinition' && def.operation === 'subscription';
},
wsLink, // 如果是 subscription则走 ws
from([authLink, httpLink])
);
export const createApolloClient = () => { export const createApolloClient = () => {
return new ApolloClient({ return new ApolloClient({
link: from([authLink, httpLink]), link,
cache: new InMemoryCache(), cache: new InMemoryCache(),
}); });
}; };

55
package-lock.json generated
View File

@ -10,7 +10,7 @@
"dependencies": { "dependencies": {
"@21st-extension/react": "^0.5.14", "@21st-extension/react": "^0.5.14",
"@21st-extension/toolbar-next": "^0.5.14", "@21st-extension/toolbar-next": "^0.5.14",
"@apollo/client": "^3.13.8", "@apollo/client": "^3.13.9",
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
@ -40,6 +40,7 @@
"dnd-kit": "^0.0.2", "dnd-kit": "^0.0.2",
"framer-motion": "^12.23.6", "framer-motion": "^12.23.6",
"graphql": "^16.11.0", "graphql": "^16.11.0",
"graphql-ws": "^6.0.6",
"lucide-react": "^0.525.0", "lucide-react": "^0.525.0",
"maplibre-gl": "^5.6.1", "maplibre-gl": "^5.6.1",
"next": "15.4.1", "next": "15.4.1",
@ -140,9 +141,9 @@
} }
}, },
"node_modules/@apollo/client": { "node_modules/@apollo/client": {
"version": "3.13.8", "version": "3.13.9",
"resolved": "http://mirrors.cloud.tencent.com/npm/@apollo/client/-/client-3.13.8.tgz", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.9.tgz",
"integrity": "sha512-YM9lQpm0VfVco4DSyKooHS/fDTiKQcCHfxr7i3iL6a0kP/jNO5+4NFK6vtRDxaYisd5BrwOZHLJpPBnvRVpKPg==", "integrity": "sha512-RStSzQfL1XwL6/NWd7W8avhGQYTgPCtJ+qHkkTTSj9Upp3VVm6Oppv81YWdXG1FgEpDPW4hvCrTUELdcC4inCQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@graphql-typed-document-node/core": "^3.1.1", "@graphql-typed-document-node/core": "^3.1.1",
@ -3564,7 +3565,7 @@
}, },
"node_modules/graphql": { "node_modules/graphql": {
"version": "16.11.0", "version": "16.11.0",
"resolved": "http://mirrors.cloud.tencent.com/npm/graphql/-/graphql-16.11.0.tgz", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -3586,6 +3587,36 @@
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
} }
}, },
"node_modules/graphql-ws": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.6.tgz",
"integrity": "sha512-zgfER9s+ftkGKUZgc0xbx8T7/HMO4AV5/YuYiFc+AtgcO5T0v8AxYYNQ+ltzuzDZgNkYJaFspm5MMYLjQzrkmw==",
"license": "MIT",
"engines": {
"node": ">=20"
},
"peerDependencies": {
"@fastify/websocket": "^10 || ^11",
"crossws": "~0.3",
"graphql": "^15.10.1 || ^16",
"uWebSockets.js": "^20",
"ws": "^8"
},
"peerDependenciesMeta": {
"@fastify/websocket": {
"optional": true
},
"crossws": {
"optional": true
},
"uWebSockets.js": {
"optional": true
},
"ws": {
"optional": true
}
}
},
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -5599,9 +5630,9 @@
} }
}, },
"@apollo/client": { "@apollo/client": {
"version": "3.13.8", "version": "3.13.9",
"resolved": "http://mirrors.cloud.tencent.com/npm/@apollo/client/-/client-3.13.8.tgz", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.9.tgz",
"integrity": "sha512-YM9lQpm0VfVco4DSyKooHS/fDTiKQcCHfxr7i3iL6a0kP/jNO5+4NFK6vtRDxaYisd5BrwOZHLJpPBnvRVpKPg==", "integrity": "sha512-RStSzQfL1XwL6/NWd7W8avhGQYTgPCtJ+qHkkTTSj9Upp3VVm6Oppv81YWdXG1FgEpDPW4hvCrTUELdcC4inCQ==",
"requires": { "requires": {
"@graphql-typed-document-node/core": "^3.1.1", "@graphql-typed-document-node/core": "^3.1.1",
"@wry/caches": "^1.0.0", "@wry/caches": "^1.0.0",
@ -7705,7 +7736,7 @@
}, },
"graphql": { "graphql": {
"version": "16.11.0", "version": "16.11.0",
"resolved": "http://mirrors.cloud.tencent.com/npm/graphql/-/graphql-16.11.0.tgz", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==" "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw=="
}, },
"graphql-tag": { "graphql-tag": {
@ -7716,6 +7747,12 @@
"tslib": "^2.1.0" "tslib": "^2.1.0"
} }
}, },
"graphql-ws": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.6.tgz",
"integrity": "sha512-zgfER9s+ftkGKUZgc0xbx8T7/HMO4AV5/YuYiFc+AtgcO5T0v8AxYYNQ+ltzuzDZgNkYJaFspm5MMYLjQzrkmw==",
"requires": {}
},
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",

View File

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@21st-extension/react": "^0.5.14", "@21st-extension/react": "^0.5.14",
"@21st-extension/toolbar-next": "^0.5.14", "@21st-extension/toolbar-next": "^0.5.14",
"@apollo/client": "^3.13.8", "@apollo/client": "^3.13.9",
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
@ -41,6 +41,7 @@
"dnd-kit": "^0.0.2", "dnd-kit": "^0.0.2",
"framer-motion": "^12.23.6", "framer-motion": "^12.23.6",
"graphql": "^16.11.0", "graphql": "^16.11.0",
"graphql-ws": "^6.0.6",
"lucide-react": "^0.525.0", "lucide-react": "^0.525.0",
"maplibre-gl": "^5.6.1", "maplibre-gl": "^5.6.1",
"next": "15.4.1", "next": "15.4.1",