- {[1, 2, 3].map((i) => (
-
- ))}
+
+
+
+
+
+
+
+
+
+
+
+
+ {[1, 2, 3].map((i) => (
+
+ ))}
+
-
-
-
-
-
-
-
-
-
- {/* 项目信息卡片 */}
-
- {[1, 2, 3, 4].map((i) => (
-
-
-
+
+ {[1, 2, 3, 4].map((i) => (
+
+
+
+
+ ))}
- ))}
-
- {/* 领取按钮或领取成功显示 */}
-
-
-
+
+
- {/* 项目描述 */}
-
-
-
@@ -166,13 +175,13 @@ export function ReceiveMain() {
) : error || !project ? (
-
+
diff --git a/frontend/lib/get-strict-context.tsx b/frontend/lib/get-strict-context.tsx
new file mode 100644
index 00000000..c341bdee
--- /dev/null
+++ b/frontend/lib/get-strict-context.tsx
@@ -0,0 +1,36 @@
+import * as React from 'react';
+
+function getStrictContext
(
+ name?: string,
+): readonly [
+ ({
+ value,
+ children,
+ }: {
+ value: T;
+ children?: React.ReactNode;
+ }) => React.JSX.Element,
+ () => T,
+] {
+ const Context = React.createContext(undefined);
+
+ const Provider = ({
+ value,
+ children,
+ }: {
+ value: T;
+ children?: React.ReactNode;
+ }) => {children};
+
+ const useSafeContext = () => {
+ const ctx = React.useContext(Context);
+ if (ctx === undefined) {
+ throw new Error(`useContext must be used within ${name ?? 'a Provider'}`);
+ }
+ return ctx;
+ };
+
+ return [Provider, useSafeContext] as const;
+}
+
+export {getStrictContext};
diff --git a/frontend/lib/services/project/types.ts b/frontend/lib/services/project/types.ts
index 667d7a48..c17cf991 100644
--- a/frontend/lib/services/project/types.ts
+++ b/frontend/lib/services/project/types.ts
@@ -219,6 +219,14 @@ export interface GetProjectResponseData extends Project {
creator_username: string;
/** 创建者昵称 */
creator_nickname: string;
+ /** 项目是否已完成 */
+ is_completed?: boolean;
+ /** 项目状态 */
+ status?: number;
+ /** 举报数量 */
+ report_count?: number;
+ /** 是否在探索页隐藏 */
+ hide_from_explore?: boolean;
/** 项目标签列表 */
tags: string[] | null;
/** 可领取数量 */
diff --git a/frontend/next.config.ts b/frontend/next.config.ts
index 84e93bdb..dda25aae 100644
--- a/frontend/next.config.ts
+++ b/frontend/next.config.ts
@@ -2,6 +2,14 @@ import type {NextConfig} from 'next';
const nextConfig: NextConfig = {
/* config options here */
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'so.baobeihuijia.com',
+ },
+ ],
+ },
async rewrites() {
return [
diff --git a/frontend/package.json b/frontend/package.json
index bb0d232c..40a47aed 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -17,6 +17,7 @@
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
+ "@floating-ui/react": "^0.27.19",
"@hcaptcha/react-hcaptcha": "^1.12.0",
"@radix-ui/react-alert-dialog": "^1.1.14",
"@radix-ui/react-avatar": "^1.1.10",
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index 79389487..e1a08db1 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -25,6 +25,9 @@ importers:
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@19.1.0)
+ '@floating-ui/react':
+ specifier: ^0.27.19
+ version: 0.27.19(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@hcaptcha/react-hcaptcha':
specifier: ^1.12.0
version: 1.12.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -299,15 +302,36 @@ packages:
'@floating-ui/core@1.7.0':
resolution: {integrity: sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==}
+ '@floating-ui/core@1.7.5':
+ resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==}
+
'@floating-ui/dom@1.7.0':
resolution: {integrity: sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==}
+ '@floating-ui/dom@1.7.6':
+ resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==}
+
'@floating-ui/react-dom@2.1.2':
resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
+ '@floating-ui/react-dom@2.1.8':
+ resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==}
+ peerDependencies:
+ react: '>=16.8.0'
+ react-dom: '>=16.8.0'
+
+ '@floating-ui/react@0.27.19':
+ resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==}
+ peerDependencies:
+ react: '>=17.0.0'
+ react-dom: '>=17.0.0'
+
+ '@floating-ui/utils@0.2.11':
+ resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
+
'@floating-ui/utils@0.2.9':
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
@@ -3263,6 +3287,9 @@ packages:
resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==}
engines: {node: ^14.18.0 || >=16.0.0}
+ tabbable@6.4.0:
+ resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==}
+
tailwind-merge@3.3.0:
resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==}
@@ -3550,17 +3577,42 @@ snapshots:
dependencies:
'@floating-ui/utils': 0.2.9
+ '@floating-ui/core@1.7.5':
+ dependencies:
+ '@floating-ui/utils': 0.2.11
+
'@floating-ui/dom@1.7.0':
dependencies:
'@floating-ui/core': 1.7.0
'@floating-ui/utils': 0.2.9
+ '@floating-ui/dom@1.7.6':
+ dependencies:
+ '@floating-ui/core': 1.7.5
+ '@floating-ui/utils': 0.2.11
+
'@floating-ui/react-dom@2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@floating-ui/dom': 1.7.0
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
+ '@floating-ui/react-dom@2.1.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@floating-ui/dom': 1.7.6
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+
+ '@floating-ui/react@0.27.19(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ '@floating-ui/react-dom': 2.1.8(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@floating-ui/utils': 0.2.11
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ tabbable: 6.4.0
+
+ '@floating-ui/utils@0.2.11': {}
+
'@floating-ui/utils@0.2.9': {}
'@hcaptcha/loader@2.0.0': {}
@@ -6982,6 +7034,8 @@ snapshots:
dependencies:
'@pkgr/core': 0.2.7
+ tabbable@6.4.0: {}
+
tailwind-merge@3.3.0: {}
tailwindcss@4.1.8: {}
diff --git a/frontend/public/heart.json b/frontend/public/heart.json
new file mode 100644
index 00000000..141eb91f
--- /dev/null
+++ b/frontend/public/heart.json
@@ -0,0 +1,182 @@
+[
+ {
+ "name": "秦玉美",
+ "sex": "女",
+ "birthDay": "1997-01-11",
+ "lostDay": "2000-02-03",
+ "lostAddress": "河北省,沧州市,河间市、北石槽乡、北大齐村",
+ "lostHeight": "85cm",
+ "feature": "爱说、头顶有两个旋",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2015/11/s_f5e193801379161c.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/35860.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "吴仕荣",
+ "sex": "男",
+ "birthDay": "1991-01-05",
+ "lostDay": "1991-10-30",
+ "lostAddress": "河北省,唐山市,迁西县,东莲花院乡柳沟峪村",
+ "lostHeight": "未知",
+ "feature": "男,身高185,体型微瘦,长脸,单眼皮",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2021/1/s_a74ba77ee952a9d9.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/6/125258.html",
+ "categoryName": "其他寻人"
+ },
+ {
+ "name": "杨超",
+ "sex": "男",
+ "birthDay": "2001-03-30",
+ "lostDay": "2003-08-20",
+ "lostAddress": "宁夏吴忠市利通区东塔寺石佛四村八队",
+ "lostHeight": "80cm",
+ "feature": "左屁股有个小坑,后脑勺有个小伤疤。",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2009/12/s_246e430c9a13c63e.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/2406.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "贺广丽",
+ "sex": "女",
+ "birthDay": "1986-04-17",
+ "lostDay": "2002-01-29",
+ "lostAddress": "吉林省梅河口市吉乐乡卧龙村",
+ "lostHeight": "156cm",
+ "feature": "",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2012/1/s_50643d1bd946aa55.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/9053.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "许利",
+ "sex": "男",
+ "birthDay": "1988-10-14",
+ "lostDay": "2007-07-05",
+ "lostAddress": "浙江省,温州市,市辖区,小南门第一桥",
+ "lostHeight": "160cm",
+ "feature": "右胳膊上有一伤疤,缝了五六针线。",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2017/8/s_81fcae04c99b1e0e.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/6/64432.html",
+ "categoryName": "其他寻人"
+ },
+ {
+ "name": "杨洋#",
+ "sex": "男",
+ "birthDay": "2005-08-15",
+ "lostDay": "2009-03-16",
+ "lostAddress": "云南镇雄赤水源广场",
+ "lostHeight": "90cm",
+ "feature": "圆脸型,大眼睛,语言不流利",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2009/4/s_314cddcc53bfa238.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/1038.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "黄朵",
+ "sex": "女",
+ "birthDay": "2000-02-03",
+ "lostDay": "2000-02-21",
+ "lostAddress": "江西省,萍乡市,芦溪县宣风镇茶垣村",
+ "lostHeight": "未知",
+ "feature": "黄朵发现的时候穿脏衣服。刚出生的,肚脐尚未愈合。圆脸。在她的喉咙一小疤痕。哭很多。在她的耳朵上一点点点头。\r\n",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2014/3/s_591f8ae1d0ec3d20.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/7/18514.html",
+ "categoryName": "海外寻亲"
+ },
+ {
+ "name": "陈楠1",
+ "sex": "男",
+ "birthDay": "2002-08-22",
+ "lostDay": "2006-11-17",
+ "lostAddress": "重庆市沙坪坝区土弯",
+ "lostHeight": "未知",
+ "feature": "",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2009/11/s_1ac478664b98b687.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/2261.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "马喜琴",
+ "sex": "女",
+ "birthDay": "2002-10-03",
+ "lostDay": "2016-02-06",
+ "lostAddress": "甘肃省,定西市,渭源县,会川镇,罗家磨村,泉下社",
+ "lostHeight": "未知",
+ "feature": "她是个身体瘦瘦的,学生头发,身高1.5米",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2016/3/s_fd4188d4d1053a70.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/41923.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "徐义成",
+ "sex": "男",
+ "birthDay": "2012-12-07",
+ "lostDay": "2012-12-07",
+ "lostAddress": "贵州省,毕节市,七星关区,七星关区民政局",
+ "lostHeight": "未知",
+ "feature": "精神病人",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2012/12/s_29764241868f462f.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/6/12878.html",
+ "categoryName": "其他寻人"
+ },
+ {
+ "name": "谭浩宇",
+ "sex": "男",
+ "birthDay": "2002-09-13",
+ "lostDay": "2013-09-07",
+ "lostAddress": "湖南省,郴州市, 嘉禾县车头镇沙平村",
+ "lostHeight": "2cm",
+ "feature": "鼻梁上有道痕迹",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2016/4/s_5891a60ad27072e2.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/42444.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "仵宇飞",
+ "sex": "男",
+ "birthDay": "2005-01-25",
+ "lostDay": "2019-08-19",
+ "lostAddress": "河北省,衡水市,冀州市魏屯镇",
+ "lostHeight": "2cm",
+ "feature": "圆脸不胖不瘦走路有点弯腰",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2020/2/s_8cd428d41e2930b4.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/108540.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "鲁梦洋",
+ "sex": "女",
+ "birthDay": "1995-01-03",
+ "lostDay": "2008-01-23",
+ "lostAddress": "天津市大港区",
+ "lostHeight": "158cm",
+ "feature": "上穿绿色短羽绒服,内穿偶合色毛衣,下穿牛仔裤,红色旅游鞋.",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2009/2/s_4bd8b6709d558298.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/940.html",
+ "categoryName": "家寻宝贝"
+ },
+ {
+ "name": "池金凤",
+ "sex": "女",
+ "birthDay": "1989-02-20",
+ "lostDay": "2008-03-09",
+ "lostAddress": "浙江省,绍兴市,绍兴县,转移印花厂",
+ "lostHeight": "163cm",
+ "feature": "单眼皮柳叶眉身材适中",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2016/1/s_51cf6e44e381e1fb.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/6/38963.html",
+ "categoryName": "其他寻人"
+ },
+ {
+ "name": "尹蓉",
+ "sex": "女",
+ "birthDay": "2006-10-16",
+ "lostDay": "2008-01-20",
+ "lostAddress": "云南省红河州个旧市鸡街镇东风路口",
+ "lostHeight": "未知",
+ "feature": "2008年1月20日在云南省红河州个旧市鸡街镇东风路口丢失,面颊右边有大拇指大小胎记,上穿土红色的衣服,下穿粉色的棉裤,脚穿黄色凉布鞋。",
+ "photoUrl": "https://so.baobeihuijia.com/bbhj/special/2009/12/s_86f6ff2513e3aac2.jpg",
+ "detailUrl": "https://www.baobeihuijia.com/bbhj/contents/3/2423.html",
+ "categoryName": "家寻宝贝"
+ }
+]
\ No newline at end of file