feat: 初始化项目结构并添加核心功能
- 初始化项目结构,包括Vue 3、Pinia、Vue Router、TailwindCSS等依赖 - 添加首页、活动详情页、创建活动页等核心页面 - 实现活动分类、搜索、报名等基本功能 - 添加公共组件如按钮、输入框、模态框等 - 配置Vite、TailwindCSS、PostCSS等构建工具
Showing
53 changed files
with
13111 additions
and
0 deletions
.gitignore
0 → 100644
| 1 | +# Logs | ||
| 2 | +logs | ||
| 3 | +*.log | ||
| 4 | +npm-debug.log* | ||
| 5 | +yarn-debug.log* | ||
| 6 | +yarn-error.log* | ||
| 7 | +pnpm-debug.log* | ||
| 8 | +lerna-debug.log* | ||
| 9 | + | ||
| 10 | +node_modules | ||
| 11 | +dist | ||
| 12 | +dist-ssr | ||
| 13 | +*.local | ||
| 14 | + | ||
| 15 | +# Editor directories and files | ||
| 16 | +.vscode/* | ||
| 17 | +!.vscode/extensions.json | ||
| 18 | +.idea | ||
| 19 | +.DS_Store | ||
| 20 | +*.suo | ||
| 21 | +*.ntvs* | ||
| 22 | +*.njsproj | ||
| 23 | +*.sln | ||
| 24 | +*.sw? | ||
| 25 | + | ||
| 26 | +.history | ||
| 27 | +node_modules | ||
| 28 | +.vscode | ||
| 29 | +mlaj-read |
| 1 | +# React + Vite Template | ||
| 2 | + | ||
| 3 | +A modern React template for web applications and games, featuring React 18, Vite, TailwindCSS, and Material UI. | ||
| 4 | + | ||
| 5 | +## Project Structure | ||
| 6 | + | ||
| 7 | +``` | ||
| 8 | +├── src/ | ||
| 9 | +│ ├── App.jsx # Main application component | ||
| 10 | +│ ├── main.jsx # Application entry point | ||
| 11 | +│ └── index.css # Global styles (Tailwind) | ||
| 12 | +├── public/ # Static assets | ||
| 13 | +├── index.html # HTML template | ||
| 14 | +├── vite.config.js # Vite configuration | ||
| 15 | +├── tailwind.config.js # Tailwind configuration | ||
| 16 | +├── postcss.config.js # PostCSS configuration | ||
| 17 | +└── eslint.config.js # ESLint configuration | ||
| 18 | +``` | ||
| 19 | + | ||
| 20 | +## Development Guidelines | ||
| 21 | + | ||
| 22 | +- Modify `index.html` and `src/App.jsx` as needed | ||
| 23 | +- Create new folders or files in `src/` directory as needed | ||
| 24 | +- Style components using TailwindCSS utility classes | ||
| 25 | +- Avoid modifying `src/main.jsx` and `src/index.css` | ||
| 26 | +- Only modify `vite.config.js` if absolutely necessary | ||
| 27 | + | ||
| 28 | +## Available Scripts | ||
| 29 | +- `pnpm install` - Install dependencies | ||
| 30 | +- `pnpm run dev` - Start development server | ||
| 31 | +- `pnpm run lint` - Lint source files | ||
| 32 | + | ||
| 33 | +## Tech Stack | ||
| 34 | + | ||
| 35 | +- React | ||
| 36 | +- Vite | ||
| 37 | +- TailwindCSS | ||
| 38 | +- ESLint | ||
| 39 | +- Javascript | ... | ... |
index.html
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-04-17 08:14:25 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 13:26:33 | ||
| 5 | + * @FilePath: /reading-club-app/index.html | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<!doctype html> | ||
| 9 | +<html lang="en"> | ||
| 10 | + | ||
| 11 | +<head> | ||
| 12 | + <meta charset="UTF-8" /> | ||
| 13 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| 14 | + <title>读书会 - 连接爱读书的人</title> | ||
| 15 | +</head> | ||
| 16 | + | ||
| 17 | +<body> | ||
| 18 | + <div id="root"></div> | ||
| 19 | + <script type="module" src="/src/main.js"></script> | ||
| 20 | +</body> | ||
| 21 | + | ||
| 22 | +</html> |
package.json
0 → 100644
| 1 | +{ | ||
| 2 | + "name": "vue-reading-club", | ||
| 3 | + "private": true, | ||
| 4 | + "version": "0.0.0", | ||
| 5 | + "type": "module", | ||
| 6 | + "scripts": { | ||
| 7 | + "dev": "vite", | ||
| 8 | + "build": "vite build", | ||
| 9 | + "lint": "eslint ./src --quiet", | ||
| 10 | + "preview": "vite preview" | ||
| 11 | + }, | ||
| 12 | + "dependencies": { | ||
| 13 | + "@vitejs/plugin-vue-jsx": "4.1.2", | ||
| 14 | + "pinia": "^2.1.7", | ||
| 15 | + "vue": "^3.4.21", | ||
| 16 | + "vue-router": "^4.3.0" | ||
| 17 | + }, | ||
| 18 | + "devDependencies": { | ||
| 19 | + "@vitejs/plugin-vue": "^5.0.4", | ||
| 20 | + "@vue/compiler-sfc": "^3.4.21", | ||
| 21 | + "autoprefixer": "^10.4.20", | ||
| 22 | + "eslint": "^9.9.0", | ||
| 23 | + "eslint-plugin-vue": "^9.24.0", | ||
| 24 | + "postcss": "^8.4.45", | ||
| 25 | + "tailwindcss": "^3.4.10", | ||
| 26 | + "vite": "^5.4.1" | ||
| 27 | + } | ||
| 28 | +} |
pnpm-lock.yaml
0 → 100644
| 1 | +lockfileVersion: '9.0' | ||
| 2 | + | ||
| 3 | +settings: | ||
| 4 | + autoInstallPeers: true | ||
| 5 | + excludeLinksFromLockfile: false | ||
| 6 | + | ||
| 7 | +importers: | ||
| 8 | + | ||
| 9 | + .: | ||
| 10 | + dependencies: | ||
| 11 | + '@vitejs/plugin-vue-jsx': | ||
| 12 | + specifier: 4.1.2 | ||
| 13 | + version: 4.1.2(vite@5.4.18)(vue@3.5.13) | ||
| 14 | + pinia: | ||
| 15 | + specifier: ^2.1.7 | ||
| 16 | + version: 2.3.1(vue@3.5.13) | ||
| 17 | + vue: | ||
| 18 | + specifier: ^3.4.21 | ||
| 19 | + version: 3.5.13 | ||
| 20 | + vue-router: | ||
| 21 | + specifier: ^4.3.0 | ||
| 22 | + version: 4.5.0(vue@3.5.13) | ||
| 23 | + devDependencies: | ||
| 24 | + '@vitejs/plugin-vue': | ||
| 25 | + specifier: ^5.0.4 | ||
| 26 | + version: 5.2.3(vite@5.4.18)(vue@3.5.13) | ||
| 27 | + '@vue/compiler-sfc': | ||
| 28 | + specifier: ^3.4.21 | ||
| 29 | + version: 3.5.13 | ||
| 30 | + autoprefixer: | ||
| 31 | + specifier: ^10.4.20 | ||
| 32 | + version: 10.4.21(postcss@8.5.3) | ||
| 33 | + eslint: | ||
| 34 | + specifier: ^9.9.0 | ||
| 35 | + version: 9.24.0(jiti@1.21.7) | ||
| 36 | + eslint-plugin-vue: | ||
| 37 | + specifier: ^9.24.0 | ||
| 38 | + version: 9.33.0(eslint@9.24.0(jiti@1.21.7)) | ||
| 39 | + postcss: | ||
| 40 | + specifier: ^8.4.45 | ||
| 41 | + version: 8.5.3 | ||
| 42 | + tailwindcss: | ||
| 43 | + specifier: ^3.4.10 | ||
| 44 | + version: 3.4.17 | ||
| 45 | + vite: | ||
| 46 | + specifier: ^5.4.1 | ||
| 47 | + version: 5.4.18 | ||
| 48 | + | ||
| 49 | +packages: | ||
| 50 | + | ||
| 51 | + '@alloc/quick-lru@5.2.0': | ||
| 52 | + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} | ||
| 53 | + engines: {node: '>=10'} | ||
| 54 | + | ||
| 55 | + '@ampproject/remapping@2.3.0': | ||
| 56 | + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} | ||
| 57 | + engines: {node: '>=6.0.0'} | ||
| 58 | + | ||
| 59 | + '@babel/code-frame@7.26.2': | ||
| 60 | + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} | ||
| 61 | + engines: {node: '>=6.9.0'} | ||
| 62 | + | ||
| 63 | + '@babel/compat-data@7.26.8': | ||
| 64 | + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} | ||
| 65 | + engines: {node: '>=6.9.0'} | ||
| 66 | + | ||
| 67 | + '@babel/core@7.26.10': | ||
| 68 | + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} | ||
| 69 | + engines: {node: '>=6.9.0'} | ||
| 70 | + | ||
| 71 | + '@babel/generator@7.27.0': | ||
| 72 | + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} | ||
| 73 | + engines: {node: '>=6.9.0'} | ||
| 74 | + | ||
| 75 | + '@babel/helper-annotate-as-pure@7.25.9': | ||
| 76 | + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} | ||
| 77 | + engines: {node: '>=6.9.0'} | ||
| 78 | + | ||
| 79 | + '@babel/helper-compilation-targets@7.27.0': | ||
| 80 | + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} | ||
| 81 | + engines: {node: '>=6.9.0'} | ||
| 82 | + | ||
| 83 | + '@babel/helper-create-class-features-plugin@7.27.0': | ||
| 84 | + resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==} | ||
| 85 | + engines: {node: '>=6.9.0'} | ||
| 86 | + peerDependencies: | ||
| 87 | + '@babel/core': ^7.0.0 | ||
| 88 | + | ||
| 89 | + '@babel/helper-member-expression-to-functions@7.25.9': | ||
| 90 | + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} | ||
| 91 | + engines: {node: '>=6.9.0'} | ||
| 92 | + | ||
| 93 | + '@babel/helper-module-imports@7.25.9': | ||
| 94 | + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} | ||
| 95 | + engines: {node: '>=6.9.0'} | ||
| 96 | + | ||
| 97 | + '@babel/helper-module-transforms@7.26.0': | ||
| 98 | + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} | ||
| 99 | + engines: {node: '>=6.9.0'} | ||
| 100 | + peerDependencies: | ||
| 101 | + '@babel/core': ^7.0.0 | ||
| 102 | + | ||
| 103 | + '@babel/helper-optimise-call-expression@7.25.9': | ||
| 104 | + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} | ||
| 105 | + engines: {node: '>=6.9.0'} | ||
| 106 | + | ||
| 107 | + '@babel/helper-plugin-utils@7.26.5': | ||
| 108 | + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} | ||
| 109 | + engines: {node: '>=6.9.0'} | ||
| 110 | + | ||
| 111 | + '@babel/helper-replace-supers@7.26.5': | ||
| 112 | + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} | ||
| 113 | + engines: {node: '>=6.9.0'} | ||
| 114 | + peerDependencies: | ||
| 115 | + '@babel/core': ^7.0.0 | ||
| 116 | + | ||
| 117 | + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': | ||
| 118 | + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} | ||
| 119 | + engines: {node: '>=6.9.0'} | ||
| 120 | + | ||
| 121 | + '@babel/helper-string-parser@7.25.9': | ||
| 122 | + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} | ||
| 123 | + engines: {node: '>=6.9.0'} | ||
| 124 | + | ||
| 125 | + '@babel/helper-validator-identifier@7.25.9': | ||
| 126 | + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} | ||
| 127 | + engines: {node: '>=6.9.0'} | ||
| 128 | + | ||
| 129 | + '@babel/helper-validator-option@7.25.9': | ||
| 130 | + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} | ||
| 131 | + engines: {node: '>=6.9.0'} | ||
| 132 | + | ||
| 133 | + '@babel/helpers@7.27.0': | ||
| 134 | + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} | ||
| 135 | + engines: {node: '>=6.9.0'} | ||
| 136 | + | ||
| 137 | + '@babel/parser@7.27.0': | ||
| 138 | + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} | ||
| 139 | + engines: {node: '>=6.0.0'} | ||
| 140 | + hasBin: true | ||
| 141 | + | ||
| 142 | + '@babel/plugin-syntax-jsx@7.25.9': | ||
| 143 | + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} | ||
| 144 | + engines: {node: '>=6.9.0'} | ||
| 145 | + peerDependencies: | ||
| 146 | + '@babel/core': ^7.0.0-0 | ||
| 147 | + | ||
| 148 | + '@babel/plugin-syntax-typescript@7.25.9': | ||
| 149 | + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} | ||
| 150 | + engines: {node: '>=6.9.0'} | ||
| 151 | + peerDependencies: | ||
| 152 | + '@babel/core': ^7.0.0-0 | ||
| 153 | + | ||
| 154 | + '@babel/plugin-transform-typescript@7.27.0': | ||
| 155 | + resolution: {integrity: sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==} | ||
| 156 | + engines: {node: '>=6.9.0'} | ||
| 157 | + peerDependencies: | ||
| 158 | + '@babel/core': ^7.0.0-0 | ||
| 159 | + | ||
| 160 | + '@babel/template@7.27.0': | ||
| 161 | + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} | ||
| 162 | + engines: {node: '>=6.9.0'} | ||
| 163 | + | ||
| 164 | + '@babel/traverse@7.27.0': | ||
| 165 | + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} | ||
| 166 | + engines: {node: '>=6.9.0'} | ||
| 167 | + | ||
| 168 | + '@babel/types@7.27.0': | ||
| 169 | + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} | ||
| 170 | + engines: {node: '>=6.9.0'} | ||
| 171 | + | ||
| 172 | + '@esbuild/aix-ppc64@0.21.5': | ||
| 173 | + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} | ||
| 174 | + engines: {node: '>=12'} | ||
| 175 | + cpu: [ppc64] | ||
| 176 | + os: [aix] | ||
| 177 | + | ||
| 178 | + '@esbuild/android-arm64@0.21.5': | ||
| 179 | + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} | ||
| 180 | + engines: {node: '>=12'} | ||
| 181 | + cpu: [arm64] | ||
| 182 | + os: [android] | ||
| 183 | + | ||
| 184 | + '@esbuild/android-arm@0.21.5': | ||
| 185 | + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} | ||
| 186 | + engines: {node: '>=12'} | ||
| 187 | + cpu: [arm] | ||
| 188 | + os: [android] | ||
| 189 | + | ||
| 190 | + '@esbuild/android-x64@0.21.5': | ||
| 191 | + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} | ||
| 192 | + engines: {node: '>=12'} | ||
| 193 | + cpu: [x64] | ||
| 194 | + os: [android] | ||
| 195 | + | ||
| 196 | + '@esbuild/darwin-arm64@0.21.5': | ||
| 197 | + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} | ||
| 198 | + engines: {node: '>=12'} | ||
| 199 | + cpu: [arm64] | ||
| 200 | + os: [darwin] | ||
| 201 | + | ||
| 202 | + '@esbuild/darwin-x64@0.21.5': | ||
| 203 | + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} | ||
| 204 | + engines: {node: '>=12'} | ||
| 205 | + cpu: [x64] | ||
| 206 | + os: [darwin] | ||
| 207 | + | ||
| 208 | + '@esbuild/freebsd-arm64@0.21.5': | ||
| 209 | + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} | ||
| 210 | + engines: {node: '>=12'} | ||
| 211 | + cpu: [arm64] | ||
| 212 | + os: [freebsd] | ||
| 213 | + | ||
| 214 | + '@esbuild/freebsd-x64@0.21.5': | ||
| 215 | + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} | ||
| 216 | + engines: {node: '>=12'} | ||
| 217 | + cpu: [x64] | ||
| 218 | + os: [freebsd] | ||
| 219 | + | ||
| 220 | + '@esbuild/linux-arm64@0.21.5': | ||
| 221 | + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} | ||
| 222 | + engines: {node: '>=12'} | ||
| 223 | + cpu: [arm64] | ||
| 224 | + os: [linux] | ||
| 225 | + | ||
| 226 | + '@esbuild/linux-arm@0.21.5': | ||
| 227 | + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} | ||
| 228 | + engines: {node: '>=12'} | ||
| 229 | + cpu: [arm] | ||
| 230 | + os: [linux] | ||
| 231 | + | ||
| 232 | + '@esbuild/linux-ia32@0.21.5': | ||
| 233 | + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} | ||
| 234 | + engines: {node: '>=12'} | ||
| 235 | + cpu: [ia32] | ||
| 236 | + os: [linux] | ||
| 237 | + | ||
| 238 | + '@esbuild/linux-loong64@0.21.5': | ||
| 239 | + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} | ||
| 240 | + engines: {node: '>=12'} | ||
| 241 | + cpu: [loong64] | ||
| 242 | + os: [linux] | ||
| 243 | + | ||
| 244 | + '@esbuild/linux-mips64el@0.21.5': | ||
| 245 | + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} | ||
| 246 | + engines: {node: '>=12'} | ||
| 247 | + cpu: [mips64el] | ||
| 248 | + os: [linux] | ||
| 249 | + | ||
| 250 | + '@esbuild/linux-ppc64@0.21.5': | ||
| 251 | + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} | ||
| 252 | + engines: {node: '>=12'} | ||
| 253 | + cpu: [ppc64] | ||
| 254 | + os: [linux] | ||
| 255 | + | ||
| 256 | + '@esbuild/linux-riscv64@0.21.5': | ||
| 257 | + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} | ||
| 258 | + engines: {node: '>=12'} | ||
| 259 | + cpu: [riscv64] | ||
| 260 | + os: [linux] | ||
| 261 | + | ||
| 262 | + '@esbuild/linux-s390x@0.21.5': | ||
| 263 | + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} | ||
| 264 | + engines: {node: '>=12'} | ||
| 265 | + cpu: [s390x] | ||
| 266 | + os: [linux] | ||
| 267 | + | ||
| 268 | + '@esbuild/linux-x64@0.21.5': | ||
| 269 | + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} | ||
| 270 | + engines: {node: '>=12'} | ||
| 271 | + cpu: [x64] | ||
| 272 | + os: [linux] | ||
| 273 | + | ||
| 274 | + '@esbuild/netbsd-x64@0.21.5': | ||
| 275 | + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} | ||
| 276 | + engines: {node: '>=12'} | ||
| 277 | + cpu: [x64] | ||
| 278 | + os: [netbsd] | ||
| 279 | + | ||
| 280 | + '@esbuild/openbsd-x64@0.21.5': | ||
| 281 | + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} | ||
| 282 | + engines: {node: '>=12'} | ||
| 283 | + cpu: [x64] | ||
| 284 | + os: [openbsd] | ||
| 285 | + | ||
| 286 | + '@esbuild/sunos-x64@0.21.5': | ||
| 287 | + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} | ||
| 288 | + engines: {node: '>=12'} | ||
| 289 | + cpu: [x64] | ||
| 290 | + os: [sunos] | ||
| 291 | + | ||
| 292 | + '@esbuild/win32-arm64@0.21.5': | ||
| 293 | + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} | ||
| 294 | + engines: {node: '>=12'} | ||
| 295 | + cpu: [arm64] | ||
| 296 | + os: [win32] | ||
| 297 | + | ||
| 298 | + '@esbuild/win32-ia32@0.21.5': | ||
| 299 | + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} | ||
| 300 | + engines: {node: '>=12'} | ||
| 301 | + cpu: [ia32] | ||
| 302 | + os: [win32] | ||
| 303 | + | ||
| 304 | + '@esbuild/win32-x64@0.21.5': | ||
| 305 | + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} | ||
| 306 | + engines: {node: '>=12'} | ||
| 307 | + cpu: [x64] | ||
| 308 | + os: [win32] | ||
| 309 | + | ||
| 310 | + '@eslint-community/eslint-utils@4.6.1': | ||
| 311 | + resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} | ||
| 312 | + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||
| 313 | + peerDependencies: | ||
| 314 | + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 | ||
| 315 | + | ||
| 316 | + '@eslint-community/regexpp@4.12.1': | ||
| 317 | + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} | ||
| 318 | + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} | ||
| 319 | + | ||
| 320 | + '@eslint/config-array@0.20.0': | ||
| 321 | + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} | ||
| 322 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 323 | + | ||
| 324 | + '@eslint/config-helpers@0.2.1': | ||
| 325 | + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} | ||
| 326 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 327 | + | ||
| 328 | + '@eslint/core@0.12.0': | ||
| 329 | + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} | ||
| 330 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 331 | + | ||
| 332 | + '@eslint/core@0.13.0': | ||
| 333 | + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} | ||
| 334 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 335 | + | ||
| 336 | + '@eslint/eslintrc@3.3.1': | ||
| 337 | + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} | ||
| 338 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 339 | + | ||
| 340 | + '@eslint/js@9.24.0': | ||
| 341 | + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} | ||
| 342 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 343 | + | ||
| 344 | + '@eslint/object-schema@2.1.6': | ||
| 345 | + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} | ||
| 346 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 347 | + | ||
| 348 | + '@eslint/plugin-kit@0.2.8': | ||
| 349 | + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} | ||
| 350 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 351 | + | ||
| 352 | + '@humanfs/core@0.19.1': | ||
| 353 | + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} | ||
| 354 | + engines: {node: '>=18.18.0'} | ||
| 355 | + | ||
| 356 | + '@humanfs/node@0.16.6': | ||
| 357 | + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} | ||
| 358 | + engines: {node: '>=18.18.0'} | ||
| 359 | + | ||
| 360 | + '@humanwhocodes/module-importer@1.0.1': | ||
| 361 | + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} | ||
| 362 | + engines: {node: '>=12.22'} | ||
| 363 | + | ||
| 364 | + '@humanwhocodes/retry@0.3.1': | ||
| 365 | + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} | ||
| 366 | + engines: {node: '>=18.18'} | ||
| 367 | + | ||
| 368 | + '@humanwhocodes/retry@0.4.2': | ||
| 369 | + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} | ||
| 370 | + engines: {node: '>=18.18'} | ||
| 371 | + | ||
| 372 | + '@isaacs/cliui@8.0.2': | ||
| 373 | + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} | ||
| 374 | + engines: {node: '>=12'} | ||
| 375 | + | ||
| 376 | + '@jridgewell/gen-mapping@0.3.8': | ||
| 377 | + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} | ||
| 378 | + engines: {node: '>=6.0.0'} | ||
| 379 | + | ||
| 380 | + '@jridgewell/resolve-uri@3.1.2': | ||
| 381 | + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} | ||
| 382 | + engines: {node: '>=6.0.0'} | ||
| 383 | + | ||
| 384 | + '@jridgewell/set-array@1.2.1': | ||
| 385 | + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} | ||
| 386 | + engines: {node: '>=6.0.0'} | ||
| 387 | + | ||
| 388 | + '@jridgewell/sourcemap-codec@1.5.0': | ||
| 389 | + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} | ||
| 390 | + | ||
| 391 | + '@jridgewell/trace-mapping@0.3.25': | ||
| 392 | + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} | ||
| 393 | + | ||
| 394 | + '@nodelib/fs.scandir@2.1.5': | ||
| 395 | + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} | ||
| 396 | + engines: {node: '>= 8'} | ||
| 397 | + | ||
| 398 | + '@nodelib/fs.stat@2.0.5': | ||
| 399 | + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} | ||
| 400 | + engines: {node: '>= 8'} | ||
| 401 | + | ||
| 402 | + '@nodelib/fs.walk@1.2.8': | ||
| 403 | + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} | ||
| 404 | + engines: {node: '>= 8'} | ||
| 405 | + | ||
| 406 | + '@pkgjs/parseargs@0.11.0': | ||
| 407 | + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} | ||
| 408 | + engines: {node: '>=14'} | ||
| 409 | + | ||
| 410 | + '@rollup/rollup-android-arm-eabi@4.40.0': | ||
| 411 | + resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} | ||
| 412 | + cpu: [arm] | ||
| 413 | + os: [android] | ||
| 414 | + | ||
| 415 | + '@rollup/rollup-android-arm64@4.40.0': | ||
| 416 | + resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} | ||
| 417 | + cpu: [arm64] | ||
| 418 | + os: [android] | ||
| 419 | + | ||
| 420 | + '@rollup/rollup-darwin-arm64@4.40.0': | ||
| 421 | + resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} | ||
| 422 | + cpu: [arm64] | ||
| 423 | + os: [darwin] | ||
| 424 | + | ||
| 425 | + '@rollup/rollup-darwin-x64@4.40.0': | ||
| 426 | + resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} | ||
| 427 | + cpu: [x64] | ||
| 428 | + os: [darwin] | ||
| 429 | + | ||
| 430 | + '@rollup/rollup-freebsd-arm64@4.40.0': | ||
| 431 | + resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} | ||
| 432 | + cpu: [arm64] | ||
| 433 | + os: [freebsd] | ||
| 434 | + | ||
| 435 | + '@rollup/rollup-freebsd-x64@4.40.0': | ||
| 436 | + resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} | ||
| 437 | + cpu: [x64] | ||
| 438 | + os: [freebsd] | ||
| 439 | + | ||
| 440 | + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': | ||
| 441 | + resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} | ||
| 442 | + cpu: [arm] | ||
| 443 | + os: [linux] | ||
| 444 | + | ||
| 445 | + '@rollup/rollup-linux-arm-musleabihf@4.40.0': | ||
| 446 | + resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} | ||
| 447 | + cpu: [arm] | ||
| 448 | + os: [linux] | ||
| 449 | + | ||
| 450 | + '@rollup/rollup-linux-arm64-gnu@4.40.0': | ||
| 451 | + resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} | ||
| 452 | + cpu: [arm64] | ||
| 453 | + os: [linux] | ||
| 454 | + | ||
| 455 | + '@rollup/rollup-linux-arm64-musl@4.40.0': | ||
| 456 | + resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} | ||
| 457 | + cpu: [arm64] | ||
| 458 | + os: [linux] | ||
| 459 | + | ||
| 460 | + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': | ||
| 461 | + resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} | ||
| 462 | + cpu: [loong64] | ||
| 463 | + os: [linux] | ||
| 464 | + | ||
| 465 | + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': | ||
| 466 | + resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} | ||
| 467 | + cpu: [ppc64] | ||
| 468 | + os: [linux] | ||
| 469 | + | ||
| 470 | + '@rollup/rollup-linux-riscv64-gnu@4.40.0': | ||
| 471 | + resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} | ||
| 472 | + cpu: [riscv64] | ||
| 473 | + os: [linux] | ||
| 474 | + | ||
| 475 | + '@rollup/rollup-linux-riscv64-musl@4.40.0': | ||
| 476 | + resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} | ||
| 477 | + cpu: [riscv64] | ||
| 478 | + os: [linux] | ||
| 479 | + | ||
| 480 | + '@rollup/rollup-linux-s390x-gnu@4.40.0': | ||
| 481 | + resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} | ||
| 482 | + cpu: [s390x] | ||
| 483 | + os: [linux] | ||
| 484 | + | ||
| 485 | + '@rollup/rollup-linux-x64-gnu@4.40.0': | ||
| 486 | + resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} | ||
| 487 | + cpu: [x64] | ||
| 488 | + os: [linux] | ||
| 489 | + | ||
| 490 | + '@rollup/rollup-linux-x64-musl@4.40.0': | ||
| 491 | + resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} | ||
| 492 | + cpu: [x64] | ||
| 493 | + os: [linux] | ||
| 494 | + | ||
| 495 | + '@rollup/rollup-win32-arm64-msvc@4.40.0': | ||
| 496 | + resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} | ||
| 497 | + cpu: [arm64] | ||
| 498 | + os: [win32] | ||
| 499 | + | ||
| 500 | + '@rollup/rollup-win32-ia32-msvc@4.40.0': | ||
| 501 | + resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} | ||
| 502 | + cpu: [ia32] | ||
| 503 | + os: [win32] | ||
| 504 | + | ||
| 505 | + '@rollup/rollup-win32-x64-msvc@4.40.0': | ||
| 506 | + resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} | ||
| 507 | + cpu: [x64] | ||
| 508 | + os: [win32] | ||
| 509 | + | ||
| 510 | + '@types/estree@1.0.7': | ||
| 511 | + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} | ||
| 512 | + | ||
| 513 | + '@types/json-schema@7.0.15': | ||
| 514 | + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} | ||
| 515 | + | ||
| 516 | + '@vitejs/plugin-vue-jsx@4.1.2': | ||
| 517 | + resolution: {integrity: sha512-4Rk0GdE0QCdsIkuMmWeg11gmM4x8UmTnZR/LWPm7QJ7+BsK4tq08udrN0isrrWqz5heFy9HLV/7bOLgFS8hUjA==} | ||
| 518 | + engines: {node: ^18.0.0 || >=20.0.0} | ||
| 519 | + peerDependencies: | ||
| 520 | + vite: ^5.0.0 || ^6.0.0 | ||
| 521 | + vue: ^3.0.0 | ||
| 522 | + | ||
| 523 | + '@vitejs/plugin-vue@5.2.3': | ||
| 524 | + resolution: {integrity: sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==} | ||
| 525 | + engines: {node: ^18.0.0 || >=20.0.0} | ||
| 526 | + peerDependencies: | ||
| 527 | + vite: ^5.0.0 || ^6.0.0 | ||
| 528 | + vue: ^3.2.25 | ||
| 529 | + | ||
| 530 | + '@vue/babel-helper-vue-transform-on@1.4.0': | ||
| 531 | + resolution: {integrity: sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==} | ||
| 532 | + | ||
| 533 | + '@vue/babel-plugin-jsx@1.4.0': | ||
| 534 | + resolution: {integrity: sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA==} | ||
| 535 | + peerDependencies: | ||
| 536 | + '@babel/core': ^7.0.0-0 | ||
| 537 | + peerDependenciesMeta: | ||
| 538 | + '@babel/core': | ||
| 539 | + optional: true | ||
| 540 | + | ||
| 541 | + '@vue/babel-plugin-resolve-type@1.4.0': | ||
| 542 | + resolution: {integrity: sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ==} | ||
| 543 | + peerDependencies: | ||
| 544 | + '@babel/core': ^7.0.0-0 | ||
| 545 | + | ||
| 546 | + '@vue/compiler-core@3.5.13': | ||
| 547 | + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} | ||
| 548 | + | ||
| 549 | + '@vue/compiler-dom@3.5.13': | ||
| 550 | + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} | ||
| 551 | + | ||
| 552 | + '@vue/compiler-sfc@3.5.13': | ||
| 553 | + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} | ||
| 554 | + | ||
| 555 | + '@vue/compiler-ssr@3.5.13': | ||
| 556 | + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} | ||
| 557 | + | ||
| 558 | + '@vue/devtools-api@6.6.4': | ||
| 559 | + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} | ||
| 560 | + | ||
| 561 | + '@vue/reactivity@3.5.13': | ||
| 562 | + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} | ||
| 563 | + | ||
| 564 | + '@vue/runtime-core@3.5.13': | ||
| 565 | + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} | ||
| 566 | + | ||
| 567 | + '@vue/runtime-dom@3.5.13': | ||
| 568 | + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} | ||
| 569 | + | ||
| 570 | + '@vue/server-renderer@3.5.13': | ||
| 571 | + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} | ||
| 572 | + peerDependencies: | ||
| 573 | + vue: 3.5.13 | ||
| 574 | + | ||
| 575 | + '@vue/shared@3.5.13': | ||
| 576 | + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} | ||
| 577 | + | ||
| 578 | + acorn-jsx@5.3.2: | ||
| 579 | + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} | ||
| 580 | + peerDependencies: | ||
| 581 | + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 | ||
| 582 | + | ||
| 583 | + acorn@8.14.1: | ||
| 584 | + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} | ||
| 585 | + engines: {node: '>=0.4.0'} | ||
| 586 | + hasBin: true | ||
| 587 | + | ||
| 588 | + ajv@6.12.6: | ||
| 589 | + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} | ||
| 590 | + | ||
| 591 | + ansi-regex@5.0.1: | ||
| 592 | + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} | ||
| 593 | + engines: {node: '>=8'} | ||
| 594 | + | ||
| 595 | + ansi-regex@6.1.0: | ||
| 596 | + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} | ||
| 597 | + engines: {node: '>=12'} | ||
| 598 | + | ||
| 599 | + ansi-styles@4.3.0: | ||
| 600 | + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} | ||
| 601 | + engines: {node: '>=8'} | ||
| 602 | + | ||
| 603 | + ansi-styles@6.2.1: | ||
| 604 | + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} | ||
| 605 | + engines: {node: '>=12'} | ||
| 606 | + | ||
| 607 | + any-promise@1.3.0: | ||
| 608 | + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} | ||
| 609 | + | ||
| 610 | + anymatch@3.1.3: | ||
| 611 | + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} | ||
| 612 | + engines: {node: '>= 8'} | ||
| 613 | + | ||
| 614 | + arg@5.0.2: | ||
| 615 | + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} | ||
| 616 | + | ||
| 617 | + argparse@2.0.1: | ||
| 618 | + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} | ||
| 619 | + | ||
| 620 | + autoprefixer@10.4.21: | ||
| 621 | + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} | ||
| 622 | + engines: {node: ^10 || ^12 || >=14} | ||
| 623 | + hasBin: true | ||
| 624 | + peerDependencies: | ||
| 625 | + postcss: ^8.1.0 | ||
| 626 | + | ||
| 627 | + balanced-match@1.0.2: | ||
| 628 | + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} | ||
| 629 | + | ||
| 630 | + binary-extensions@2.3.0: | ||
| 631 | + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} | ||
| 632 | + engines: {node: '>=8'} | ||
| 633 | + | ||
| 634 | + boolbase@1.0.0: | ||
| 635 | + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} | ||
| 636 | + | ||
| 637 | + brace-expansion@1.1.11: | ||
| 638 | + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} | ||
| 639 | + | ||
| 640 | + brace-expansion@2.0.1: | ||
| 641 | + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} | ||
| 642 | + | ||
| 643 | + braces@3.0.3: | ||
| 644 | + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} | ||
| 645 | + engines: {node: '>=8'} | ||
| 646 | + | ||
| 647 | + browserslist@4.24.4: | ||
| 648 | + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} | ||
| 649 | + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} | ||
| 650 | + hasBin: true | ||
| 651 | + | ||
| 652 | + callsites@3.1.0: | ||
| 653 | + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} | ||
| 654 | + engines: {node: '>=6'} | ||
| 655 | + | ||
| 656 | + camelcase-css@2.0.1: | ||
| 657 | + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} | ||
| 658 | + engines: {node: '>= 6'} | ||
| 659 | + | ||
| 660 | + caniuse-lite@1.0.30001714: | ||
| 661 | + resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==} | ||
| 662 | + | ||
| 663 | + chalk@4.1.2: | ||
| 664 | + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} | ||
| 665 | + engines: {node: '>=10'} | ||
| 666 | + | ||
| 667 | + chokidar@3.6.0: | ||
| 668 | + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} | ||
| 669 | + engines: {node: '>= 8.10.0'} | ||
| 670 | + | ||
| 671 | + color-convert@2.0.1: | ||
| 672 | + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} | ||
| 673 | + engines: {node: '>=7.0.0'} | ||
| 674 | + | ||
| 675 | + color-name@1.1.4: | ||
| 676 | + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} | ||
| 677 | + | ||
| 678 | + commander@4.1.1: | ||
| 679 | + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} | ||
| 680 | + engines: {node: '>= 6'} | ||
| 681 | + | ||
| 682 | + concat-map@0.0.1: | ||
| 683 | + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} | ||
| 684 | + | ||
| 685 | + convert-source-map@2.0.0: | ||
| 686 | + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} | ||
| 687 | + | ||
| 688 | + cross-spawn@7.0.6: | ||
| 689 | + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} | ||
| 690 | + engines: {node: '>= 8'} | ||
| 691 | + | ||
| 692 | + cssesc@3.0.0: | ||
| 693 | + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} | ||
| 694 | + engines: {node: '>=4'} | ||
| 695 | + hasBin: true | ||
| 696 | + | ||
| 697 | + csstype@3.1.3: | ||
| 698 | + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} | ||
| 699 | + | ||
| 700 | + debug@4.4.0: | ||
| 701 | + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} | ||
| 702 | + engines: {node: '>=6.0'} | ||
| 703 | + peerDependencies: | ||
| 704 | + supports-color: '*' | ||
| 705 | + peerDependenciesMeta: | ||
| 706 | + supports-color: | ||
| 707 | + optional: true | ||
| 708 | + | ||
| 709 | + deep-is@0.1.4: | ||
| 710 | + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} | ||
| 711 | + | ||
| 712 | + didyoumean@1.2.2: | ||
| 713 | + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} | ||
| 714 | + | ||
| 715 | + dlv@1.1.3: | ||
| 716 | + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} | ||
| 717 | + | ||
| 718 | + eastasianwidth@0.2.0: | ||
| 719 | + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} | ||
| 720 | + | ||
| 721 | + electron-to-chromium@1.5.137: | ||
| 722 | + resolution: {integrity: sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==} | ||
| 723 | + | ||
| 724 | + emoji-regex@8.0.0: | ||
| 725 | + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} | ||
| 726 | + | ||
| 727 | + emoji-regex@9.2.2: | ||
| 728 | + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} | ||
| 729 | + | ||
| 730 | + entities@4.5.0: | ||
| 731 | + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} | ||
| 732 | + engines: {node: '>=0.12'} | ||
| 733 | + | ||
| 734 | + esbuild@0.21.5: | ||
| 735 | + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} | ||
| 736 | + engines: {node: '>=12'} | ||
| 737 | + hasBin: true | ||
| 738 | + | ||
| 739 | + escalade@3.2.0: | ||
| 740 | + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} | ||
| 741 | + engines: {node: '>=6'} | ||
| 742 | + | ||
| 743 | + escape-string-regexp@4.0.0: | ||
| 744 | + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} | ||
| 745 | + engines: {node: '>=10'} | ||
| 746 | + | ||
| 747 | + eslint-plugin-vue@9.33.0: | ||
| 748 | + resolution: {integrity: sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==} | ||
| 749 | + engines: {node: ^14.17.0 || >=16.0.0} | ||
| 750 | + peerDependencies: | ||
| 751 | + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 | ||
| 752 | + | ||
| 753 | + eslint-scope@7.2.2: | ||
| 754 | + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} | ||
| 755 | + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||
| 756 | + | ||
| 757 | + eslint-scope@8.3.0: | ||
| 758 | + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} | ||
| 759 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 760 | + | ||
| 761 | + eslint-visitor-keys@3.4.3: | ||
| 762 | + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} | ||
| 763 | + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||
| 764 | + | ||
| 765 | + eslint-visitor-keys@4.2.0: | ||
| 766 | + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} | ||
| 767 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 768 | + | ||
| 769 | + eslint@9.24.0: | ||
| 770 | + resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} | ||
| 771 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 772 | + hasBin: true | ||
| 773 | + peerDependencies: | ||
| 774 | + jiti: '*' | ||
| 775 | + peerDependenciesMeta: | ||
| 776 | + jiti: | ||
| 777 | + optional: true | ||
| 778 | + | ||
| 779 | + espree@10.3.0: | ||
| 780 | + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} | ||
| 781 | + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} | ||
| 782 | + | ||
| 783 | + espree@9.6.1: | ||
| 784 | + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} | ||
| 785 | + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | ||
| 786 | + | ||
| 787 | + esquery@1.6.0: | ||
| 788 | + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} | ||
| 789 | + engines: {node: '>=0.10'} | ||
| 790 | + | ||
| 791 | + esrecurse@4.3.0: | ||
| 792 | + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} | ||
| 793 | + engines: {node: '>=4.0'} | ||
| 794 | + | ||
| 795 | + estraverse@5.3.0: | ||
| 796 | + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} | ||
| 797 | + engines: {node: '>=4.0'} | ||
| 798 | + | ||
| 799 | + estree-walker@2.0.2: | ||
| 800 | + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} | ||
| 801 | + | ||
| 802 | + esutils@2.0.3: | ||
| 803 | + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} | ||
| 804 | + engines: {node: '>=0.10.0'} | ||
| 805 | + | ||
| 806 | + fast-deep-equal@3.1.3: | ||
| 807 | + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} | ||
| 808 | + | ||
| 809 | + fast-glob@3.3.3: | ||
| 810 | + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} | ||
| 811 | + engines: {node: '>=8.6.0'} | ||
| 812 | + | ||
| 813 | + fast-json-stable-stringify@2.1.0: | ||
| 814 | + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} | ||
| 815 | + | ||
| 816 | + fast-levenshtein@2.0.6: | ||
| 817 | + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} | ||
| 818 | + | ||
| 819 | + fastq@1.19.1: | ||
| 820 | + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} | ||
| 821 | + | ||
| 822 | + file-entry-cache@8.0.0: | ||
| 823 | + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} | ||
| 824 | + engines: {node: '>=16.0.0'} | ||
| 825 | + | ||
| 826 | + fill-range@7.1.1: | ||
| 827 | + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} | ||
| 828 | + engines: {node: '>=8'} | ||
| 829 | + | ||
| 830 | + find-up@5.0.0: | ||
| 831 | + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} | ||
| 832 | + engines: {node: '>=10'} | ||
| 833 | + | ||
| 834 | + flat-cache@4.0.1: | ||
| 835 | + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} | ||
| 836 | + engines: {node: '>=16'} | ||
| 837 | + | ||
| 838 | + flatted@3.3.3: | ||
| 839 | + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} | ||
| 840 | + | ||
| 841 | + foreground-child@3.3.1: | ||
| 842 | + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} | ||
| 843 | + engines: {node: '>=14'} | ||
| 844 | + | ||
| 845 | + fraction.js@4.3.7: | ||
| 846 | + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} | ||
| 847 | + | ||
| 848 | + fsevents@2.3.3: | ||
| 849 | + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} | ||
| 850 | + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} | ||
| 851 | + os: [darwin] | ||
| 852 | + | ||
| 853 | + function-bind@1.1.2: | ||
| 854 | + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} | ||
| 855 | + | ||
| 856 | + gensync@1.0.0-beta.2: | ||
| 857 | + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} | ||
| 858 | + engines: {node: '>=6.9.0'} | ||
| 859 | + | ||
| 860 | + glob-parent@5.1.2: | ||
| 861 | + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} | ||
| 862 | + engines: {node: '>= 6'} | ||
| 863 | + | ||
| 864 | + glob-parent@6.0.2: | ||
| 865 | + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} | ||
| 866 | + engines: {node: '>=10.13.0'} | ||
| 867 | + | ||
| 868 | + glob@10.4.5: | ||
| 869 | + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} | ||
| 870 | + hasBin: true | ||
| 871 | + | ||
| 872 | + globals@11.12.0: | ||
| 873 | + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} | ||
| 874 | + engines: {node: '>=4'} | ||
| 875 | + | ||
| 876 | + globals@13.24.0: | ||
| 877 | + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} | ||
| 878 | + engines: {node: '>=8'} | ||
| 879 | + | ||
| 880 | + globals@14.0.0: | ||
| 881 | + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} | ||
| 882 | + engines: {node: '>=18'} | ||
| 883 | + | ||
| 884 | + has-flag@4.0.0: | ||
| 885 | + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} | ||
| 886 | + engines: {node: '>=8'} | ||
| 887 | + | ||
| 888 | + hasown@2.0.2: | ||
| 889 | + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} | ||
| 890 | + engines: {node: '>= 0.4'} | ||
| 891 | + | ||
| 892 | + ignore@5.3.2: | ||
| 893 | + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} | ||
| 894 | + engines: {node: '>= 4'} | ||
| 895 | + | ||
| 896 | + import-fresh@3.3.1: | ||
| 897 | + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} | ||
| 898 | + engines: {node: '>=6'} | ||
| 899 | + | ||
| 900 | + imurmurhash@0.1.4: | ||
| 901 | + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} | ||
| 902 | + engines: {node: '>=0.8.19'} | ||
| 903 | + | ||
| 904 | + is-binary-path@2.1.0: | ||
| 905 | + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} | ||
| 906 | + engines: {node: '>=8'} | ||
| 907 | + | ||
| 908 | + is-core-module@2.16.1: | ||
| 909 | + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} | ||
| 910 | + engines: {node: '>= 0.4'} | ||
| 911 | + | ||
| 912 | + is-extglob@2.1.1: | ||
| 913 | + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} | ||
| 914 | + engines: {node: '>=0.10.0'} | ||
| 915 | + | ||
| 916 | + is-fullwidth-code-point@3.0.0: | ||
| 917 | + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} | ||
| 918 | + engines: {node: '>=8'} | ||
| 919 | + | ||
| 920 | + is-glob@4.0.3: | ||
| 921 | + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} | ||
| 922 | + engines: {node: '>=0.10.0'} | ||
| 923 | + | ||
| 924 | + is-number@7.0.0: | ||
| 925 | + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} | ||
| 926 | + engines: {node: '>=0.12.0'} | ||
| 927 | + | ||
| 928 | + isexe@2.0.0: | ||
| 929 | + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} | ||
| 930 | + | ||
| 931 | + jackspeak@3.4.3: | ||
| 932 | + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} | ||
| 933 | + | ||
| 934 | + jiti@1.21.7: | ||
| 935 | + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} | ||
| 936 | + hasBin: true | ||
| 937 | + | ||
| 938 | + js-tokens@4.0.0: | ||
| 939 | + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} | ||
| 940 | + | ||
| 941 | + js-yaml@4.1.0: | ||
| 942 | + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} | ||
| 943 | + hasBin: true | ||
| 944 | + | ||
| 945 | + jsesc@3.1.0: | ||
| 946 | + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} | ||
| 947 | + engines: {node: '>=6'} | ||
| 948 | + hasBin: true | ||
| 949 | + | ||
| 950 | + json-buffer@3.0.1: | ||
| 951 | + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} | ||
| 952 | + | ||
| 953 | + json-schema-traverse@0.4.1: | ||
| 954 | + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} | ||
| 955 | + | ||
| 956 | + json-stable-stringify-without-jsonify@1.0.1: | ||
| 957 | + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} | ||
| 958 | + | ||
| 959 | + json5@2.2.3: | ||
| 960 | + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} | ||
| 961 | + engines: {node: '>=6'} | ||
| 962 | + hasBin: true | ||
| 963 | + | ||
| 964 | + keyv@4.5.4: | ||
| 965 | + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} | ||
| 966 | + | ||
| 967 | + levn@0.4.1: | ||
| 968 | + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} | ||
| 969 | + engines: {node: '>= 0.8.0'} | ||
| 970 | + | ||
| 971 | + lilconfig@3.1.3: | ||
| 972 | + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} | ||
| 973 | + engines: {node: '>=14'} | ||
| 974 | + | ||
| 975 | + lines-and-columns@1.2.4: | ||
| 976 | + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} | ||
| 977 | + | ||
| 978 | + locate-path@6.0.0: | ||
| 979 | + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} | ||
| 980 | + engines: {node: '>=10'} | ||
| 981 | + | ||
| 982 | + lodash.merge@4.6.2: | ||
| 983 | + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} | ||
| 984 | + | ||
| 985 | + lodash@4.17.21: | ||
| 986 | + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} | ||
| 987 | + | ||
| 988 | + lru-cache@10.4.3: | ||
| 989 | + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} | ||
| 990 | + | ||
| 991 | + lru-cache@5.1.1: | ||
| 992 | + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} | ||
| 993 | + | ||
| 994 | + magic-string@0.30.17: | ||
| 995 | + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} | ||
| 996 | + | ||
| 997 | + merge2@1.4.1: | ||
| 998 | + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} | ||
| 999 | + engines: {node: '>= 8'} | ||
| 1000 | + | ||
| 1001 | + micromatch@4.0.8: | ||
| 1002 | + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} | ||
| 1003 | + engines: {node: '>=8.6'} | ||
| 1004 | + | ||
| 1005 | + minimatch@3.1.2: | ||
| 1006 | + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} | ||
| 1007 | + | ||
| 1008 | + minimatch@9.0.5: | ||
| 1009 | + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} | ||
| 1010 | + engines: {node: '>=16 || 14 >=14.17'} | ||
| 1011 | + | ||
| 1012 | + minipass@7.1.2: | ||
| 1013 | + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} | ||
| 1014 | + engines: {node: '>=16 || 14 >=14.17'} | ||
| 1015 | + | ||
| 1016 | + ms@2.1.3: | ||
| 1017 | + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} | ||
| 1018 | + | ||
| 1019 | + mz@2.7.0: | ||
| 1020 | + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} | ||
| 1021 | + | ||
| 1022 | + nanoid@3.3.11: | ||
| 1023 | + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} | ||
| 1024 | + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} | ||
| 1025 | + hasBin: true | ||
| 1026 | + | ||
| 1027 | + natural-compare@1.4.0: | ||
| 1028 | + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} | ||
| 1029 | + | ||
| 1030 | + node-releases@2.0.19: | ||
| 1031 | + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} | ||
| 1032 | + | ||
| 1033 | + normalize-path@3.0.0: | ||
| 1034 | + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} | ||
| 1035 | + engines: {node: '>=0.10.0'} | ||
| 1036 | + | ||
| 1037 | + normalize-range@0.1.2: | ||
| 1038 | + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} | ||
| 1039 | + engines: {node: '>=0.10.0'} | ||
| 1040 | + | ||
| 1041 | + nth-check@2.1.1: | ||
| 1042 | + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} | ||
| 1043 | + | ||
| 1044 | + object-assign@4.1.1: | ||
| 1045 | + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} | ||
| 1046 | + engines: {node: '>=0.10.0'} | ||
| 1047 | + | ||
| 1048 | + object-hash@3.0.0: | ||
| 1049 | + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} | ||
| 1050 | + engines: {node: '>= 6'} | ||
| 1051 | + | ||
| 1052 | + optionator@0.9.4: | ||
| 1053 | + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} | ||
| 1054 | + engines: {node: '>= 0.8.0'} | ||
| 1055 | + | ||
| 1056 | + p-limit@3.1.0: | ||
| 1057 | + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} | ||
| 1058 | + engines: {node: '>=10'} | ||
| 1059 | + | ||
| 1060 | + p-locate@5.0.0: | ||
| 1061 | + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} | ||
| 1062 | + engines: {node: '>=10'} | ||
| 1063 | + | ||
| 1064 | + package-json-from-dist@1.0.1: | ||
| 1065 | + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} | ||
| 1066 | + | ||
| 1067 | + parent-module@1.0.1: | ||
| 1068 | + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} | ||
| 1069 | + engines: {node: '>=6'} | ||
| 1070 | + | ||
| 1071 | + path-exists@4.0.0: | ||
| 1072 | + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} | ||
| 1073 | + engines: {node: '>=8'} | ||
| 1074 | + | ||
| 1075 | + path-key@3.1.1: | ||
| 1076 | + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} | ||
| 1077 | + engines: {node: '>=8'} | ||
| 1078 | + | ||
| 1079 | + path-parse@1.0.7: | ||
| 1080 | + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} | ||
| 1081 | + | ||
| 1082 | + path-scurry@1.11.1: | ||
| 1083 | + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} | ||
| 1084 | + engines: {node: '>=16 || 14 >=14.18'} | ||
| 1085 | + | ||
| 1086 | + picocolors@1.1.1: | ||
| 1087 | + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} | ||
| 1088 | + | ||
| 1089 | + picomatch@2.3.1: | ||
| 1090 | + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} | ||
| 1091 | + engines: {node: '>=8.6'} | ||
| 1092 | + | ||
| 1093 | + pify@2.3.0: | ||
| 1094 | + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} | ||
| 1095 | + engines: {node: '>=0.10.0'} | ||
| 1096 | + | ||
| 1097 | + pinia@2.3.1: | ||
| 1098 | + resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==} | ||
| 1099 | + peerDependencies: | ||
| 1100 | + typescript: '>=4.4.4' | ||
| 1101 | + vue: ^2.7.0 || ^3.5.11 | ||
| 1102 | + peerDependenciesMeta: | ||
| 1103 | + typescript: | ||
| 1104 | + optional: true | ||
| 1105 | + | ||
| 1106 | + pirates@4.0.7: | ||
| 1107 | + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} | ||
| 1108 | + engines: {node: '>= 6'} | ||
| 1109 | + | ||
| 1110 | + postcss-import@15.1.0: | ||
| 1111 | + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} | ||
| 1112 | + engines: {node: '>=14.0.0'} | ||
| 1113 | + peerDependencies: | ||
| 1114 | + postcss: ^8.0.0 | ||
| 1115 | + | ||
| 1116 | + postcss-js@4.0.1: | ||
| 1117 | + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} | ||
| 1118 | + engines: {node: ^12 || ^14 || >= 16} | ||
| 1119 | + peerDependencies: | ||
| 1120 | + postcss: ^8.4.21 | ||
| 1121 | + | ||
| 1122 | + postcss-load-config@4.0.2: | ||
| 1123 | + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} | ||
| 1124 | + engines: {node: '>= 14'} | ||
| 1125 | + peerDependencies: | ||
| 1126 | + postcss: '>=8.0.9' | ||
| 1127 | + ts-node: '>=9.0.0' | ||
| 1128 | + peerDependenciesMeta: | ||
| 1129 | + postcss: | ||
| 1130 | + optional: true | ||
| 1131 | + ts-node: | ||
| 1132 | + optional: true | ||
| 1133 | + | ||
| 1134 | + postcss-nested@6.2.0: | ||
| 1135 | + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} | ||
| 1136 | + engines: {node: '>=12.0'} | ||
| 1137 | + peerDependencies: | ||
| 1138 | + postcss: ^8.2.14 | ||
| 1139 | + | ||
| 1140 | + postcss-selector-parser@6.1.2: | ||
| 1141 | + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} | ||
| 1142 | + engines: {node: '>=4'} | ||
| 1143 | + | ||
| 1144 | + postcss-value-parser@4.2.0: | ||
| 1145 | + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} | ||
| 1146 | + | ||
| 1147 | + postcss@8.5.3: | ||
| 1148 | + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} | ||
| 1149 | + engines: {node: ^10 || ^12 || >=14} | ||
| 1150 | + | ||
| 1151 | + prelude-ls@1.2.1: | ||
| 1152 | + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} | ||
| 1153 | + engines: {node: '>= 0.8.0'} | ||
| 1154 | + | ||
| 1155 | + punycode@2.3.1: | ||
| 1156 | + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} | ||
| 1157 | + engines: {node: '>=6'} | ||
| 1158 | + | ||
| 1159 | + queue-microtask@1.2.3: | ||
| 1160 | + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} | ||
| 1161 | + | ||
| 1162 | + read-cache@1.0.0: | ||
| 1163 | + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} | ||
| 1164 | + | ||
| 1165 | + readdirp@3.6.0: | ||
| 1166 | + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} | ||
| 1167 | + engines: {node: '>=8.10.0'} | ||
| 1168 | + | ||
| 1169 | + resolve-from@4.0.0: | ||
| 1170 | + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} | ||
| 1171 | + engines: {node: '>=4'} | ||
| 1172 | + | ||
| 1173 | + resolve@1.22.10: | ||
| 1174 | + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} | ||
| 1175 | + engines: {node: '>= 0.4'} | ||
| 1176 | + hasBin: true | ||
| 1177 | + | ||
| 1178 | + reusify@1.1.0: | ||
| 1179 | + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} | ||
| 1180 | + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} | ||
| 1181 | + | ||
| 1182 | + rollup@4.40.0: | ||
| 1183 | + resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} | ||
| 1184 | + engines: {node: '>=18.0.0', npm: '>=8.0.0'} | ||
| 1185 | + hasBin: true | ||
| 1186 | + | ||
| 1187 | + run-parallel@1.2.0: | ||
| 1188 | + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} | ||
| 1189 | + | ||
| 1190 | + semver@6.3.1: | ||
| 1191 | + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} | ||
| 1192 | + hasBin: true | ||
| 1193 | + | ||
| 1194 | + semver@7.7.1: | ||
| 1195 | + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} | ||
| 1196 | + engines: {node: '>=10'} | ||
| 1197 | + hasBin: true | ||
| 1198 | + | ||
| 1199 | + shebang-command@2.0.0: | ||
| 1200 | + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} | ||
| 1201 | + engines: {node: '>=8'} | ||
| 1202 | + | ||
| 1203 | + shebang-regex@3.0.0: | ||
| 1204 | + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} | ||
| 1205 | + engines: {node: '>=8'} | ||
| 1206 | + | ||
| 1207 | + signal-exit@4.1.0: | ||
| 1208 | + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} | ||
| 1209 | + engines: {node: '>=14'} | ||
| 1210 | + | ||
| 1211 | + source-map-js@1.2.1: | ||
| 1212 | + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} | ||
| 1213 | + engines: {node: '>=0.10.0'} | ||
| 1214 | + | ||
| 1215 | + string-width@4.2.3: | ||
| 1216 | + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} | ||
| 1217 | + engines: {node: '>=8'} | ||
| 1218 | + | ||
| 1219 | + string-width@5.1.2: | ||
| 1220 | + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} | ||
| 1221 | + engines: {node: '>=12'} | ||
| 1222 | + | ||
| 1223 | + strip-ansi@6.0.1: | ||
| 1224 | + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} | ||
| 1225 | + engines: {node: '>=8'} | ||
| 1226 | + | ||
| 1227 | + strip-ansi@7.1.0: | ||
| 1228 | + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} | ||
| 1229 | + engines: {node: '>=12'} | ||
| 1230 | + | ||
| 1231 | + strip-json-comments@3.1.1: | ||
| 1232 | + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} | ||
| 1233 | + engines: {node: '>=8'} | ||
| 1234 | + | ||
| 1235 | + sucrase@3.35.0: | ||
| 1236 | + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} | ||
| 1237 | + engines: {node: '>=16 || 14 >=14.17'} | ||
| 1238 | + hasBin: true | ||
| 1239 | + | ||
| 1240 | + supports-color@7.2.0: | ||
| 1241 | + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} | ||
| 1242 | + engines: {node: '>=8'} | ||
| 1243 | + | ||
| 1244 | + supports-preserve-symlinks-flag@1.0.0: | ||
| 1245 | + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} | ||
| 1246 | + engines: {node: '>= 0.4'} | ||
| 1247 | + | ||
| 1248 | + tailwindcss@3.4.17: | ||
| 1249 | + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} | ||
| 1250 | + engines: {node: '>=14.0.0'} | ||
| 1251 | + hasBin: true | ||
| 1252 | + | ||
| 1253 | + thenify-all@1.6.0: | ||
| 1254 | + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} | ||
| 1255 | + engines: {node: '>=0.8'} | ||
| 1256 | + | ||
| 1257 | + thenify@3.3.1: | ||
| 1258 | + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} | ||
| 1259 | + | ||
| 1260 | + to-regex-range@5.0.1: | ||
| 1261 | + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} | ||
| 1262 | + engines: {node: '>=8.0'} | ||
| 1263 | + | ||
| 1264 | + ts-interface-checker@0.1.13: | ||
| 1265 | + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} | ||
| 1266 | + | ||
| 1267 | + type-check@0.4.0: | ||
| 1268 | + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} | ||
| 1269 | + engines: {node: '>= 0.8.0'} | ||
| 1270 | + | ||
| 1271 | + type-fest@0.20.2: | ||
| 1272 | + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} | ||
| 1273 | + engines: {node: '>=10'} | ||
| 1274 | + | ||
| 1275 | + update-browserslist-db@1.1.3: | ||
| 1276 | + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} | ||
| 1277 | + hasBin: true | ||
| 1278 | + peerDependencies: | ||
| 1279 | + browserslist: '>= 4.21.0' | ||
| 1280 | + | ||
| 1281 | + uri-js@4.4.1: | ||
| 1282 | + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} | ||
| 1283 | + | ||
| 1284 | + util-deprecate@1.0.2: | ||
| 1285 | + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} | ||
| 1286 | + | ||
| 1287 | + vite@5.4.18: | ||
| 1288 | + resolution: {integrity: sha512-1oDcnEp3lVyHCuQ2YFelM4Alm2o91xNoMncRm1U7S+JdYfYOvbiGZ3/CxGttrOu2M/KcGz7cRC2DoNUA6urmMA==} | ||
| 1289 | + engines: {node: ^18.0.0 || >=20.0.0} | ||
| 1290 | + hasBin: true | ||
| 1291 | + peerDependencies: | ||
| 1292 | + '@types/node': ^18.0.0 || >=20.0.0 | ||
| 1293 | + less: '*' | ||
| 1294 | + lightningcss: ^1.21.0 | ||
| 1295 | + sass: '*' | ||
| 1296 | + sass-embedded: '*' | ||
| 1297 | + stylus: '*' | ||
| 1298 | + sugarss: '*' | ||
| 1299 | + terser: ^5.4.0 | ||
| 1300 | + peerDependenciesMeta: | ||
| 1301 | + '@types/node': | ||
| 1302 | + optional: true | ||
| 1303 | + less: | ||
| 1304 | + optional: true | ||
| 1305 | + lightningcss: | ||
| 1306 | + optional: true | ||
| 1307 | + sass: | ||
| 1308 | + optional: true | ||
| 1309 | + sass-embedded: | ||
| 1310 | + optional: true | ||
| 1311 | + stylus: | ||
| 1312 | + optional: true | ||
| 1313 | + sugarss: | ||
| 1314 | + optional: true | ||
| 1315 | + terser: | ||
| 1316 | + optional: true | ||
| 1317 | + | ||
| 1318 | + vue-demi@0.14.10: | ||
| 1319 | + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} | ||
| 1320 | + engines: {node: '>=12'} | ||
| 1321 | + hasBin: true | ||
| 1322 | + peerDependencies: | ||
| 1323 | + '@vue/composition-api': ^1.0.0-rc.1 | ||
| 1324 | + vue: ^3.0.0-0 || ^2.6.0 | ||
| 1325 | + peerDependenciesMeta: | ||
| 1326 | + '@vue/composition-api': | ||
| 1327 | + optional: true | ||
| 1328 | + | ||
| 1329 | + vue-eslint-parser@9.4.3: | ||
| 1330 | + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} | ||
| 1331 | + engines: {node: ^14.17.0 || >=16.0.0} | ||
| 1332 | + peerDependencies: | ||
| 1333 | + eslint: '>=6.0.0' | ||
| 1334 | + | ||
| 1335 | + vue-router@4.5.0: | ||
| 1336 | + resolution: {integrity: sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==} | ||
| 1337 | + peerDependencies: | ||
| 1338 | + vue: ^3.2.0 | ||
| 1339 | + | ||
| 1340 | + vue@3.5.13: | ||
| 1341 | + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} | ||
| 1342 | + peerDependencies: | ||
| 1343 | + typescript: '*' | ||
| 1344 | + peerDependenciesMeta: | ||
| 1345 | + typescript: | ||
| 1346 | + optional: true | ||
| 1347 | + | ||
| 1348 | + which@2.0.2: | ||
| 1349 | + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} | ||
| 1350 | + engines: {node: '>= 8'} | ||
| 1351 | + hasBin: true | ||
| 1352 | + | ||
| 1353 | + word-wrap@1.2.5: | ||
| 1354 | + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} | ||
| 1355 | + engines: {node: '>=0.10.0'} | ||
| 1356 | + | ||
| 1357 | + wrap-ansi@7.0.0: | ||
| 1358 | + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} | ||
| 1359 | + engines: {node: '>=10'} | ||
| 1360 | + | ||
| 1361 | + wrap-ansi@8.1.0: | ||
| 1362 | + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} | ||
| 1363 | + engines: {node: '>=12'} | ||
| 1364 | + | ||
| 1365 | + xml-name-validator@4.0.0: | ||
| 1366 | + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} | ||
| 1367 | + engines: {node: '>=12'} | ||
| 1368 | + | ||
| 1369 | + yallist@3.1.1: | ||
| 1370 | + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} | ||
| 1371 | + | ||
| 1372 | + yaml@2.7.1: | ||
| 1373 | + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} | ||
| 1374 | + engines: {node: '>= 14'} | ||
| 1375 | + hasBin: true | ||
| 1376 | + | ||
| 1377 | + yocto-queue@0.1.0: | ||
| 1378 | + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} | ||
| 1379 | + engines: {node: '>=10'} | ||
| 1380 | + | ||
| 1381 | +snapshots: | ||
| 1382 | + | ||
| 1383 | + '@alloc/quick-lru@5.2.0': {} | ||
| 1384 | + | ||
| 1385 | + '@ampproject/remapping@2.3.0': | ||
| 1386 | + dependencies: | ||
| 1387 | + '@jridgewell/gen-mapping': 0.3.8 | ||
| 1388 | + '@jridgewell/trace-mapping': 0.3.25 | ||
| 1389 | + | ||
| 1390 | + '@babel/code-frame@7.26.2': | ||
| 1391 | + dependencies: | ||
| 1392 | + '@babel/helper-validator-identifier': 7.25.9 | ||
| 1393 | + js-tokens: 4.0.0 | ||
| 1394 | + picocolors: 1.1.1 | ||
| 1395 | + | ||
| 1396 | + '@babel/compat-data@7.26.8': {} | ||
| 1397 | + | ||
| 1398 | + '@babel/core@7.26.10': | ||
| 1399 | + dependencies: | ||
| 1400 | + '@ampproject/remapping': 2.3.0 | ||
| 1401 | + '@babel/code-frame': 7.26.2 | ||
| 1402 | + '@babel/generator': 7.27.0 | ||
| 1403 | + '@babel/helper-compilation-targets': 7.27.0 | ||
| 1404 | + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) | ||
| 1405 | + '@babel/helpers': 7.27.0 | ||
| 1406 | + '@babel/parser': 7.27.0 | ||
| 1407 | + '@babel/template': 7.27.0 | ||
| 1408 | + '@babel/traverse': 7.27.0 | ||
| 1409 | + '@babel/types': 7.27.0 | ||
| 1410 | + convert-source-map: 2.0.0 | ||
| 1411 | + debug: 4.4.0 | ||
| 1412 | + gensync: 1.0.0-beta.2 | ||
| 1413 | + json5: 2.2.3 | ||
| 1414 | + semver: 6.3.1 | ||
| 1415 | + transitivePeerDependencies: | ||
| 1416 | + - supports-color | ||
| 1417 | + | ||
| 1418 | + '@babel/generator@7.27.0': | ||
| 1419 | + dependencies: | ||
| 1420 | + '@babel/parser': 7.27.0 | ||
| 1421 | + '@babel/types': 7.27.0 | ||
| 1422 | + '@jridgewell/gen-mapping': 0.3.8 | ||
| 1423 | + '@jridgewell/trace-mapping': 0.3.25 | ||
| 1424 | + jsesc: 3.1.0 | ||
| 1425 | + | ||
| 1426 | + '@babel/helper-annotate-as-pure@7.25.9': | ||
| 1427 | + dependencies: | ||
| 1428 | + '@babel/types': 7.27.0 | ||
| 1429 | + | ||
| 1430 | + '@babel/helper-compilation-targets@7.27.0': | ||
| 1431 | + dependencies: | ||
| 1432 | + '@babel/compat-data': 7.26.8 | ||
| 1433 | + '@babel/helper-validator-option': 7.25.9 | ||
| 1434 | + browserslist: 4.24.4 | ||
| 1435 | + lru-cache: 5.1.1 | ||
| 1436 | + semver: 6.3.1 | ||
| 1437 | + | ||
| 1438 | + '@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)': | ||
| 1439 | + dependencies: | ||
| 1440 | + '@babel/core': 7.26.10 | ||
| 1441 | + '@babel/helper-annotate-as-pure': 7.25.9 | ||
| 1442 | + '@babel/helper-member-expression-to-functions': 7.25.9 | ||
| 1443 | + '@babel/helper-optimise-call-expression': 7.25.9 | ||
| 1444 | + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) | ||
| 1445 | + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 | ||
| 1446 | + '@babel/traverse': 7.27.0 | ||
| 1447 | + semver: 6.3.1 | ||
| 1448 | + transitivePeerDependencies: | ||
| 1449 | + - supports-color | ||
| 1450 | + | ||
| 1451 | + '@babel/helper-member-expression-to-functions@7.25.9': | ||
| 1452 | + dependencies: | ||
| 1453 | + '@babel/traverse': 7.27.0 | ||
| 1454 | + '@babel/types': 7.27.0 | ||
| 1455 | + transitivePeerDependencies: | ||
| 1456 | + - supports-color | ||
| 1457 | + | ||
| 1458 | + '@babel/helper-module-imports@7.25.9': | ||
| 1459 | + dependencies: | ||
| 1460 | + '@babel/traverse': 7.27.0 | ||
| 1461 | + '@babel/types': 7.27.0 | ||
| 1462 | + transitivePeerDependencies: | ||
| 1463 | + - supports-color | ||
| 1464 | + | ||
| 1465 | + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': | ||
| 1466 | + dependencies: | ||
| 1467 | + '@babel/core': 7.26.10 | ||
| 1468 | + '@babel/helper-module-imports': 7.25.9 | ||
| 1469 | + '@babel/helper-validator-identifier': 7.25.9 | ||
| 1470 | + '@babel/traverse': 7.27.0 | ||
| 1471 | + transitivePeerDependencies: | ||
| 1472 | + - supports-color | ||
| 1473 | + | ||
| 1474 | + '@babel/helper-optimise-call-expression@7.25.9': | ||
| 1475 | + dependencies: | ||
| 1476 | + '@babel/types': 7.27.0 | ||
| 1477 | + | ||
| 1478 | + '@babel/helper-plugin-utils@7.26.5': {} | ||
| 1479 | + | ||
| 1480 | + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.10)': | ||
| 1481 | + dependencies: | ||
| 1482 | + '@babel/core': 7.26.10 | ||
| 1483 | + '@babel/helper-member-expression-to-functions': 7.25.9 | ||
| 1484 | + '@babel/helper-optimise-call-expression': 7.25.9 | ||
| 1485 | + '@babel/traverse': 7.27.0 | ||
| 1486 | + transitivePeerDependencies: | ||
| 1487 | + - supports-color | ||
| 1488 | + | ||
| 1489 | + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': | ||
| 1490 | + dependencies: | ||
| 1491 | + '@babel/traverse': 7.27.0 | ||
| 1492 | + '@babel/types': 7.27.0 | ||
| 1493 | + transitivePeerDependencies: | ||
| 1494 | + - supports-color | ||
| 1495 | + | ||
| 1496 | + '@babel/helper-string-parser@7.25.9': {} | ||
| 1497 | + | ||
| 1498 | + '@babel/helper-validator-identifier@7.25.9': {} | ||
| 1499 | + | ||
| 1500 | + '@babel/helper-validator-option@7.25.9': {} | ||
| 1501 | + | ||
| 1502 | + '@babel/helpers@7.27.0': | ||
| 1503 | + dependencies: | ||
| 1504 | + '@babel/template': 7.27.0 | ||
| 1505 | + '@babel/types': 7.27.0 | ||
| 1506 | + | ||
| 1507 | + '@babel/parser@7.27.0': | ||
| 1508 | + dependencies: | ||
| 1509 | + '@babel/types': 7.27.0 | ||
| 1510 | + | ||
| 1511 | + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': | ||
| 1512 | + dependencies: | ||
| 1513 | + '@babel/core': 7.26.10 | ||
| 1514 | + '@babel/helper-plugin-utils': 7.26.5 | ||
| 1515 | + | ||
| 1516 | + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': | ||
| 1517 | + dependencies: | ||
| 1518 | + '@babel/core': 7.26.10 | ||
| 1519 | + '@babel/helper-plugin-utils': 7.26.5 | ||
| 1520 | + | ||
| 1521 | + '@babel/plugin-transform-typescript@7.27.0(@babel/core@7.26.10)': | ||
| 1522 | + dependencies: | ||
| 1523 | + '@babel/core': 7.26.10 | ||
| 1524 | + '@babel/helper-annotate-as-pure': 7.25.9 | ||
| 1525 | + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) | ||
| 1526 | + '@babel/helper-plugin-utils': 7.26.5 | ||
| 1527 | + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 | ||
| 1528 | + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) | ||
| 1529 | + transitivePeerDependencies: | ||
| 1530 | + - supports-color | ||
| 1531 | + | ||
| 1532 | + '@babel/template@7.27.0': | ||
| 1533 | + dependencies: | ||
| 1534 | + '@babel/code-frame': 7.26.2 | ||
| 1535 | + '@babel/parser': 7.27.0 | ||
| 1536 | + '@babel/types': 7.27.0 | ||
| 1537 | + | ||
| 1538 | + '@babel/traverse@7.27.0': | ||
| 1539 | + dependencies: | ||
| 1540 | + '@babel/code-frame': 7.26.2 | ||
| 1541 | + '@babel/generator': 7.27.0 | ||
| 1542 | + '@babel/parser': 7.27.0 | ||
| 1543 | + '@babel/template': 7.27.0 | ||
| 1544 | + '@babel/types': 7.27.0 | ||
| 1545 | + debug: 4.4.0 | ||
| 1546 | + globals: 11.12.0 | ||
| 1547 | + transitivePeerDependencies: | ||
| 1548 | + - supports-color | ||
| 1549 | + | ||
| 1550 | + '@babel/types@7.27.0': | ||
| 1551 | + dependencies: | ||
| 1552 | + '@babel/helper-string-parser': 7.25.9 | ||
| 1553 | + '@babel/helper-validator-identifier': 7.25.9 | ||
| 1554 | + | ||
| 1555 | + '@esbuild/aix-ppc64@0.21.5': | ||
| 1556 | + optional: true | ||
| 1557 | + | ||
| 1558 | + '@esbuild/android-arm64@0.21.5': | ||
| 1559 | + optional: true | ||
| 1560 | + | ||
| 1561 | + '@esbuild/android-arm@0.21.5': | ||
| 1562 | + optional: true | ||
| 1563 | + | ||
| 1564 | + '@esbuild/android-x64@0.21.5': | ||
| 1565 | + optional: true | ||
| 1566 | + | ||
| 1567 | + '@esbuild/darwin-arm64@0.21.5': | ||
| 1568 | + optional: true | ||
| 1569 | + | ||
| 1570 | + '@esbuild/darwin-x64@0.21.5': | ||
| 1571 | + optional: true | ||
| 1572 | + | ||
| 1573 | + '@esbuild/freebsd-arm64@0.21.5': | ||
| 1574 | + optional: true | ||
| 1575 | + | ||
| 1576 | + '@esbuild/freebsd-x64@0.21.5': | ||
| 1577 | + optional: true | ||
| 1578 | + | ||
| 1579 | + '@esbuild/linux-arm64@0.21.5': | ||
| 1580 | + optional: true | ||
| 1581 | + | ||
| 1582 | + '@esbuild/linux-arm@0.21.5': | ||
| 1583 | + optional: true | ||
| 1584 | + | ||
| 1585 | + '@esbuild/linux-ia32@0.21.5': | ||
| 1586 | + optional: true | ||
| 1587 | + | ||
| 1588 | + '@esbuild/linux-loong64@0.21.5': | ||
| 1589 | + optional: true | ||
| 1590 | + | ||
| 1591 | + '@esbuild/linux-mips64el@0.21.5': | ||
| 1592 | + optional: true | ||
| 1593 | + | ||
| 1594 | + '@esbuild/linux-ppc64@0.21.5': | ||
| 1595 | + optional: true | ||
| 1596 | + | ||
| 1597 | + '@esbuild/linux-riscv64@0.21.5': | ||
| 1598 | + optional: true | ||
| 1599 | + | ||
| 1600 | + '@esbuild/linux-s390x@0.21.5': | ||
| 1601 | + optional: true | ||
| 1602 | + | ||
| 1603 | + '@esbuild/linux-x64@0.21.5': | ||
| 1604 | + optional: true | ||
| 1605 | + | ||
| 1606 | + '@esbuild/netbsd-x64@0.21.5': | ||
| 1607 | + optional: true | ||
| 1608 | + | ||
| 1609 | + '@esbuild/openbsd-x64@0.21.5': | ||
| 1610 | + optional: true | ||
| 1611 | + | ||
| 1612 | + '@esbuild/sunos-x64@0.21.5': | ||
| 1613 | + optional: true | ||
| 1614 | + | ||
| 1615 | + '@esbuild/win32-arm64@0.21.5': | ||
| 1616 | + optional: true | ||
| 1617 | + | ||
| 1618 | + '@esbuild/win32-ia32@0.21.5': | ||
| 1619 | + optional: true | ||
| 1620 | + | ||
| 1621 | + '@esbuild/win32-x64@0.21.5': | ||
| 1622 | + optional: true | ||
| 1623 | + | ||
| 1624 | + '@eslint-community/eslint-utils@4.6.1(eslint@9.24.0(jiti@1.21.7))': | ||
| 1625 | + dependencies: | ||
| 1626 | + eslint: 9.24.0(jiti@1.21.7) | ||
| 1627 | + eslint-visitor-keys: 3.4.3 | ||
| 1628 | + | ||
| 1629 | + '@eslint-community/regexpp@4.12.1': {} | ||
| 1630 | + | ||
| 1631 | + '@eslint/config-array@0.20.0': | ||
| 1632 | + dependencies: | ||
| 1633 | + '@eslint/object-schema': 2.1.6 | ||
| 1634 | + debug: 4.4.0 | ||
| 1635 | + minimatch: 3.1.2 | ||
| 1636 | + transitivePeerDependencies: | ||
| 1637 | + - supports-color | ||
| 1638 | + | ||
| 1639 | + '@eslint/config-helpers@0.2.1': {} | ||
| 1640 | + | ||
| 1641 | + '@eslint/core@0.12.0': | ||
| 1642 | + dependencies: | ||
| 1643 | + '@types/json-schema': 7.0.15 | ||
| 1644 | + | ||
| 1645 | + '@eslint/core@0.13.0': | ||
| 1646 | + dependencies: | ||
| 1647 | + '@types/json-schema': 7.0.15 | ||
| 1648 | + | ||
| 1649 | + '@eslint/eslintrc@3.3.1': | ||
| 1650 | + dependencies: | ||
| 1651 | + ajv: 6.12.6 | ||
| 1652 | + debug: 4.4.0 | ||
| 1653 | + espree: 10.3.0 | ||
| 1654 | + globals: 14.0.0 | ||
| 1655 | + ignore: 5.3.2 | ||
| 1656 | + import-fresh: 3.3.1 | ||
| 1657 | + js-yaml: 4.1.0 | ||
| 1658 | + minimatch: 3.1.2 | ||
| 1659 | + strip-json-comments: 3.1.1 | ||
| 1660 | + transitivePeerDependencies: | ||
| 1661 | + - supports-color | ||
| 1662 | + | ||
| 1663 | + '@eslint/js@9.24.0': {} | ||
| 1664 | + | ||
| 1665 | + '@eslint/object-schema@2.1.6': {} | ||
| 1666 | + | ||
| 1667 | + '@eslint/plugin-kit@0.2.8': | ||
| 1668 | + dependencies: | ||
| 1669 | + '@eslint/core': 0.13.0 | ||
| 1670 | + levn: 0.4.1 | ||
| 1671 | + | ||
| 1672 | + '@humanfs/core@0.19.1': {} | ||
| 1673 | + | ||
| 1674 | + '@humanfs/node@0.16.6': | ||
| 1675 | + dependencies: | ||
| 1676 | + '@humanfs/core': 0.19.1 | ||
| 1677 | + '@humanwhocodes/retry': 0.3.1 | ||
| 1678 | + | ||
| 1679 | + '@humanwhocodes/module-importer@1.0.1': {} | ||
| 1680 | + | ||
| 1681 | + '@humanwhocodes/retry@0.3.1': {} | ||
| 1682 | + | ||
| 1683 | + '@humanwhocodes/retry@0.4.2': {} | ||
| 1684 | + | ||
| 1685 | + '@isaacs/cliui@8.0.2': | ||
| 1686 | + dependencies: | ||
| 1687 | + string-width: 5.1.2 | ||
| 1688 | + string-width-cjs: string-width@4.2.3 | ||
| 1689 | + strip-ansi: 7.1.0 | ||
| 1690 | + strip-ansi-cjs: strip-ansi@6.0.1 | ||
| 1691 | + wrap-ansi: 8.1.0 | ||
| 1692 | + wrap-ansi-cjs: wrap-ansi@7.0.0 | ||
| 1693 | + | ||
| 1694 | + '@jridgewell/gen-mapping@0.3.8': | ||
| 1695 | + dependencies: | ||
| 1696 | + '@jridgewell/set-array': 1.2.1 | ||
| 1697 | + '@jridgewell/sourcemap-codec': 1.5.0 | ||
| 1698 | + '@jridgewell/trace-mapping': 0.3.25 | ||
| 1699 | + | ||
| 1700 | + '@jridgewell/resolve-uri@3.1.2': {} | ||
| 1701 | + | ||
| 1702 | + '@jridgewell/set-array@1.2.1': {} | ||
| 1703 | + | ||
| 1704 | + '@jridgewell/sourcemap-codec@1.5.0': {} | ||
| 1705 | + | ||
| 1706 | + '@jridgewell/trace-mapping@0.3.25': | ||
| 1707 | + dependencies: | ||
| 1708 | + '@jridgewell/resolve-uri': 3.1.2 | ||
| 1709 | + '@jridgewell/sourcemap-codec': 1.5.0 | ||
| 1710 | + | ||
| 1711 | + '@nodelib/fs.scandir@2.1.5': | ||
| 1712 | + dependencies: | ||
| 1713 | + '@nodelib/fs.stat': 2.0.5 | ||
| 1714 | + run-parallel: 1.2.0 | ||
| 1715 | + | ||
| 1716 | + '@nodelib/fs.stat@2.0.5': {} | ||
| 1717 | + | ||
| 1718 | + '@nodelib/fs.walk@1.2.8': | ||
| 1719 | + dependencies: | ||
| 1720 | + '@nodelib/fs.scandir': 2.1.5 | ||
| 1721 | + fastq: 1.19.1 | ||
| 1722 | + | ||
| 1723 | + '@pkgjs/parseargs@0.11.0': | ||
| 1724 | + optional: true | ||
| 1725 | + | ||
| 1726 | + '@rollup/rollup-android-arm-eabi@4.40.0': | ||
| 1727 | + optional: true | ||
| 1728 | + | ||
| 1729 | + '@rollup/rollup-android-arm64@4.40.0': | ||
| 1730 | + optional: true | ||
| 1731 | + | ||
| 1732 | + '@rollup/rollup-darwin-arm64@4.40.0': | ||
| 1733 | + optional: true | ||
| 1734 | + | ||
| 1735 | + '@rollup/rollup-darwin-x64@4.40.0': | ||
| 1736 | + optional: true | ||
| 1737 | + | ||
| 1738 | + '@rollup/rollup-freebsd-arm64@4.40.0': | ||
| 1739 | + optional: true | ||
| 1740 | + | ||
| 1741 | + '@rollup/rollup-freebsd-x64@4.40.0': | ||
| 1742 | + optional: true | ||
| 1743 | + | ||
| 1744 | + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': | ||
| 1745 | + optional: true | ||
| 1746 | + | ||
| 1747 | + '@rollup/rollup-linux-arm-musleabihf@4.40.0': | ||
| 1748 | + optional: true | ||
| 1749 | + | ||
| 1750 | + '@rollup/rollup-linux-arm64-gnu@4.40.0': | ||
| 1751 | + optional: true | ||
| 1752 | + | ||
| 1753 | + '@rollup/rollup-linux-arm64-musl@4.40.0': | ||
| 1754 | + optional: true | ||
| 1755 | + | ||
| 1756 | + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': | ||
| 1757 | + optional: true | ||
| 1758 | + | ||
| 1759 | + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': | ||
| 1760 | + optional: true | ||
| 1761 | + | ||
| 1762 | + '@rollup/rollup-linux-riscv64-gnu@4.40.0': | ||
| 1763 | + optional: true | ||
| 1764 | + | ||
| 1765 | + '@rollup/rollup-linux-riscv64-musl@4.40.0': | ||
| 1766 | + optional: true | ||
| 1767 | + | ||
| 1768 | + '@rollup/rollup-linux-s390x-gnu@4.40.0': | ||
| 1769 | + optional: true | ||
| 1770 | + | ||
| 1771 | + '@rollup/rollup-linux-x64-gnu@4.40.0': | ||
| 1772 | + optional: true | ||
| 1773 | + | ||
| 1774 | + '@rollup/rollup-linux-x64-musl@4.40.0': | ||
| 1775 | + optional: true | ||
| 1776 | + | ||
| 1777 | + '@rollup/rollup-win32-arm64-msvc@4.40.0': | ||
| 1778 | + optional: true | ||
| 1779 | + | ||
| 1780 | + '@rollup/rollup-win32-ia32-msvc@4.40.0': | ||
| 1781 | + optional: true | ||
| 1782 | + | ||
| 1783 | + '@rollup/rollup-win32-x64-msvc@4.40.0': | ||
| 1784 | + optional: true | ||
| 1785 | + | ||
| 1786 | + '@types/estree@1.0.7': {} | ||
| 1787 | + | ||
| 1788 | + '@types/json-schema@7.0.15': {} | ||
| 1789 | + | ||
| 1790 | + '@vitejs/plugin-vue-jsx@4.1.2(vite@5.4.18)(vue@3.5.13)': | ||
| 1791 | + dependencies: | ||
| 1792 | + '@babel/core': 7.26.10 | ||
| 1793 | + '@babel/plugin-transform-typescript': 7.27.0(@babel/core@7.26.10) | ||
| 1794 | + '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.26.10) | ||
| 1795 | + vite: 5.4.18 | ||
| 1796 | + vue: 3.5.13 | ||
| 1797 | + transitivePeerDependencies: | ||
| 1798 | + - supports-color | ||
| 1799 | + | ||
| 1800 | + '@vitejs/plugin-vue@5.2.3(vite@5.4.18)(vue@3.5.13)': | ||
| 1801 | + dependencies: | ||
| 1802 | + vite: 5.4.18 | ||
| 1803 | + vue: 3.5.13 | ||
| 1804 | + | ||
| 1805 | + '@vue/babel-helper-vue-transform-on@1.4.0': {} | ||
| 1806 | + | ||
| 1807 | + '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.26.10)': | ||
| 1808 | + dependencies: | ||
| 1809 | + '@babel/helper-module-imports': 7.25.9 | ||
| 1810 | + '@babel/helper-plugin-utils': 7.26.5 | ||
| 1811 | + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) | ||
| 1812 | + '@babel/template': 7.27.0 | ||
| 1813 | + '@babel/traverse': 7.27.0 | ||
| 1814 | + '@babel/types': 7.27.0 | ||
| 1815 | + '@vue/babel-helper-vue-transform-on': 1.4.0 | ||
| 1816 | + '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.26.10) | ||
| 1817 | + '@vue/shared': 3.5.13 | ||
| 1818 | + optionalDependencies: | ||
| 1819 | + '@babel/core': 7.26.10 | ||
| 1820 | + transitivePeerDependencies: | ||
| 1821 | + - supports-color | ||
| 1822 | + | ||
| 1823 | + '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.26.10)': | ||
| 1824 | + dependencies: | ||
| 1825 | + '@babel/code-frame': 7.26.2 | ||
| 1826 | + '@babel/core': 7.26.10 | ||
| 1827 | + '@babel/helper-module-imports': 7.25.9 | ||
| 1828 | + '@babel/helper-plugin-utils': 7.26.5 | ||
| 1829 | + '@babel/parser': 7.27.0 | ||
| 1830 | + '@vue/compiler-sfc': 3.5.13 | ||
| 1831 | + transitivePeerDependencies: | ||
| 1832 | + - supports-color | ||
| 1833 | + | ||
| 1834 | + '@vue/compiler-core@3.5.13': | ||
| 1835 | + dependencies: | ||
| 1836 | + '@babel/parser': 7.27.0 | ||
| 1837 | + '@vue/shared': 3.5.13 | ||
| 1838 | + entities: 4.5.0 | ||
| 1839 | + estree-walker: 2.0.2 | ||
| 1840 | + source-map-js: 1.2.1 | ||
| 1841 | + | ||
| 1842 | + '@vue/compiler-dom@3.5.13': | ||
| 1843 | + dependencies: | ||
| 1844 | + '@vue/compiler-core': 3.5.13 | ||
| 1845 | + '@vue/shared': 3.5.13 | ||
| 1846 | + | ||
| 1847 | + '@vue/compiler-sfc@3.5.13': | ||
| 1848 | + dependencies: | ||
| 1849 | + '@babel/parser': 7.27.0 | ||
| 1850 | + '@vue/compiler-core': 3.5.13 | ||
| 1851 | + '@vue/compiler-dom': 3.5.13 | ||
| 1852 | + '@vue/compiler-ssr': 3.5.13 | ||
| 1853 | + '@vue/shared': 3.5.13 | ||
| 1854 | + estree-walker: 2.0.2 | ||
| 1855 | + magic-string: 0.30.17 | ||
| 1856 | + postcss: 8.5.3 | ||
| 1857 | + source-map-js: 1.2.1 | ||
| 1858 | + | ||
| 1859 | + '@vue/compiler-ssr@3.5.13': | ||
| 1860 | + dependencies: | ||
| 1861 | + '@vue/compiler-dom': 3.5.13 | ||
| 1862 | + '@vue/shared': 3.5.13 | ||
| 1863 | + | ||
| 1864 | + '@vue/devtools-api@6.6.4': {} | ||
| 1865 | + | ||
| 1866 | + '@vue/reactivity@3.5.13': | ||
| 1867 | + dependencies: | ||
| 1868 | + '@vue/shared': 3.5.13 | ||
| 1869 | + | ||
| 1870 | + '@vue/runtime-core@3.5.13': | ||
| 1871 | + dependencies: | ||
| 1872 | + '@vue/reactivity': 3.5.13 | ||
| 1873 | + '@vue/shared': 3.5.13 | ||
| 1874 | + | ||
| 1875 | + '@vue/runtime-dom@3.5.13': | ||
| 1876 | + dependencies: | ||
| 1877 | + '@vue/reactivity': 3.5.13 | ||
| 1878 | + '@vue/runtime-core': 3.5.13 | ||
| 1879 | + '@vue/shared': 3.5.13 | ||
| 1880 | + csstype: 3.1.3 | ||
| 1881 | + | ||
| 1882 | + '@vue/server-renderer@3.5.13(vue@3.5.13)': | ||
| 1883 | + dependencies: | ||
| 1884 | + '@vue/compiler-ssr': 3.5.13 | ||
| 1885 | + '@vue/shared': 3.5.13 | ||
| 1886 | + vue: 3.5.13 | ||
| 1887 | + | ||
| 1888 | + '@vue/shared@3.5.13': {} | ||
| 1889 | + | ||
| 1890 | + acorn-jsx@5.3.2(acorn@8.14.1): | ||
| 1891 | + dependencies: | ||
| 1892 | + acorn: 8.14.1 | ||
| 1893 | + | ||
| 1894 | + acorn@8.14.1: {} | ||
| 1895 | + | ||
| 1896 | + ajv@6.12.6: | ||
| 1897 | + dependencies: | ||
| 1898 | + fast-deep-equal: 3.1.3 | ||
| 1899 | + fast-json-stable-stringify: 2.1.0 | ||
| 1900 | + json-schema-traverse: 0.4.1 | ||
| 1901 | + uri-js: 4.4.1 | ||
| 1902 | + | ||
| 1903 | + ansi-regex@5.0.1: {} | ||
| 1904 | + | ||
| 1905 | + ansi-regex@6.1.0: {} | ||
| 1906 | + | ||
| 1907 | + ansi-styles@4.3.0: | ||
| 1908 | + dependencies: | ||
| 1909 | + color-convert: 2.0.1 | ||
| 1910 | + | ||
| 1911 | + ansi-styles@6.2.1: {} | ||
| 1912 | + | ||
| 1913 | + any-promise@1.3.0: {} | ||
| 1914 | + | ||
| 1915 | + anymatch@3.1.3: | ||
| 1916 | + dependencies: | ||
| 1917 | + normalize-path: 3.0.0 | ||
| 1918 | + picomatch: 2.3.1 | ||
| 1919 | + | ||
| 1920 | + arg@5.0.2: {} | ||
| 1921 | + | ||
| 1922 | + argparse@2.0.1: {} | ||
| 1923 | + | ||
| 1924 | + autoprefixer@10.4.21(postcss@8.5.3): | ||
| 1925 | + dependencies: | ||
| 1926 | + browserslist: 4.24.4 | ||
| 1927 | + caniuse-lite: 1.0.30001714 | ||
| 1928 | + fraction.js: 4.3.7 | ||
| 1929 | + normalize-range: 0.1.2 | ||
| 1930 | + picocolors: 1.1.1 | ||
| 1931 | + postcss: 8.5.3 | ||
| 1932 | + postcss-value-parser: 4.2.0 | ||
| 1933 | + | ||
| 1934 | + balanced-match@1.0.2: {} | ||
| 1935 | + | ||
| 1936 | + binary-extensions@2.3.0: {} | ||
| 1937 | + | ||
| 1938 | + boolbase@1.0.0: {} | ||
| 1939 | + | ||
| 1940 | + brace-expansion@1.1.11: | ||
| 1941 | + dependencies: | ||
| 1942 | + balanced-match: 1.0.2 | ||
| 1943 | + concat-map: 0.0.1 | ||
| 1944 | + | ||
| 1945 | + brace-expansion@2.0.1: | ||
| 1946 | + dependencies: | ||
| 1947 | + balanced-match: 1.0.2 | ||
| 1948 | + | ||
| 1949 | + braces@3.0.3: | ||
| 1950 | + dependencies: | ||
| 1951 | + fill-range: 7.1.1 | ||
| 1952 | + | ||
| 1953 | + browserslist@4.24.4: | ||
| 1954 | + dependencies: | ||
| 1955 | + caniuse-lite: 1.0.30001714 | ||
| 1956 | + electron-to-chromium: 1.5.137 | ||
| 1957 | + node-releases: 2.0.19 | ||
| 1958 | + update-browserslist-db: 1.1.3(browserslist@4.24.4) | ||
| 1959 | + | ||
| 1960 | + callsites@3.1.0: {} | ||
| 1961 | + | ||
| 1962 | + camelcase-css@2.0.1: {} | ||
| 1963 | + | ||
| 1964 | + caniuse-lite@1.0.30001714: {} | ||
| 1965 | + | ||
| 1966 | + chalk@4.1.2: | ||
| 1967 | + dependencies: | ||
| 1968 | + ansi-styles: 4.3.0 | ||
| 1969 | + supports-color: 7.2.0 | ||
| 1970 | + | ||
| 1971 | + chokidar@3.6.0: | ||
| 1972 | + dependencies: | ||
| 1973 | + anymatch: 3.1.3 | ||
| 1974 | + braces: 3.0.3 | ||
| 1975 | + glob-parent: 5.1.2 | ||
| 1976 | + is-binary-path: 2.1.0 | ||
| 1977 | + is-glob: 4.0.3 | ||
| 1978 | + normalize-path: 3.0.0 | ||
| 1979 | + readdirp: 3.6.0 | ||
| 1980 | + optionalDependencies: | ||
| 1981 | + fsevents: 2.3.3 | ||
| 1982 | + | ||
| 1983 | + color-convert@2.0.1: | ||
| 1984 | + dependencies: | ||
| 1985 | + color-name: 1.1.4 | ||
| 1986 | + | ||
| 1987 | + color-name@1.1.4: {} | ||
| 1988 | + | ||
| 1989 | + commander@4.1.1: {} | ||
| 1990 | + | ||
| 1991 | + concat-map@0.0.1: {} | ||
| 1992 | + | ||
| 1993 | + convert-source-map@2.0.0: {} | ||
| 1994 | + | ||
| 1995 | + cross-spawn@7.0.6: | ||
| 1996 | + dependencies: | ||
| 1997 | + path-key: 3.1.1 | ||
| 1998 | + shebang-command: 2.0.0 | ||
| 1999 | + which: 2.0.2 | ||
| 2000 | + | ||
| 2001 | + cssesc@3.0.0: {} | ||
| 2002 | + | ||
| 2003 | + csstype@3.1.3: {} | ||
| 2004 | + | ||
| 2005 | + debug@4.4.0: | ||
| 2006 | + dependencies: | ||
| 2007 | + ms: 2.1.3 | ||
| 2008 | + | ||
| 2009 | + deep-is@0.1.4: {} | ||
| 2010 | + | ||
| 2011 | + didyoumean@1.2.2: {} | ||
| 2012 | + | ||
| 2013 | + dlv@1.1.3: {} | ||
| 2014 | + | ||
| 2015 | + eastasianwidth@0.2.0: {} | ||
| 2016 | + | ||
| 2017 | + electron-to-chromium@1.5.137: {} | ||
| 2018 | + | ||
| 2019 | + emoji-regex@8.0.0: {} | ||
| 2020 | + | ||
| 2021 | + emoji-regex@9.2.2: {} | ||
| 2022 | + | ||
| 2023 | + entities@4.5.0: {} | ||
| 2024 | + | ||
| 2025 | + esbuild@0.21.5: | ||
| 2026 | + optionalDependencies: | ||
| 2027 | + '@esbuild/aix-ppc64': 0.21.5 | ||
| 2028 | + '@esbuild/android-arm': 0.21.5 | ||
| 2029 | + '@esbuild/android-arm64': 0.21.5 | ||
| 2030 | + '@esbuild/android-x64': 0.21.5 | ||
| 2031 | + '@esbuild/darwin-arm64': 0.21.5 | ||
| 2032 | + '@esbuild/darwin-x64': 0.21.5 | ||
| 2033 | + '@esbuild/freebsd-arm64': 0.21.5 | ||
| 2034 | + '@esbuild/freebsd-x64': 0.21.5 | ||
| 2035 | + '@esbuild/linux-arm': 0.21.5 | ||
| 2036 | + '@esbuild/linux-arm64': 0.21.5 | ||
| 2037 | + '@esbuild/linux-ia32': 0.21.5 | ||
| 2038 | + '@esbuild/linux-loong64': 0.21.5 | ||
| 2039 | + '@esbuild/linux-mips64el': 0.21.5 | ||
| 2040 | + '@esbuild/linux-ppc64': 0.21.5 | ||
| 2041 | + '@esbuild/linux-riscv64': 0.21.5 | ||
| 2042 | + '@esbuild/linux-s390x': 0.21.5 | ||
| 2043 | + '@esbuild/linux-x64': 0.21.5 | ||
| 2044 | + '@esbuild/netbsd-x64': 0.21.5 | ||
| 2045 | + '@esbuild/openbsd-x64': 0.21.5 | ||
| 2046 | + '@esbuild/sunos-x64': 0.21.5 | ||
| 2047 | + '@esbuild/win32-arm64': 0.21.5 | ||
| 2048 | + '@esbuild/win32-ia32': 0.21.5 | ||
| 2049 | + '@esbuild/win32-x64': 0.21.5 | ||
| 2050 | + | ||
| 2051 | + escalade@3.2.0: {} | ||
| 2052 | + | ||
| 2053 | + escape-string-regexp@4.0.0: {} | ||
| 2054 | + | ||
| 2055 | + eslint-plugin-vue@9.33.0(eslint@9.24.0(jiti@1.21.7)): | ||
| 2056 | + dependencies: | ||
| 2057 | + '@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0(jiti@1.21.7)) | ||
| 2058 | + eslint: 9.24.0(jiti@1.21.7) | ||
| 2059 | + globals: 13.24.0 | ||
| 2060 | + natural-compare: 1.4.0 | ||
| 2061 | + nth-check: 2.1.1 | ||
| 2062 | + postcss-selector-parser: 6.1.2 | ||
| 2063 | + semver: 7.7.1 | ||
| 2064 | + vue-eslint-parser: 9.4.3(eslint@9.24.0(jiti@1.21.7)) | ||
| 2065 | + xml-name-validator: 4.0.0 | ||
| 2066 | + transitivePeerDependencies: | ||
| 2067 | + - supports-color | ||
| 2068 | + | ||
| 2069 | + eslint-scope@7.2.2: | ||
| 2070 | + dependencies: | ||
| 2071 | + esrecurse: 4.3.0 | ||
| 2072 | + estraverse: 5.3.0 | ||
| 2073 | + | ||
| 2074 | + eslint-scope@8.3.0: | ||
| 2075 | + dependencies: | ||
| 2076 | + esrecurse: 4.3.0 | ||
| 2077 | + estraverse: 5.3.0 | ||
| 2078 | + | ||
| 2079 | + eslint-visitor-keys@3.4.3: {} | ||
| 2080 | + | ||
| 2081 | + eslint-visitor-keys@4.2.0: {} | ||
| 2082 | + | ||
| 2083 | + eslint@9.24.0(jiti@1.21.7): | ||
| 2084 | + dependencies: | ||
| 2085 | + '@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0(jiti@1.21.7)) | ||
| 2086 | + '@eslint-community/regexpp': 4.12.1 | ||
| 2087 | + '@eslint/config-array': 0.20.0 | ||
| 2088 | + '@eslint/config-helpers': 0.2.1 | ||
| 2089 | + '@eslint/core': 0.12.0 | ||
| 2090 | + '@eslint/eslintrc': 3.3.1 | ||
| 2091 | + '@eslint/js': 9.24.0 | ||
| 2092 | + '@eslint/plugin-kit': 0.2.8 | ||
| 2093 | + '@humanfs/node': 0.16.6 | ||
| 2094 | + '@humanwhocodes/module-importer': 1.0.1 | ||
| 2095 | + '@humanwhocodes/retry': 0.4.2 | ||
| 2096 | + '@types/estree': 1.0.7 | ||
| 2097 | + '@types/json-schema': 7.0.15 | ||
| 2098 | + ajv: 6.12.6 | ||
| 2099 | + chalk: 4.1.2 | ||
| 2100 | + cross-spawn: 7.0.6 | ||
| 2101 | + debug: 4.4.0 | ||
| 2102 | + escape-string-regexp: 4.0.0 | ||
| 2103 | + eslint-scope: 8.3.0 | ||
| 2104 | + eslint-visitor-keys: 4.2.0 | ||
| 2105 | + espree: 10.3.0 | ||
| 2106 | + esquery: 1.6.0 | ||
| 2107 | + esutils: 2.0.3 | ||
| 2108 | + fast-deep-equal: 3.1.3 | ||
| 2109 | + file-entry-cache: 8.0.0 | ||
| 2110 | + find-up: 5.0.0 | ||
| 2111 | + glob-parent: 6.0.2 | ||
| 2112 | + ignore: 5.3.2 | ||
| 2113 | + imurmurhash: 0.1.4 | ||
| 2114 | + is-glob: 4.0.3 | ||
| 2115 | + json-stable-stringify-without-jsonify: 1.0.1 | ||
| 2116 | + lodash.merge: 4.6.2 | ||
| 2117 | + minimatch: 3.1.2 | ||
| 2118 | + natural-compare: 1.4.0 | ||
| 2119 | + optionator: 0.9.4 | ||
| 2120 | + optionalDependencies: | ||
| 2121 | + jiti: 1.21.7 | ||
| 2122 | + transitivePeerDependencies: | ||
| 2123 | + - supports-color | ||
| 2124 | + | ||
| 2125 | + espree@10.3.0: | ||
| 2126 | + dependencies: | ||
| 2127 | + acorn: 8.14.1 | ||
| 2128 | + acorn-jsx: 5.3.2(acorn@8.14.1) | ||
| 2129 | + eslint-visitor-keys: 4.2.0 | ||
| 2130 | + | ||
| 2131 | + espree@9.6.1: | ||
| 2132 | + dependencies: | ||
| 2133 | + acorn: 8.14.1 | ||
| 2134 | + acorn-jsx: 5.3.2(acorn@8.14.1) | ||
| 2135 | + eslint-visitor-keys: 3.4.3 | ||
| 2136 | + | ||
| 2137 | + esquery@1.6.0: | ||
| 2138 | + dependencies: | ||
| 2139 | + estraverse: 5.3.0 | ||
| 2140 | + | ||
| 2141 | + esrecurse@4.3.0: | ||
| 2142 | + dependencies: | ||
| 2143 | + estraverse: 5.3.0 | ||
| 2144 | + | ||
| 2145 | + estraverse@5.3.0: {} | ||
| 2146 | + | ||
| 2147 | + estree-walker@2.0.2: {} | ||
| 2148 | + | ||
| 2149 | + esutils@2.0.3: {} | ||
| 2150 | + | ||
| 2151 | + fast-deep-equal@3.1.3: {} | ||
| 2152 | + | ||
| 2153 | + fast-glob@3.3.3: | ||
| 2154 | + dependencies: | ||
| 2155 | + '@nodelib/fs.stat': 2.0.5 | ||
| 2156 | + '@nodelib/fs.walk': 1.2.8 | ||
| 2157 | + glob-parent: 5.1.2 | ||
| 2158 | + merge2: 1.4.1 | ||
| 2159 | + micromatch: 4.0.8 | ||
| 2160 | + | ||
| 2161 | + fast-json-stable-stringify@2.1.0: {} | ||
| 2162 | + | ||
| 2163 | + fast-levenshtein@2.0.6: {} | ||
| 2164 | + | ||
| 2165 | + fastq@1.19.1: | ||
| 2166 | + dependencies: | ||
| 2167 | + reusify: 1.1.0 | ||
| 2168 | + | ||
| 2169 | + file-entry-cache@8.0.0: | ||
| 2170 | + dependencies: | ||
| 2171 | + flat-cache: 4.0.1 | ||
| 2172 | + | ||
| 2173 | + fill-range@7.1.1: | ||
| 2174 | + dependencies: | ||
| 2175 | + to-regex-range: 5.0.1 | ||
| 2176 | + | ||
| 2177 | + find-up@5.0.0: | ||
| 2178 | + dependencies: | ||
| 2179 | + locate-path: 6.0.0 | ||
| 2180 | + path-exists: 4.0.0 | ||
| 2181 | + | ||
| 2182 | + flat-cache@4.0.1: | ||
| 2183 | + dependencies: | ||
| 2184 | + flatted: 3.3.3 | ||
| 2185 | + keyv: 4.5.4 | ||
| 2186 | + | ||
| 2187 | + flatted@3.3.3: {} | ||
| 2188 | + | ||
| 2189 | + foreground-child@3.3.1: | ||
| 2190 | + dependencies: | ||
| 2191 | + cross-spawn: 7.0.6 | ||
| 2192 | + signal-exit: 4.1.0 | ||
| 2193 | + | ||
| 2194 | + fraction.js@4.3.7: {} | ||
| 2195 | + | ||
| 2196 | + fsevents@2.3.3: | ||
| 2197 | + optional: true | ||
| 2198 | + | ||
| 2199 | + function-bind@1.1.2: {} | ||
| 2200 | + | ||
| 2201 | + gensync@1.0.0-beta.2: {} | ||
| 2202 | + | ||
| 2203 | + glob-parent@5.1.2: | ||
| 2204 | + dependencies: | ||
| 2205 | + is-glob: 4.0.3 | ||
| 2206 | + | ||
| 2207 | + glob-parent@6.0.2: | ||
| 2208 | + dependencies: | ||
| 2209 | + is-glob: 4.0.3 | ||
| 2210 | + | ||
| 2211 | + glob@10.4.5: | ||
| 2212 | + dependencies: | ||
| 2213 | + foreground-child: 3.3.1 | ||
| 2214 | + jackspeak: 3.4.3 | ||
| 2215 | + minimatch: 9.0.5 | ||
| 2216 | + minipass: 7.1.2 | ||
| 2217 | + package-json-from-dist: 1.0.1 | ||
| 2218 | + path-scurry: 1.11.1 | ||
| 2219 | + | ||
| 2220 | + globals@11.12.0: {} | ||
| 2221 | + | ||
| 2222 | + globals@13.24.0: | ||
| 2223 | + dependencies: | ||
| 2224 | + type-fest: 0.20.2 | ||
| 2225 | + | ||
| 2226 | + globals@14.0.0: {} | ||
| 2227 | + | ||
| 2228 | + has-flag@4.0.0: {} | ||
| 2229 | + | ||
| 2230 | + hasown@2.0.2: | ||
| 2231 | + dependencies: | ||
| 2232 | + function-bind: 1.1.2 | ||
| 2233 | + | ||
| 2234 | + ignore@5.3.2: {} | ||
| 2235 | + | ||
| 2236 | + import-fresh@3.3.1: | ||
| 2237 | + dependencies: | ||
| 2238 | + parent-module: 1.0.1 | ||
| 2239 | + resolve-from: 4.0.0 | ||
| 2240 | + | ||
| 2241 | + imurmurhash@0.1.4: {} | ||
| 2242 | + | ||
| 2243 | + is-binary-path@2.1.0: | ||
| 2244 | + dependencies: | ||
| 2245 | + binary-extensions: 2.3.0 | ||
| 2246 | + | ||
| 2247 | + is-core-module@2.16.1: | ||
| 2248 | + dependencies: | ||
| 2249 | + hasown: 2.0.2 | ||
| 2250 | + | ||
| 2251 | + is-extglob@2.1.1: {} | ||
| 2252 | + | ||
| 2253 | + is-fullwidth-code-point@3.0.0: {} | ||
| 2254 | + | ||
| 2255 | + is-glob@4.0.3: | ||
| 2256 | + dependencies: | ||
| 2257 | + is-extglob: 2.1.1 | ||
| 2258 | + | ||
| 2259 | + is-number@7.0.0: {} | ||
| 2260 | + | ||
| 2261 | + isexe@2.0.0: {} | ||
| 2262 | + | ||
| 2263 | + jackspeak@3.4.3: | ||
| 2264 | + dependencies: | ||
| 2265 | + '@isaacs/cliui': 8.0.2 | ||
| 2266 | + optionalDependencies: | ||
| 2267 | + '@pkgjs/parseargs': 0.11.0 | ||
| 2268 | + | ||
| 2269 | + jiti@1.21.7: {} | ||
| 2270 | + | ||
| 2271 | + js-tokens@4.0.0: {} | ||
| 2272 | + | ||
| 2273 | + js-yaml@4.1.0: | ||
| 2274 | + dependencies: | ||
| 2275 | + argparse: 2.0.1 | ||
| 2276 | + | ||
| 2277 | + jsesc@3.1.0: {} | ||
| 2278 | + | ||
| 2279 | + json-buffer@3.0.1: {} | ||
| 2280 | + | ||
| 2281 | + json-schema-traverse@0.4.1: {} | ||
| 2282 | + | ||
| 2283 | + json-stable-stringify-without-jsonify@1.0.1: {} | ||
| 2284 | + | ||
| 2285 | + json5@2.2.3: {} | ||
| 2286 | + | ||
| 2287 | + keyv@4.5.4: | ||
| 2288 | + dependencies: | ||
| 2289 | + json-buffer: 3.0.1 | ||
| 2290 | + | ||
| 2291 | + levn@0.4.1: | ||
| 2292 | + dependencies: | ||
| 2293 | + prelude-ls: 1.2.1 | ||
| 2294 | + type-check: 0.4.0 | ||
| 2295 | + | ||
| 2296 | + lilconfig@3.1.3: {} | ||
| 2297 | + | ||
| 2298 | + lines-and-columns@1.2.4: {} | ||
| 2299 | + | ||
| 2300 | + locate-path@6.0.0: | ||
| 2301 | + dependencies: | ||
| 2302 | + p-locate: 5.0.0 | ||
| 2303 | + | ||
| 2304 | + lodash.merge@4.6.2: {} | ||
| 2305 | + | ||
| 2306 | + lodash@4.17.21: {} | ||
| 2307 | + | ||
| 2308 | + lru-cache@10.4.3: {} | ||
| 2309 | + | ||
| 2310 | + lru-cache@5.1.1: | ||
| 2311 | + dependencies: | ||
| 2312 | + yallist: 3.1.1 | ||
| 2313 | + | ||
| 2314 | + magic-string@0.30.17: | ||
| 2315 | + dependencies: | ||
| 2316 | + '@jridgewell/sourcemap-codec': 1.5.0 | ||
| 2317 | + | ||
| 2318 | + merge2@1.4.1: {} | ||
| 2319 | + | ||
| 2320 | + micromatch@4.0.8: | ||
| 2321 | + dependencies: | ||
| 2322 | + braces: 3.0.3 | ||
| 2323 | + picomatch: 2.3.1 | ||
| 2324 | + | ||
| 2325 | + minimatch@3.1.2: | ||
| 2326 | + dependencies: | ||
| 2327 | + brace-expansion: 1.1.11 | ||
| 2328 | + | ||
| 2329 | + minimatch@9.0.5: | ||
| 2330 | + dependencies: | ||
| 2331 | + brace-expansion: 2.0.1 | ||
| 2332 | + | ||
| 2333 | + minipass@7.1.2: {} | ||
| 2334 | + | ||
| 2335 | + ms@2.1.3: {} | ||
| 2336 | + | ||
| 2337 | + mz@2.7.0: | ||
| 2338 | + dependencies: | ||
| 2339 | + any-promise: 1.3.0 | ||
| 2340 | + object-assign: 4.1.1 | ||
| 2341 | + thenify-all: 1.6.0 | ||
| 2342 | + | ||
| 2343 | + nanoid@3.3.11: {} | ||
| 2344 | + | ||
| 2345 | + natural-compare@1.4.0: {} | ||
| 2346 | + | ||
| 2347 | + node-releases@2.0.19: {} | ||
| 2348 | + | ||
| 2349 | + normalize-path@3.0.0: {} | ||
| 2350 | + | ||
| 2351 | + normalize-range@0.1.2: {} | ||
| 2352 | + | ||
| 2353 | + nth-check@2.1.1: | ||
| 2354 | + dependencies: | ||
| 2355 | + boolbase: 1.0.0 | ||
| 2356 | + | ||
| 2357 | + object-assign@4.1.1: {} | ||
| 2358 | + | ||
| 2359 | + object-hash@3.0.0: {} | ||
| 2360 | + | ||
| 2361 | + optionator@0.9.4: | ||
| 2362 | + dependencies: | ||
| 2363 | + deep-is: 0.1.4 | ||
| 2364 | + fast-levenshtein: 2.0.6 | ||
| 2365 | + levn: 0.4.1 | ||
| 2366 | + prelude-ls: 1.2.1 | ||
| 2367 | + type-check: 0.4.0 | ||
| 2368 | + word-wrap: 1.2.5 | ||
| 2369 | + | ||
| 2370 | + p-limit@3.1.0: | ||
| 2371 | + dependencies: | ||
| 2372 | + yocto-queue: 0.1.0 | ||
| 2373 | + | ||
| 2374 | + p-locate@5.0.0: | ||
| 2375 | + dependencies: | ||
| 2376 | + p-limit: 3.1.0 | ||
| 2377 | + | ||
| 2378 | + package-json-from-dist@1.0.1: {} | ||
| 2379 | + | ||
| 2380 | + parent-module@1.0.1: | ||
| 2381 | + dependencies: | ||
| 2382 | + callsites: 3.1.0 | ||
| 2383 | + | ||
| 2384 | + path-exists@4.0.0: {} | ||
| 2385 | + | ||
| 2386 | + path-key@3.1.1: {} | ||
| 2387 | + | ||
| 2388 | + path-parse@1.0.7: {} | ||
| 2389 | + | ||
| 2390 | + path-scurry@1.11.1: | ||
| 2391 | + dependencies: | ||
| 2392 | + lru-cache: 10.4.3 | ||
| 2393 | + minipass: 7.1.2 | ||
| 2394 | + | ||
| 2395 | + picocolors@1.1.1: {} | ||
| 2396 | + | ||
| 2397 | + picomatch@2.3.1: {} | ||
| 2398 | + | ||
| 2399 | + pify@2.3.0: {} | ||
| 2400 | + | ||
| 2401 | + pinia@2.3.1(vue@3.5.13): | ||
| 2402 | + dependencies: | ||
| 2403 | + '@vue/devtools-api': 6.6.4 | ||
| 2404 | + vue: 3.5.13 | ||
| 2405 | + vue-demi: 0.14.10(vue@3.5.13) | ||
| 2406 | + transitivePeerDependencies: | ||
| 2407 | + - '@vue/composition-api' | ||
| 2408 | + | ||
| 2409 | + pirates@4.0.7: {} | ||
| 2410 | + | ||
| 2411 | + postcss-import@15.1.0(postcss@8.5.3): | ||
| 2412 | + dependencies: | ||
| 2413 | + postcss: 8.5.3 | ||
| 2414 | + postcss-value-parser: 4.2.0 | ||
| 2415 | + read-cache: 1.0.0 | ||
| 2416 | + resolve: 1.22.10 | ||
| 2417 | + | ||
| 2418 | + postcss-js@4.0.1(postcss@8.5.3): | ||
| 2419 | + dependencies: | ||
| 2420 | + camelcase-css: 2.0.1 | ||
| 2421 | + postcss: 8.5.3 | ||
| 2422 | + | ||
| 2423 | + postcss-load-config@4.0.2(postcss@8.5.3): | ||
| 2424 | + dependencies: | ||
| 2425 | + lilconfig: 3.1.3 | ||
| 2426 | + yaml: 2.7.1 | ||
| 2427 | + optionalDependencies: | ||
| 2428 | + postcss: 8.5.3 | ||
| 2429 | + | ||
| 2430 | + postcss-nested@6.2.0(postcss@8.5.3): | ||
| 2431 | + dependencies: | ||
| 2432 | + postcss: 8.5.3 | ||
| 2433 | + postcss-selector-parser: 6.1.2 | ||
| 2434 | + | ||
| 2435 | + postcss-selector-parser@6.1.2: | ||
| 2436 | + dependencies: | ||
| 2437 | + cssesc: 3.0.0 | ||
| 2438 | + util-deprecate: 1.0.2 | ||
| 2439 | + | ||
| 2440 | + postcss-value-parser@4.2.0: {} | ||
| 2441 | + | ||
| 2442 | + postcss@8.5.3: | ||
| 2443 | + dependencies: | ||
| 2444 | + nanoid: 3.3.11 | ||
| 2445 | + picocolors: 1.1.1 | ||
| 2446 | + source-map-js: 1.2.1 | ||
| 2447 | + | ||
| 2448 | + prelude-ls@1.2.1: {} | ||
| 2449 | + | ||
| 2450 | + punycode@2.3.1: {} | ||
| 2451 | + | ||
| 2452 | + queue-microtask@1.2.3: {} | ||
| 2453 | + | ||
| 2454 | + read-cache@1.0.0: | ||
| 2455 | + dependencies: | ||
| 2456 | + pify: 2.3.0 | ||
| 2457 | + | ||
| 2458 | + readdirp@3.6.0: | ||
| 2459 | + dependencies: | ||
| 2460 | + picomatch: 2.3.1 | ||
| 2461 | + | ||
| 2462 | + resolve-from@4.0.0: {} | ||
| 2463 | + | ||
| 2464 | + resolve@1.22.10: | ||
| 2465 | + dependencies: | ||
| 2466 | + is-core-module: 2.16.1 | ||
| 2467 | + path-parse: 1.0.7 | ||
| 2468 | + supports-preserve-symlinks-flag: 1.0.0 | ||
| 2469 | + | ||
| 2470 | + reusify@1.1.0: {} | ||
| 2471 | + | ||
| 2472 | + rollup@4.40.0: | ||
| 2473 | + dependencies: | ||
| 2474 | + '@types/estree': 1.0.7 | ||
| 2475 | + optionalDependencies: | ||
| 2476 | + '@rollup/rollup-android-arm-eabi': 4.40.0 | ||
| 2477 | + '@rollup/rollup-android-arm64': 4.40.0 | ||
| 2478 | + '@rollup/rollup-darwin-arm64': 4.40.0 | ||
| 2479 | + '@rollup/rollup-darwin-x64': 4.40.0 | ||
| 2480 | + '@rollup/rollup-freebsd-arm64': 4.40.0 | ||
| 2481 | + '@rollup/rollup-freebsd-x64': 4.40.0 | ||
| 2482 | + '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 | ||
| 2483 | + '@rollup/rollup-linux-arm-musleabihf': 4.40.0 | ||
| 2484 | + '@rollup/rollup-linux-arm64-gnu': 4.40.0 | ||
| 2485 | + '@rollup/rollup-linux-arm64-musl': 4.40.0 | ||
| 2486 | + '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 | ||
| 2487 | + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 | ||
| 2488 | + '@rollup/rollup-linux-riscv64-gnu': 4.40.0 | ||
| 2489 | + '@rollup/rollup-linux-riscv64-musl': 4.40.0 | ||
| 2490 | + '@rollup/rollup-linux-s390x-gnu': 4.40.0 | ||
| 2491 | + '@rollup/rollup-linux-x64-gnu': 4.40.0 | ||
| 2492 | + '@rollup/rollup-linux-x64-musl': 4.40.0 | ||
| 2493 | + '@rollup/rollup-win32-arm64-msvc': 4.40.0 | ||
| 2494 | + '@rollup/rollup-win32-ia32-msvc': 4.40.0 | ||
| 2495 | + '@rollup/rollup-win32-x64-msvc': 4.40.0 | ||
| 2496 | + fsevents: 2.3.3 | ||
| 2497 | + | ||
| 2498 | + run-parallel@1.2.0: | ||
| 2499 | + dependencies: | ||
| 2500 | + queue-microtask: 1.2.3 | ||
| 2501 | + | ||
| 2502 | + semver@6.3.1: {} | ||
| 2503 | + | ||
| 2504 | + semver@7.7.1: {} | ||
| 2505 | + | ||
| 2506 | + shebang-command@2.0.0: | ||
| 2507 | + dependencies: | ||
| 2508 | + shebang-regex: 3.0.0 | ||
| 2509 | + | ||
| 2510 | + shebang-regex@3.0.0: {} | ||
| 2511 | + | ||
| 2512 | + signal-exit@4.1.0: {} | ||
| 2513 | + | ||
| 2514 | + source-map-js@1.2.1: {} | ||
| 2515 | + | ||
| 2516 | + string-width@4.2.3: | ||
| 2517 | + dependencies: | ||
| 2518 | + emoji-regex: 8.0.0 | ||
| 2519 | + is-fullwidth-code-point: 3.0.0 | ||
| 2520 | + strip-ansi: 6.0.1 | ||
| 2521 | + | ||
| 2522 | + string-width@5.1.2: | ||
| 2523 | + dependencies: | ||
| 2524 | + eastasianwidth: 0.2.0 | ||
| 2525 | + emoji-regex: 9.2.2 | ||
| 2526 | + strip-ansi: 7.1.0 | ||
| 2527 | + | ||
| 2528 | + strip-ansi@6.0.1: | ||
| 2529 | + dependencies: | ||
| 2530 | + ansi-regex: 5.0.1 | ||
| 2531 | + | ||
| 2532 | + strip-ansi@7.1.0: | ||
| 2533 | + dependencies: | ||
| 2534 | + ansi-regex: 6.1.0 | ||
| 2535 | + | ||
| 2536 | + strip-json-comments@3.1.1: {} | ||
| 2537 | + | ||
| 2538 | + sucrase@3.35.0: | ||
| 2539 | + dependencies: | ||
| 2540 | + '@jridgewell/gen-mapping': 0.3.8 | ||
| 2541 | + commander: 4.1.1 | ||
| 2542 | + glob: 10.4.5 | ||
| 2543 | + lines-and-columns: 1.2.4 | ||
| 2544 | + mz: 2.7.0 | ||
| 2545 | + pirates: 4.0.7 | ||
| 2546 | + ts-interface-checker: 0.1.13 | ||
| 2547 | + | ||
| 2548 | + supports-color@7.2.0: | ||
| 2549 | + dependencies: | ||
| 2550 | + has-flag: 4.0.0 | ||
| 2551 | + | ||
| 2552 | + supports-preserve-symlinks-flag@1.0.0: {} | ||
| 2553 | + | ||
| 2554 | + tailwindcss@3.4.17: | ||
| 2555 | + dependencies: | ||
| 2556 | + '@alloc/quick-lru': 5.2.0 | ||
| 2557 | + arg: 5.0.2 | ||
| 2558 | + chokidar: 3.6.0 | ||
| 2559 | + didyoumean: 1.2.2 | ||
| 2560 | + dlv: 1.1.3 | ||
| 2561 | + fast-glob: 3.3.3 | ||
| 2562 | + glob-parent: 6.0.2 | ||
| 2563 | + is-glob: 4.0.3 | ||
| 2564 | + jiti: 1.21.7 | ||
| 2565 | + lilconfig: 3.1.3 | ||
| 2566 | + micromatch: 4.0.8 | ||
| 2567 | + normalize-path: 3.0.0 | ||
| 2568 | + object-hash: 3.0.0 | ||
| 2569 | + picocolors: 1.1.1 | ||
| 2570 | + postcss: 8.5.3 | ||
| 2571 | + postcss-import: 15.1.0(postcss@8.5.3) | ||
| 2572 | + postcss-js: 4.0.1(postcss@8.5.3) | ||
| 2573 | + postcss-load-config: 4.0.2(postcss@8.5.3) | ||
| 2574 | + postcss-nested: 6.2.0(postcss@8.5.3) | ||
| 2575 | + postcss-selector-parser: 6.1.2 | ||
| 2576 | + resolve: 1.22.10 | ||
| 2577 | + sucrase: 3.35.0 | ||
| 2578 | + transitivePeerDependencies: | ||
| 2579 | + - ts-node | ||
| 2580 | + | ||
| 2581 | + thenify-all@1.6.0: | ||
| 2582 | + dependencies: | ||
| 2583 | + thenify: 3.3.1 | ||
| 2584 | + | ||
| 2585 | + thenify@3.3.1: | ||
| 2586 | + dependencies: | ||
| 2587 | + any-promise: 1.3.0 | ||
| 2588 | + | ||
| 2589 | + to-regex-range@5.0.1: | ||
| 2590 | + dependencies: | ||
| 2591 | + is-number: 7.0.0 | ||
| 2592 | + | ||
| 2593 | + ts-interface-checker@0.1.13: {} | ||
| 2594 | + | ||
| 2595 | + type-check@0.4.0: | ||
| 2596 | + dependencies: | ||
| 2597 | + prelude-ls: 1.2.1 | ||
| 2598 | + | ||
| 2599 | + type-fest@0.20.2: {} | ||
| 2600 | + | ||
| 2601 | + update-browserslist-db@1.1.3(browserslist@4.24.4): | ||
| 2602 | + dependencies: | ||
| 2603 | + browserslist: 4.24.4 | ||
| 2604 | + escalade: 3.2.0 | ||
| 2605 | + picocolors: 1.1.1 | ||
| 2606 | + | ||
| 2607 | + uri-js@4.4.1: | ||
| 2608 | + dependencies: | ||
| 2609 | + punycode: 2.3.1 | ||
| 2610 | + | ||
| 2611 | + util-deprecate@1.0.2: {} | ||
| 2612 | + | ||
| 2613 | + vite@5.4.18: | ||
| 2614 | + dependencies: | ||
| 2615 | + esbuild: 0.21.5 | ||
| 2616 | + postcss: 8.5.3 | ||
| 2617 | + rollup: 4.40.0 | ||
| 2618 | + optionalDependencies: | ||
| 2619 | + fsevents: 2.3.3 | ||
| 2620 | + | ||
| 2621 | + vue-demi@0.14.10(vue@3.5.13): | ||
| 2622 | + dependencies: | ||
| 2623 | + vue: 3.5.13 | ||
| 2624 | + | ||
| 2625 | + vue-eslint-parser@9.4.3(eslint@9.24.0(jiti@1.21.7)): | ||
| 2626 | + dependencies: | ||
| 2627 | + debug: 4.4.0 | ||
| 2628 | + eslint: 9.24.0(jiti@1.21.7) | ||
| 2629 | + eslint-scope: 7.2.2 | ||
| 2630 | + eslint-visitor-keys: 3.4.3 | ||
| 2631 | + espree: 9.6.1 | ||
| 2632 | + esquery: 1.6.0 | ||
| 2633 | + lodash: 4.17.21 | ||
| 2634 | + semver: 7.7.1 | ||
| 2635 | + transitivePeerDependencies: | ||
| 2636 | + - supports-color | ||
| 2637 | + | ||
| 2638 | + vue-router@4.5.0(vue@3.5.13): | ||
| 2639 | + dependencies: | ||
| 2640 | + '@vue/devtools-api': 6.6.4 | ||
| 2641 | + vue: 3.5.13 | ||
| 2642 | + | ||
| 2643 | + vue@3.5.13: | ||
| 2644 | + dependencies: | ||
| 2645 | + '@vue/compiler-dom': 3.5.13 | ||
| 2646 | + '@vue/compiler-sfc': 3.5.13 | ||
| 2647 | + '@vue/runtime-dom': 3.5.13 | ||
| 2648 | + '@vue/server-renderer': 3.5.13(vue@3.5.13) | ||
| 2649 | + '@vue/shared': 3.5.13 | ||
| 2650 | + | ||
| 2651 | + which@2.0.2: | ||
| 2652 | + dependencies: | ||
| 2653 | + isexe: 2.0.0 | ||
| 2654 | + | ||
| 2655 | + word-wrap@1.2.5: {} | ||
| 2656 | + | ||
| 2657 | + wrap-ansi@7.0.0: | ||
| 2658 | + dependencies: | ||
| 2659 | + ansi-styles: 4.3.0 | ||
| 2660 | + string-width: 4.2.3 | ||
| 2661 | + strip-ansi: 6.0.1 | ||
| 2662 | + | ||
| 2663 | + wrap-ansi@8.1.0: | ||
| 2664 | + dependencies: | ||
| 2665 | + ansi-styles: 6.2.1 | ||
| 2666 | + string-width: 5.1.2 | ||
| 2667 | + strip-ansi: 7.1.0 | ||
| 2668 | + | ||
| 2669 | + xml-name-validator@4.0.0: {} | ||
| 2670 | + | ||
| 2671 | + yallist@3.1.1: {} | ||
| 2672 | + | ||
| 2673 | + yaml@2.7.1: {} | ||
| 2674 | + | ||
| 2675 | + yocto-queue@0.1.0: {} |
postcss.config.js
0 → 100644
public/assets/images/.gitkeep
0 → 100644
File mode changed
public/assets/images/2RRq1BHPq4E.jpg
0 → 100644
5.47 MB
public/assets/images/CXYPfveiuis.jpg
0 → 100644
2.38 MB
public/assets/images/D5nh6mCW52c.jpg
0 → 100644
1.77 MB
public/assets/images/IHGcwEEhZgo.jpg
0 → 100644
This file is too large to display.
public/assets/images/LEVRaos2Ero.jpg
0 → 100644
2.84 MB
public/assets/images/XqXJJhK-c08.jpg
0 → 100644
890 KB
public/assets/images/activity_3_online.jpg
0 → 100644
2.38 MB
779 KB
public/assets/images/eMJc4eV0rI0.jpg
0 → 100644
2.61 MB
public/assets/images/g827ZOCwt30.jpg
0 → 100644
2.34 MB
public/assets/images/hPKTYwJ4FUo.jpg
0 → 100644
5.31 MB
public/assets/images/k2Kcwkandwg.jpg
0 → 100644
2.39 MB
public/assets/images/t2Sai-AqIpI.jpg
0 → 100644
779 KB
779 KB
public/assets/images/xY55bL5mZAM.jpg
0 → 100644
1.17 MB
public/data/activities.json
0 → 100644
| 1 | +[ | ||
| 2 | + { | ||
| 3 | + "id": "A0001", | ||
| 4 | + "title": "从《了不起的盖茨比》看世界变迁", | ||
| 5 | + "organizer_id": "O0006", | ||
| 6 | + "organizer_name": "百草园读书会", | ||
| 7 | + "description": "与志同道合的读者一起,深入解析《了不起的盖茨比》。\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n活动全程录制,无法准时参加的书友可在后续获取回放。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 8 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_1_online", | ||
| 9 | + "start_time": "2025-04-02 06:13:57", | ||
| 10 | + "end_time": "2025-04-02 07:13:57", | ||
| 11 | + "registration_start": "2025-03-25 05:13:57", | ||
| 12 | + "registration_end": "2025-04-02 05:13:57", | ||
| 13 | + "max_participants": 36, | ||
| 14 | + "participant_count": 30, | ||
| 15 | + "activity_type": "online", | ||
| 16 | + "location": null, | ||
| 17 | + "online_link": "飞书线上会议,会议ID将提前发送", | ||
| 18 | + "is_published": true, | ||
| 19 | + "is_public": true, | ||
| 20 | + "tags": [ | ||
| 21 | + "音乐" | ||
| 22 | + ], | ||
| 23 | + "view_count": 515, | ||
| 24 | + "volunteer_positions": [ | ||
| 25 | + "摄影记录", | ||
| 26 | + "签到助手" | ||
| 27 | + ], | ||
| 28 | + "created_at": "2025-03-23 05:13:57", | ||
| 29 | + "updated_at": "2025-03-25 21:13:57", | ||
| 30 | + "state": "past" | ||
| 31 | + }, | ||
| 32 | + { | ||
| 33 | + "id": "A0002", | ||
| 34 | + "title": "与作者对话:《了不起的盖茨比》背后的故事", | ||
| 35 | + "organizer_id": "O0003", | ||
| 36 | + "organizer_name": "知行合一读书社", | ||
| 37 | + "description": "想要探索《了不起的盖茨比》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 38 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_2_offline", | ||
| 39 | + "start_time": "2025-03-24 06:13:57", | ||
| 40 | + "end_time": "2025-03-24 07:13:57", | ||
| 41 | + "registration_start": "2025-03-12 01:13:57", | ||
| 42 | + "registration_end": "2025-03-24 01:13:57", | ||
| 43 | + "max_participants": 56, | ||
| 44 | + "participant_count": 50, | ||
| 45 | + "activity_type": "offline", | ||
| 46 | + "location": { | ||
| 47 | + "name": "深蓝咖啡馆", | ||
| 48 | + "address": "深圳市南山区科技园南区科苑路15号", | ||
| 49 | + "city": "深圳" | ||
| 50 | + }, | ||
| 51 | + "online_link": null, | ||
| 52 | + "is_published": true, | ||
| 53 | + "is_public": true, | ||
| 54 | + "tags": [ | ||
| 55 | + "艺术", | ||
| 56 | + "政治" | ||
| 57 | + ], | ||
| 58 | + "view_count": 380, | ||
| 59 | + "volunteer_positions": [ | ||
| 60 | + "设备维护", | ||
| 61 | + "资料分发", | ||
| 62 | + "场地布置", | ||
| 63 | + "讨论主持" | ||
| 64 | + ], | ||
| 65 | + "created_at": "2025-03-11 01:13:57", | ||
| 66 | + "updated_at": "2025-03-12 22:13:57", | ||
| 67 | + "state": "past" | ||
| 68 | + }, | ||
| 69 | + { | ||
| 70 | + "id": "A0003", | ||
| 71 | + "title": "《瓦尔登湖》读书分享会", | ||
| 72 | + "organizer_id": "O0010", | ||
| 73 | + "organizer_name": "青禾读书会", | ||
| 74 | + "description": "本次读书会将围绕《瓦尔登湖》展开深入讨论。\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n活动全程录制,无法准时参加的书友可在后续获取回放。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 75 | + "cover_image": "/assets/images/activity_3_online.jpg", | ||
| 76 | + "start_time": "2025-04-18 07:13:57", | ||
| 77 | + "end_time": "2025-04-18 10:13:57", | ||
| 78 | + "registration_start": "2025-03-25 09:13:57", | ||
| 79 | + "registration_end": "2025-04-17 09:13:57", | ||
| 80 | + "max_participants": 33, | ||
| 81 | + "participant_count": 6, | ||
| 82 | + "activity_type": "online", | ||
| 83 | + "location": null, | ||
| 84 | + "online_link": "腾讯会议线上会议,会议ID将提前发送", | ||
| 85 | + "is_published": true, | ||
| 86 | + "is_public": true, | ||
| 87 | + "tags": [ | ||
| 88 | + "亲子阅读", | ||
| 89 | + "政治" | ||
| 90 | + ], | ||
| 91 | + "view_count": 97, | ||
| 92 | + "volunteer_positions": [ | ||
| 93 | + "活动总结", | ||
| 94 | + "设备维护", | ||
| 95 | + "场地布置", | ||
| 96 | + "直播助理" | ||
| 97 | + ], | ||
| 98 | + "created_at": "2025-03-24 09:13:57", | ||
| 99 | + "updated_at": "2025-03-26 02:13:57", | ||
| 100 | + "state": "upcoming" | ||
| 101 | + }, | ||
| 102 | + { | ||
| 103 | + "id": "A0004", | ||
| 104 | + "title": "从《围城》看世界变迁", | ||
| 105 | + "organizer_id": "O0009", | ||
| 106 | + "organizer_name": "四季阅读空间", | ||
| 107 | + "description": "想要探索《围城》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 108 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_4_offline", | ||
| 109 | + "start_time": "2025-06-22 07:13:57", | ||
| 110 | + "end_time": "2025-06-22 08:13:57", | ||
| 111 | + "registration_start": "2025-06-12 03:13:57", | ||
| 112 | + "registration_end": "2025-06-22 03:13:57", | ||
| 113 | + "max_participants": 60, | ||
| 114 | + "participant_count": 5, | ||
| 115 | + "activity_type": "offline", | ||
| 116 | + "location": { | ||
| 117 | + "name": "大雁塔文化空间", | ||
| 118 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 119 | + "city": "西安" | ||
| 120 | + }, | ||
| 121 | + "online_link": null, | ||
| 122 | + "is_published": true, | ||
| 123 | + "is_public": true, | ||
| 124 | + "tags": [ | ||
| 125 | + "推理" | ||
| 126 | + ], | ||
| 127 | + "view_count": 68, | ||
| 128 | + "volunteer_positions": [ | ||
| 129 | + "设备维护", | ||
| 130 | + "场地布置", | ||
| 131 | + "讨论主持" | ||
| 132 | + ], | ||
| 133 | + "created_at": "2025-06-09 03:13:57", | ||
| 134 | + "updated_at": "2025-06-12 18:13:57", | ||
| 135 | + "state": "upcoming" | ||
| 136 | + }, | ||
| 137 | + { | ||
| 138 | + "id": "A0005", | ||
| 139 | + "title": "青年读书会:共读《月亮与六便士》", | ||
| 140 | + "organizer_id": "O0009", | ||
| 141 | + "organizer_name": "四季阅读空间", | ||
| 142 | + "description": "与志同道合的读者一起,深入解析《月亮与六便士》。\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n活动结束后有半小时自由交流时间,欢迎书友们互相认识。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 143 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_5_offline", | ||
| 144 | + "start_time": "2025-03-31 06:13:57", | ||
| 145 | + "end_time": "2025-03-31 07:13:57", | ||
| 146 | + "registration_start": "2025-03-21 23:13:57", | ||
| 147 | + "registration_end": "2025-03-30 23:13:57", | ||
| 148 | + "max_participants": 67, | ||
| 149 | + "participant_count": 62, | ||
| 150 | + "activity_type": "offline", | ||
| 151 | + "location": { | ||
| 152 | + "name": "大雁塔文化空间", | ||
| 153 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 154 | + "city": "西安" | ||
| 155 | + }, | ||
| 156 | + "online_link": null, | ||
| 157 | + "is_published": true, | ||
| 158 | + "is_public": false, | ||
| 159 | + "tags": [ | ||
| 160 | + "健康生活", | ||
| 161 | + "经济" | ||
| 162 | + ], | ||
| 163 | + "view_count": 963, | ||
| 164 | + "volunteer_positions": [ | ||
| 165 | + "设备维护" | ||
| 166 | + ], | ||
| 167 | + "created_at": "2025-03-18 23:13:57", | ||
| 168 | + "updated_at": "2025-03-22 03:13:57", | ||
| 169 | + "state": "past" | ||
| 170 | + }, | ||
| 171 | + { | ||
| 172 | + "id": "A0006", | ||
| 173 | + "title": "《三体》的艺术赏析", | ||
| 174 | + "organizer_id": "O0008", | ||
| 175 | + "organizer_name": "墨香文化传媒", | ||
| 176 | + "description": "想要探索《三体》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n线上活动无地域限制,请提前调试好设备,确保网络流畅。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 177 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_6_online", | ||
| 178 | + "start_time": "2025-05-18 07:13:57", | ||
| 179 | + "end_time": "2025-05-18 10:13:57", | ||
| 180 | + "registration_start": "2025-05-01 15:13:57", | ||
| 181 | + "registration_end": "2025-05-17 15:13:57", | ||
| 182 | + "max_participants": 61, | ||
| 183 | + "participant_count": 9, | ||
| 184 | + "activity_type": "online", | ||
| 185 | + "location": null, | ||
| 186 | + "online_link": "微信视频线上会议,会议ID将提前发送", | ||
| 187 | + "is_published": true, | ||
| 188 | + "is_public": true, | ||
| 189 | + "tags": [ | ||
| 190 | + "文学" | ||
| 191 | + ], | ||
| 192 | + "view_count": 77, | ||
| 193 | + "volunteer_positions": [ | ||
| 194 | + "秩序维持", | ||
| 195 | + "场地布置", | ||
| 196 | + "直播助理", | ||
| 197 | + "活动总结", | ||
| 198 | + "资料分发" | ||
| 199 | + ], | ||
| 200 | + "created_at": "2025-04-28 15:13:57", | ||
| 201 | + "updated_at": "2025-05-02 09:13:57", | ||
| 202 | + "state": "upcoming" | ||
| 203 | + }, | ||
| 204 | + { | ||
| 205 | + "id": "A0007", | ||
| 206 | + "title": "深度解读《活着》", | ||
| 207 | + "organizer_id": "O0006", | ||
| 208 | + "organizer_name": "百草园读书会", | ||
| 209 | + "description": "与志同道合的读者一起,深入解析《活着》。\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 210 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_7_offline", | ||
| 211 | + "start_time": "2025-04-03 05:13:57", | ||
| 212 | + "end_time": "2025-04-03 07:13:57", | ||
| 213 | + "registration_start": "2025-03-28 17:13:57", | ||
| 214 | + "registration_end": "2025-04-02 17:13:57", | ||
| 215 | + "max_participants": 30, | ||
| 216 | + "participant_count": 28, | ||
| 217 | + "activity_type": "offline", | ||
| 218 | + "location": { | ||
| 219 | + "name": "熊猫书房", | ||
| 220 | + "address": "成都市锦江区红星路三段99号", | ||
| 221 | + "city": "成都" | ||
| 222 | + }, | ||
| 223 | + "online_link": null, | ||
| 224 | + "is_published": true, | ||
| 225 | + "is_public": true, | ||
| 226 | + "tags": [ | ||
| 227 | + "科技", | ||
| 228 | + "经济" | ||
| 229 | + ], | ||
| 230 | + "view_count": 895, | ||
| 231 | + "volunteer_positions": [ | ||
| 232 | + "秩序维持" | ||
| 233 | + ], | ||
| 234 | + "created_at": "2025-03-25 17:13:57", | ||
| 235 | + "updated_at": "2025-03-29 01:13:57", | ||
| 236 | + "state": "past" | ||
| 237 | + }, | ||
| 238 | + { | ||
| 239 | + "id": "A0008", | ||
| 240 | + "title": "《月亮与六便士》的哲学思考", | ||
| 241 | + "organizer_id": "O0001", | ||
| 242 | + "organizer_name": "光合作用文化空间", | ||
| 243 | + "description": "本次读书会将围绕《月亮与六便士》展开深入讨论。\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 244 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_8_offline", | ||
| 245 | + "start_time": "2025-04-16 05:30:57", | ||
| 246 | + "end_time": "2025-04-16 07:30:57", | ||
| 247 | + "registration_start": "2025-04-11 05:30:57", | ||
| 248 | + "registration_end": "2025-04-16 05:30:57", | ||
| 249 | + "max_participants": 38, | ||
| 250 | + "participant_count": 18, | ||
| 251 | + "activity_type": "offline", | ||
| 252 | + "location": { | ||
| 253 | + "name": "紫金读书会", | ||
| 254 | + "address": "南京市鼓楼区中山路99号", | ||
| 255 | + "city": "南京" | ||
| 256 | + }, | ||
| 257 | + "online_link": null, | ||
| 258 | + "is_published": true, | ||
| 259 | + "is_public": true, | ||
| 260 | + "tags": [ | ||
| 261 | + "心灵成长" | ||
| 262 | + ], | ||
| 263 | + "view_count": 207, | ||
| 264 | + "volunteer_positions": [ | ||
| 265 | + "直播助理" | ||
| 266 | + ], | ||
| 267 | + "created_at": "2025-04-10 05:30:57", | ||
| 268 | + "updated_at": "2025-04-12 00:30:57", | ||
| 269 | + "state": "ongoing" | ||
| 270 | + }, | ||
| 271 | + { | ||
| 272 | + "id": "A0009", | ||
| 273 | + "title": "深度解读《瓦尔登湖》", | ||
| 274 | + "organizer_id": "O0001", | ||
| 275 | + "organizer_name": "光合作用文化空间", | ||
| 276 | + "description": "与志同道合的读者一起,深入解析《瓦尔登湖》。\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 277 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_9_offline", | ||
| 278 | + "start_time": "2025-05-30 07:13:57", | ||
| 279 | + "end_time": "2025-05-30 10:13:57", | ||
| 280 | + "registration_start": "2025-05-12 17:13:57", | ||
| 281 | + "registration_end": "2025-05-29 17:13:57", | ||
| 282 | + "max_participants": 52, | ||
| 283 | + "participant_count": 14, | ||
| 284 | + "activity_type": "offline", | ||
| 285 | + "location": { | ||
| 286 | + "name": "紫金读书会", | ||
| 287 | + "address": "南京市鼓楼区中山路99号", | ||
| 288 | + "city": "南京" | ||
| 289 | + }, | ||
| 290 | + "online_link": null, | ||
| 291 | + "is_published": true, | ||
| 292 | + "is_public": false, | ||
| 293 | + "tags": [ | ||
| 294 | + "哲学" | ||
| 295 | + ], | ||
| 296 | + "view_count": 69, | ||
| 297 | + "volunteer_positions": [ | ||
| 298 | + "直播助理", | ||
| 299 | + "场地布置", | ||
| 300 | + "资料分发", | ||
| 301 | + "秩序维持", | ||
| 302 | + "签到助手" | ||
| 303 | + ], | ||
| 304 | + "created_at": "2025-05-07 17:13:57", | ||
| 305 | + "updated_at": "2025-05-13 07:13:57", | ||
| 306 | + "state": "upcoming" | ||
| 307 | + }, | ||
| 308 | + { | ||
| 309 | + "id": "A0010", | ||
| 310 | + "title": "从《月亮与六便士》看世界变迁", | ||
| 311 | + "organizer_id": "O0002", | ||
| 312 | + "organizer_name": "四季阅读空间", | ||
| 313 | + "description": "与志同道合的读者一起,深入解析《月亮与六便士》。\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 314 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_10_offline", | ||
| 315 | + "start_time": "2025-04-30 07:13:57", | ||
| 316 | + "end_time": "2025-04-30 10:13:57", | ||
| 317 | + "registration_start": "2025-04-16 13:13:57", | ||
| 318 | + "registration_end": "2025-04-29 13:13:57", | ||
| 319 | + "max_participants": 76, | ||
| 320 | + "participant_count": 7, | ||
| 321 | + "activity_type": "offline", | ||
| 322 | + "location": { | ||
| 323 | + "name": "城市中心图书馆", | ||
| 324 | + "address": "北京市海淀区中关村南大街5号", | ||
| 325 | + "city": "北京" | ||
| 326 | + }, | ||
| 327 | + "online_link": null, | ||
| 328 | + "is_published": true, | ||
| 329 | + "is_public": true, | ||
| 330 | + "tags": [ | ||
| 331 | + "古典文学", | ||
| 332 | + "政治" | ||
| 333 | + ], | ||
| 334 | + "view_count": 59, | ||
| 335 | + "volunteer_positions": [ | ||
| 336 | + "签到助手", | ||
| 337 | + "茶点准备", | ||
| 338 | + "设备维护", | ||
| 339 | + "资料分发" | ||
| 340 | + ], | ||
| 341 | + "created_at": "2025-04-14 13:13:57", | ||
| 342 | + "updated_at": "2025-04-17 06:13:57", | ||
| 343 | + "state": "upcoming" | ||
| 344 | + }, | ||
| 345 | + { | ||
| 346 | + "id": "A0011", | ||
| 347 | + "title": "《人类简史》的艺术赏析", | ||
| 348 | + "organizer_id": "O0009", | ||
| 349 | + "organizer_name": "四季阅读空间", | ||
| 350 | + "description": "想要探索《人类简史》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 351 | + "cover_image": "/assets/images/t2Sai-AqIpI_activity11.jpg", | ||
| 352 | + "start_time": "2025-04-17 07:13:57", | ||
| 353 | + "end_time": "2025-04-17 08:13:57", | ||
| 354 | + "registration_start": "2025-03-22 19:13:57", | ||
| 355 | + "registration_end": "2025-04-16 19:13:57", | ||
| 356 | + "max_participants": 47, | ||
| 357 | + "participant_count": 12, | ||
| 358 | + "activity_type": "offline", | ||
| 359 | + "location": { | ||
| 360 | + "name": "大雁塔文化空间", | ||
| 361 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 362 | + "city": "西安" | ||
| 363 | + }, | ||
| 364 | + "online_link": null, | ||
| 365 | + "is_published": true, | ||
| 366 | + "is_public": true, | ||
| 367 | + "tags": [ | ||
| 368 | + "政治", | ||
| 369 | + "健康", | ||
| 370 | + "传记" | ||
| 371 | + ], | ||
| 372 | + "view_count": 61, | ||
| 373 | + "volunteer_positions": [], | ||
| 374 | + "created_at": "2025-03-21 19:13:57", | ||
| 375 | + "updated_at": "2025-03-23 05:13:57", | ||
| 376 | + "state": "upcoming" | ||
| 377 | + }, | ||
| 378 | + { | ||
| 379 | + "id": "A0012", | ||
| 380 | + "title": "与作者对话:《小王子》背后的故事", | ||
| 381 | + "organizer_id": "O0001", | ||
| 382 | + "organizer_name": "光合作用文化空间", | ||
| 383 | + "description": "本次读书会将围绕《小王子》展开深入讨论。\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n活动全程录制,无法准时参加的书友可在后续获取回放。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 384 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_12_online", | ||
| 385 | + "start_time": "2025-04-04 05:13:57", | ||
| 386 | + "end_time": "2025-04-04 07:13:57", | ||
| 387 | + "registration_start": "2025-03-27 21:13:57", | ||
| 388 | + "registration_end": "2025-04-03 21:13:57", | ||
| 389 | + "max_participants": 93, | ||
| 390 | + "participant_count": 92, | ||
| 391 | + "activity_type": "online", | ||
| 392 | + "location": null, | ||
| 393 | + "online_link": "飞书线上会议,会议ID将提前发送", | ||
| 394 | + "is_published": true, | ||
| 395 | + "is_public": true, | ||
| 396 | + "tags": [ | ||
| 397 | + "环保", | ||
| 398 | + "哲学" | ||
| 399 | + ], | ||
| 400 | + "view_count": 342, | ||
| 401 | + "volunteer_positions": [ | ||
| 402 | + "秩序维持", | ||
| 403 | + "茶点准备", | ||
| 404 | + "签到助手", | ||
| 405 | + "摄影记录", | ||
| 406 | + "资料分发" | ||
| 407 | + ], | ||
| 408 | + "created_at": "2025-03-23 21:13:57", | ||
| 409 | + "updated_at": "2025-03-28 17:13:57", | ||
| 410 | + "state": "past" | ||
| 411 | + }, | ||
| 412 | + { | ||
| 413 | + "id": "A0013", | ||
| 414 | + "title": "与作者对话:《红楼梦》背后的故事", | ||
| 415 | + "organizer_id": "O0003", | ||
| 416 | + "organizer_name": "知行合一读书社", | ||
| 417 | + "description": "本次读书会将围绕《红楼梦》展开深入讨论。\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 418 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_13_offline", | ||
| 419 | + "start_time": "2025-04-16 06:02:57", | ||
| 420 | + "end_time": "2025-04-16 08:02:57", | ||
| 421 | + "registration_start": "2025-04-10 06:02:57", | ||
| 422 | + "registration_end": "2025-04-16 06:02:57", | ||
| 423 | + "max_participants": 89, | ||
| 424 | + "participant_count": 55, | ||
| 425 | + "activity_type": "offline", | ||
| 426 | + "location": { | ||
| 427 | + "name": "深蓝咖啡馆", | ||
| 428 | + "address": "深圳市南山区科技园南区科苑路15号", | ||
| 429 | + "city": "深圳" | ||
| 430 | + }, | ||
| 431 | + "online_link": null, | ||
| 432 | + "is_published": true, | ||
| 433 | + "is_public": true, | ||
| 434 | + "tags": [ | ||
| 435 | + "管理", | ||
| 436 | + "哲学" | ||
| 437 | + ], | ||
| 438 | + "view_count": 248, | ||
| 439 | + "volunteer_positions": [], | ||
| 440 | + "created_at": "2025-04-06 06:02:57", | ||
| 441 | + "updated_at": "2025-04-10 15:02:57", | ||
| 442 | + "state": "ongoing" | ||
| 443 | + }, | ||
| 444 | + { | ||
| 445 | + "id": "A0014", | ||
| 446 | + "title": "与作者对话:《白夜行》背后的故事", | ||
| 447 | + "organizer_id": "O0003", | ||
| 448 | + "organizer_name": "知行合一读书社", | ||
| 449 | + "description": "本次读书会将围绕《白夜行》展开深入讨论。\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n参与者将通过视频会议软件连接,链接将在活动开始前发送。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 450 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_14_online", | ||
| 451 | + "start_time": "2025-05-23 07:13:57", | ||
| 452 | + "end_time": "2025-05-23 08:13:57", | ||
| 453 | + "registration_start": "2025-05-09 20:13:57", | ||
| 454 | + "registration_end": "2025-05-22 20:13:57", | ||
| 455 | + "max_participants": 28, | ||
| 456 | + "participant_count": 5, | ||
| 457 | + "activity_type": "online", | ||
| 458 | + "location": null, | ||
| 459 | + "online_link": "微信视频线上会议,会议ID将提前发送", | ||
| 460 | + "is_published": true, | ||
| 461 | + "is_public": true, | ||
| 462 | + "tags": [ | ||
| 463 | + "哲学", | ||
| 464 | + "外国文学" | ||
| 465 | + ], | ||
| 466 | + "view_count": 53, | ||
| 467 | + "volunteer_positions": [ | ||
| 468 | + "设备维护", | ||
| 469 | + "秩序维持" | ||
| 470 | + ], | ||
| 471 | + "created_at": "2025-05-07 20:13:57", | ||
| 472 | + "updated_at": "2025-05-09 21:13:57", | ||
| 473 | + "state": "upcoming" | ||
| 474 | + }, | ||
| 475 | + { | ||
| 476 | + "id": "A0015", | ||
| 477 | + "title": "《思考,快与慢》的哲学思考", | ||
| 478 | + "organizer_id": "O0003", | ||
| 479 | + "organizer_name": "知行合一读书社", | ||
| 480 | + "description": "本次读书会将围绕《思考,快与慢》展开深入讨论。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n参与者将通过视频会议软件连接,链接将在活动开始前发送。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 481 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_15_online", | ||
| 482 | + "start_time": "2025-04-16 06:02:57", | ||
| 483 | + "end_time": "2025-04-16 09:02:57", | ||
| 484 | + "registration_start": "2025-04-12 06:02:57", | ||
| 485 | + "registration_end": "2025-04-16 06:02:57", | ||
| 486 | + "max_participants": 21, | ||
| 487 | + "participant_count": 12, | ||
| 488 | + "activity_type": "online", | ||
| 489 | + "location": null, | ||
| 490 | + "online_link": "腾讯会议线上会议,会议ID将提前发送", | ||
| 491 | + "is_published": true, | ||
| 492 | + "is_public": true, | ||
| 493 | + "tags": [ | ||
| 494 | + "心理学", | ||
| 495 | + "环保" | ||
| 496 | + ], | ||
| 497 | + "view_count": 103, | ||
| 498 | + "volunteer_positions": [], | ||
| 499 | + "created_at": "2025-04-07 06:02:57", | ||
| 500 | + "updated_at": "2025-04-12 13:02:57", | ||
| 501 | + "state": "ongoing" | ||
| 502 | + }, | ||
| 503 | + { | ||
| 504 | + "id": "A0016", | ||
| 505 | + "title": "《自控力》的艺术赏析", | ||
| 506 | + "organizer_id": "O0002", | ||
| 507 | + "organizer_name": "四季阅读空间", | ||
| 508 | + "description": "本次读书会将围绕《自控力》展开深入讨论。\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 509 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_16_offline", | ||
| 510 | + "start_time": "2025-07-01 07:13:57", | ||
| 511 | + "end_time": "2025-07-01 08:13:57", | ||
| 512 | + "registration_start": "2025-06-15 13:13:57", | ||
| 513 | + "registration_end": "2025-06-30 13:13:57", | ||
| 514 | + "max_participants": 48, | ||
| 515 | + "participant_count": 2, | ||
| 516 | + "activity_type": "offline", | ||
| 517 | + "location": { | ||
| 518 | + "name": "城市中心图书馆", | ||
| 519 | + "address": "北京市海淀区中关村南大街5号", | ||
| 520 | + "city": "北京" | ||
| 521 | + }, | ||
| 522 | + "online_link": null, | ||
| 523 | + "is_published": true, | ||
| 524 | + "is_public": true, | ||
| 525 | + "tags": [ | ||
| 526 | + "历史文化" | ||
| 527 | + ], | ||
| 528 | + "view_count": 90, | ||
| 529 | + "volunteer_positions": [ | ||
| 530 | + "茶点准备", | ||
| 531 | + "场地布置", | ||
| 532 | + "活动总结", | ||
| 533 | + "设备维护", | ||
| 534 | + "签到助手" | ||
| 535 | + ], | ||
| 536 | + "created_at": "2025-06-11 13:13:57", | ||
| 537 | + "updated_at": "2025-06-16 10:13:57", | ||
| 538 | + "state": "upcoming" | ||
| 539 | + }, | ||
| 540 | + { | ||
| 541 | + "id": "A0017", | ||
| 542 | + "title": "经典重温:《解忧杂货店》", | ||
| 543 | + "organizer_id": "O0006", | ||
| 544 | + "organizer_name": "百草园读书会", | ||
| 545 | + "description": "诚挚邀请书友们参加《解忧杂货店》读书分享会。\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n线上活动无地域限制,请提前调试好设备,确保网络流畅。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 546 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_17_online", | ||
| 547 | + "start_time": "2025-06-15 07:13:57", | ||
| 548 | + "end_time": "2025-06-15 10:13:57", | ||
| 549 | + "registration_start": "2025-05-27 02:13:57", | ||
| 550 | + "registration_end": "2025-06-15 02:13:57", | ||
| 551 | + "max_participants": 75, | ||
| 552 | + "participant_count": 9, | ||
| 553 | + "activity_type": "online", | ||
| 554 | + "location": null, | ||
| 555 | + "online_link": "飞书线上会议,会议ID将提前发送", | ||
| 556 | + "is_published": true, | ||
| 557 | + "is_public": true, | ||
| 558 | + "tags": [ | ||
| 559 | + "文学", | ||
| 560 | + "科技", | ||
| 561 | + "健康" | ||
| 562 | + ], | ||
| 563 | + "view_count": 34, | ||
| 564 | + "volunteer_positions": [], | ||
| 565 | + "created_at": "2025-05-26 02:13:57", | ||
| 566 | + "updated_at": "2025-05-27 15:13:57", | ||
| 567 | + "state": "upcoming" | ||
| 568 | + }, | ||
| 569 | + { | ||
| 570 | + "id": "A0018", | ||
| 571 | + "title": "从《未来简史》看世界变迁", | ||
| 572 | + "organizer_id": "O0003", | ||
| 573 | + "organizer_name": "知行合一读书社", | ||
| 574 | + "description": "与志同道合的读者一起,深入解析《未来简史》。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n线上活动无地域限制,请提前调试好设备,确保网络流畅。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 575 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_18_online", | ||
| 576 | + "start_time": "2025-06-14 07:13:57", | ||
| 577 | + "end_time": "2025-06-14 09:13:57", | ||
| 578 | + "registration_start": "2025-06-04 02:13:57", | ||
| 579 | + "registration_end": "2025-06-14 02:13:57", | ||
| 580 | + "max_participants": 72, | ||
| 581 | + "participant_count": 12, | ||
| 582 | + "activity_type": "online", | ||
| 583 | + "location": null, | ||
| 584 | + "online_link": "飞书线上会议,会议ID将提前发送", | ||
| 585 | + "is_published": true, | ||
| 586 | + "is_public": true, | ||
| 587 | + "tags": [ | ||
| 588 | + "诗歌" | ||
| 589 | + ], | ||
| 590 | + "view_count": 27, | ||
| 591 | + "volunteer_positions": [], | ||
| 592 | + "created_at": "2025-05-31 02:13:57", | ||
| 593 | + "updated_at": "2025-06-04 07:13:57", | ||
| 594 | + "state": "upcoming" | ||
| 595 | + }, | ||
| 596 | + { | ||
| 597 | + "id": "A0019", | ||
| 598 | + "title": "与作者对话:《月亮与六便士》背后的故事", | ||
| 599 | + "organizer_id": "O0004", | ||
| 600 | + "organizer_name": "百草园读书会", | ||
| 601 | + "description": "诚挚邀请书友们参加《月亮与六便士》读书分享会。\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n线上活动无地域限制,请提前调试好设备,确保网络流畅。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 602 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_19_online", | ||
| 603 | + "start_time": "2025-04-16 05:34:57", | ||
| 604 | + "end_time": "2025-04-16 08:34:57", | ||
| 605 | + "registration_start": "2025-04-11 05:34:57", | ||
| 606 | + "registration_end": "2025-04-16 05:34:57", | ||
| 607 | + "max_participants": 29, | ||
| 608 | + "participant_count": 15, | ||
| 609 | + "activity_type": "online", | ||
| 610 | + "location": null, | ||
| 611 | + "online_link": "钉钉线上会议,会议ID将提前发送", | ||
| 612 | + "is_published": true, | ||
| 613 | + "is_public": false, | ||
| 614 | + "tags": [ | ||
| 615 | + "健康", | ||
| 616 | + "科学普及" | ||
| 617 | + ], | ||
| 618 | + "view_count": 74, | ||
| 619 | + "volunteer_positions": [ | ||
| 620 | + "摄影记录", | ||
| 621 | + "签到助手", | ||
| 622 | + "设备维护" | ||
| 623 | + ], | ||
| 624 | + "created_at": "2025-04-07 05:34:57", | ||
| 625 | + "updated_at": "2025-04-11 13:34:57", | ||
| 626 | + "state": "ongoing" | ||
| 627 | + }, | ||
| 628 | + { | ||
| 629 | + "id": "A0020", | ||
| 630 | + "title": "《心理学与生活》的哲学思考", | ||
| 631 | + "organizer_id": "O0001", | ||
| 632 | + "organizer_name": "光合作用文化空间", | ||
| 633 | + "description": "与志同道合的读者一起,深入解析《心理学与生活》。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n参与者将通过视频会议软件连接,链接将在活动开始前发送。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 634 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_20_online", | ||
| 635 | + "start_time": "2025-06-17 07:13:57", | ||
| 636 | + "end_time": "2025-06-17 10:13:57", | ||
| 637 | + "registration_start": "2025-06-01 10:13:57", | ||
| 638 | + "registration_end": "2025-06-16 10:13:57", | ||
| 639 | + "max_participants": 38, | ||
| 640 | + "participant_count": 2, | ||
| 641 | + "activity_type": "online", | ||
| 642 | + "location": null, | ||
| 643 | + "online_link": "钉钉线上会议,会议ID将提前发送", | ||
| 644 | + "is_published": true, | ||
| 645 | + "is_public": true, | ||
| 646 | + "tags": [ | ||
| 647 | + "历史", | ||
| 648 | + "文学", | ||
| 649 | + "管理" | ||
| 650 | + ], | ||
| 651 | + "view_count": 87, | ||
| 652 | + "volunteer_positions": [ | ||
| 653 | + "摄影记录", | ||
| 654 | + "资料分发" | ||
| 655 | + ], | ||
| 656 | + "created_at": "2025-05-27 10:13:57", | ||
| 657 | + "updated_at": "2025-06-02 04:13:57", | ||
| 658 | + "state": "upcoming" | ||
| 659 | + }, | ||
| 660 | + { | ||
| 661 | + "id": "A0021", | ||
| 662 | + "title": "深度解读《了不起的盖茨比》", | ||
| 663 | + "organizer_id": "O0007", | ||
| 664 | + "organizer_name": "百草园读书会", | ||
| 665 | + "description": "诚挚邀请书友们参加《了不起的盖茨比》读书分享会。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n参与者将通过视频会议软件连接,链接将在活动开始前发送。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 666 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_21_online", | ||
| 667 | + "start_time": "2025-05-04 07:13:57", | ||
| 668 | + "end_time": "2025-05-04 09:13:57", | ||
| 669 | + "registration_start": "2025-04-16 21:13:57", | ||
| 670 | + "registration_end": "2025-05-03 21:13:57", | ||
| 671 | + "max_participants": 75, | ||
| 672 | + "participant_count": 15, | ||
| 673 | + "activity_type": "online", | ||
| 674 | + "location": null, | ||
| 675 | + "online_link": "Zoom线上会议,会议ID将提前发送", | ||
| 676 | + "is_published": true, | ||
| 677 | + "is_public": false, | ||
| 678 | + "tags": [ | ||
| 679 | + "历史", | ||
| 680 | + "心灵成长" | ||
| 681 | + ], | ||
| 682 | + "view_count": 49, | ||
| 683 | + "volunteer_positions": [], | ||
| 684 | + "created_at": "2025-04-12 21:13:57", | ||
| 685 | + "updated_at": "2025-04-17 08:13:57", | ||
| 686 | + "state": "upcoming" | ||
| 687 | + }, | ||
| 688 | + { | ||
| 689 | + "id": "A0022", | ||
| 690 | + "title": "青年读书会:共读《未来简史》", | ||
| 691 | + "organizer_id": "O0005", | ||
| 692 | + "organizer_name": "鹿鸣书店", | ||
| 693 | + "description": "诚挚邀请书友们参加《未来简史》读书分享会。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 694 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_22_offline", | ||
| 695 | + "start_time": "2025-04-16 06:31:57", | ||
| 696 | + "end_time": "2025-04-16 07:31:57", | ||
| 697 | + "registration_start": "2025-04-02 06:31:57", | ||
| 698 | + "registration_end": "2025-04-16 06:31:57", | ||
| 699 | + "max_participants": 78, | ||
| 700 | + "participant_count": 46, | ||
| 701 | + "activity_type": "offline", | ||
| 702 | + "location": { | ||
| 703 | + "name": "大雁塔文化空间", | ||
| 704 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 705 | + "city": "西安" | ||
| 706 | + }, | ||
| 707 | + "online_link": null, | ||
| 708 | + "is_published": true, | ||
| 709 | + "is_public": true, | ||
| 710 | + "tags": [ | ||
| 711 | + "管理" | ||
| 712 | + ], | ||
| 713 | + "view_count": 74, | ||
| 714 | + "volunteer_positions": [ | ||
| 715 | + "设备维护", | ||
| 716 | + "直播助理", | ||
| 717 | + "资料分发" | ||
| 718 | + ], | ||
| 719 | + "created_at": "2025-04-01 06:31:57", | ||
| 720 | + "updated_at": "2025-04-02 23:31:57", | ||
| 721 | + "state": "ongoing" | ||
| 722 | + }, | ||
| 723 | + { | ||
| 724 | + "id": "A0023", | ||
| 725 | + "title": "《万物简史》的哲学思考", | ||
| 726 | + "organizer_id": "O0007", | ||
| 727 | + "organizer_name": "百草园读书会", | ||
| 728 | + "description": "诚挚邀请书友们参加《万物简史》读书分享会。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n参与者将通过视频会议软件连接,链接将在活动开始前发送。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 729 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_23_online", | ||
| 730 | + "start_time": "2025-03-27 05:13:57", | ||
| 731 | + "end_time": "2025-03-27 07:13:57", | ||
| 732 | + "registration_start": "2025-03-22 02:13:57", | ||
| 733 | + "registration_end": "2025-03-27 02:13:57", | ||
| 734 | + "max_participants": 47, | ||
| 735 | + "participant_count": 38, | ||
| 736 | + "activity_type": "online", | ||
| 737 | + "location": null, | ||
| 738 | + "online_link": "飞书线上会议,会议ID将提前发送", | ||
| 739 | + "is_published": true, | ||
| 740 | + "is_public": true, | ||
| 741 | + "tags": [ | ||
| 742 | + "外国文学", | ||
| 743 | + "历史", | ||
| 744 | + "历史文化" | ||
| 745 | + ], | ||
| 746 | + "view_count": 552, | ||
| 747 | + "volunteer_positions": [ | ||
| 748 | + "设备维护", | ||
| 749 | + "秩序维持", | ||
| 750 | + "摄影记录", | ||
| 751 | + "活动总结" | ||
| 752 | + ], | ||
| 753 | + "created_at": "2025-03-19 02:13:57", | ||
| 754 | + "updated_at": "2025-03-23 00:13:57", | ||
| 755 | + "state": "past" | ||
| 756 | + }, | ||
| 757 | + { | ||
| 758 | + "id": "A0024", | ||
| 759 | + "title": "跨界思考:《活着》与现代社会", | ||
| 760 | + "organizer_id": "O0003", | ||
| 761 | + "organizer_name": "知行合一读书社", | ||
| 762 | + "description": "想要探索《活着》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 763 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_24_offline", | ||
| 764 | + "start_time": "2025-05-21 07:13:57", | ||
| 765 | + "end_time": "2025-05-21 09:13:57", | ||
| 766 | + "registration_start": "2025-04-22 23:13:57", | ||
| 767 | + "registration_end": "2025-05-20 23:13:57", | ||
| 768 | + "max_participants": 77, | ||
| 769 | + "participant_count": 11, | ||
| 770 | + "activity_type": "offline", | ||
| 771 | + "location": { | ||
| 772 | + "name": "深蓝咖啡馆", | ||
| 773 | + "address": "深圳市南山区科技园南区科苑路15号", | ||
| 774 | + "city": "深圳" | ||
| 775 | + }, | ||
| 776 | + "online_link": null, | ||
| 777 | + "is_published": true, | ||
| 778 | + "is_public": false, | ||
| 779 | + "tags": [ | ||
| 780 | + "环保" | ||
| 781 | + ], | ||
| 782 | + "view_count": 61, | ||
| 783 | + "volunteer_positions": [ | ||
| 784 | + "茶点准备", | ||
| 785 | + "秩序维持" | ||
| 786 | + ], | ||
| 787 | + "created_at": "2025-04-20 23:13:57", | ||
| 788 | + "updated_at": "2025-04-23 12:13:57", | ||
| 789 | + "state": "upcoming" | ||
| 790 | + }, | ||
| 791 | + { | ||
| 792 | + "id": "A0025", | ||
| 793 | + "title": "经典重温:《活着》", | ||
| 794 | + "organizer_id": "O0009", | ||
| 795 | + "organizer_name": "四季阅读空间", | ||
| 796 | + "description": "与志同道合的读者一起,深入解析《活着》。\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n每一次阅读都是新的开始,每一次讨论都是思想的盛宴。", | ||
| 797 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_25_offline", | ||
| 798 | + "start_time": "2025-05-08 07:13:57", | ||
| 799 | + "end_time": "2025-05-08 09:13:57", | ||
| 800 | + "registration_start": "2025-04-22 09:13:57", | ||
| 801 | + "registration_end": "2025-05-07 09:13:57", | ||
| 802 | + "max_participants": 83, | ||
| 803 | + "participant_count": 11, | ||
| 804 | + "activity_type": "offline", | ||
| 805 | + "location": { | ||
| 806 | + "name": "大雁塔文化空间", | ||
| 807 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 808 | + "city": "西安" | ||
| 809 | + }, | ||
| 810 | + "online_link": null, | ||
| 811 | + "is_published": true, | ||
| 812 | + "is_public": true, | ||
| 813 | + "tags": [ | ||
| 814 | + "经济" | ||
| 815 | + ], | ||
| 816 | + "view_count": 30, | ||
| 817 | + "volunteer_positions": [ | ||
| 818 | + "讨论主持", | ||
| 819 | + "资料分发", | ||
| 820 | + "摄影记录", | ||
| 821 | + "秩序维持", | ||
| 822 | + "场地布置" | ||
| 823 | + ], | ||
| 824 | + "created_at": "2025-04-20 09:13:57", | ||
| 825 | + "updated_at": "2025-04-23 06:13:57", | ||
| 826 | + "state": "upcoming" | ||
| 827 | + }, | ||
| 828 | + { | ||
| 829 | + "id": "A0026", | ||
| 830 | + "title": "《未来简史》的哲学思考", | ||
| 831 | + "organizer_id": "O0007", | ||
| 832 | + "organizer_name": "百草园读书会", | ||
| 833 | + "description": "想要探索《未来简史》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n活动将邀请资深书评人进行导读,随后开展自由讨论与交流。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 834 | + "cover_image": "/assets/images/XqXJJhK-c08.jpg", | ||
| 835 | + "start_time": "2025-04-29 07:13:57", | ||
| 836 | + "end_time": "2025-04-29 09:13:57", | ||
| 837 | + "registration_start": "2025-04-03 10:13:57", | ||
| 838 | + "registration_end": "2025-04-28 10:13:57", | ||
| 839 | + "max_participants": 90, | ||
| 840 | + "participant_count": 9, | ||
| 841 | + "activity_type": "offline", | ||
| 842 | + "location": { | ||
| 843 | + "name": "紫金读书会", | ||
| 844 | + "address": "南京市鼓楼区中山路99号", | ||
| 845 | + "city": "南京" | ||
| 846 | + }, | ||
| 847 | + "online_link": null, | ||
| 848 | + "is_published": true, | ||
| 849 | + "is_public": true, | ||
| 850 | + "tags": [ | ||
| 851 | + "健康生活" | ||
| 852 | + ], | ||
| 853 | + "view_count": 60, | ||
| 854 | + "volunteer_positions": [], | ||
| 855 | + "created_at": "2025-03-29 10:13:57", | ||
| 856 | + "updated_at": "2025-04-03 22:13:57", | ||
| 857 | + "state": "upcoming" | ||
| 858 | + }, | ||
| 859 | + { | ||
| 860 | + "id": "A0027", | ||
| 861 | + "title": "跨界思考:《百年孤独》与现代社会", | ||
| 862 | + "organizer_id": "O0005", | ||
| 863 | + "organizer_name": "鹿鸣书店", | ||
| 864 | + "description": "诚挚邀请书友们参加《百年孤独》读书分享会。\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n场地座位有限,请提前报名,准时到场。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 865 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_27_offline", | ||
| 866 | + "start_time": "2025-04-16 05:21:57", | ||
| 867 | + "end_time": "2025-04-16 08:21:57", | ||
| 868 | + "registration_start": "2025-04-11 05:21:57", | ||
| 869 | + "registration_end": "2025-04-16 05:21:57", | ||
| 870 | + "max_participants": 23, | ||
| 871 | + "participant_count": 15, | ||
| 872 | + "activity_type": "offline", | ||
| 873 | + "location": { | ||
| 874 | + "name": "大雁塔文化空间", | ||
| 875 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 876 | + "city": "西安" | ||
| 877 | + }, | ||
| 878 | + "online_link": null, | ||
| 879 | + "is_published": true, | ||
| 880 | + "is_public": true, | ||
| 881 | + "tags": [ | ||
| 882 | + "社会科学", | ||
| 883 | + "传记" | ||
| 884 | + ], | ||
| 885 | + "view_count": 248, | ||
| 886 | + "volunteer_positions": [], | ||
| 887 | + "created_at": "2025-04-10 05:21:57", | ||
| 888 | + "updated_at": "2025-04-11 06:21:57", | ||
| 889 | + "state": "ongoing" | ||
| 890 | + }, | ||
| 891 | + { | ||
| 892 | + "id": "A0028", | ||
| 893 | + "title": "跨界思考:《追风筝的人》与现代社会", | ||
| 894 | + "organizer_id": "O0008", | ||
| 895 | + "organizer_name": "墨香文化传媒", | ||
| 896 | + "description": "想要探索《追风筝的人》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n除了对内容的讨论,我们还将探索作者创作背景与写作技巧。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n现场提供免费茶点,请携带纸质书籍或笔记参加。\n\n期待您的参与,共同度过一个充满思想碰撞的美好时光!", | ||
| 897 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_28_offline", | ||
| 898 | + "start_time": "2025-05-27 07:13:57", | ||
| 899 | + "end_time": "2025-05-27 10:13:57", | ||
| 900 | + "registration_start": "2025-05-06 17:13:57", | ||
| 901 | + "registration_end": "2025-05-26 17:13:57", | ||
| 902 | + "max_participants": 86, | ||
| 903 | + "participant_count": 15, | ||
| 904 | + "activity_type": "offline", | ||
| 905 | + "location": { | ||
| 906 | + "name": "大雁塔文化空间", | ||
| 907 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 908 | + "city": "西安" | ||
| 909 | + }, | ||
| 910 | + "online_link": null, | ||
| 911 | + "is_published": true, | ||
| 912 | + "is_public": true, | ||
| 913 | + "tags": [ | ||
| 914 | + "健康", | ||
| 915 | + "音乐" | ||
| 916 | + ], | ||
| 917 | + "view_count": 98, | ||
| 918 | + "volunteer_positions": [ | ||
| 919 | + "场地布置" | ||
| 920 | + ], | ||
| 921 | + "created_at": "2025-05-04 17:13:57", | ||
| 922 | + "updated_at": "2025-05-06 18:13:57", | ||
| 923 | + "state": "upcoming" | ||
| 924 | + }, | ||
| 925 | + { | ||
| 926 | + "id": "A0029", | ||
| 927 | + "title": "《了不起的盖茨比》的艺术赏析", | ||
| 928 | + "organizer_id": "O0005", | ||
| 929 | + "organizer_name": "鹿鸣书店", | ||
| 930 | + "description": "想要探索《了不起的盖茨比》的深层含义?欢迎加入我们的读书会!\n\n【活动内容】\n通过分组讨论、角色扮演等互动形式,全方位解读这部作品。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n线上活动无地域限制,请提前调试好设备,确保网络流畅。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 931 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_29_online", | ||
| 932 | + "start_time": "2025-03-18 05:13:57", | ||
| 933 | + "end_time": "2025-03-18 07:13:57", | ||
| 934 | + "registration_start": "2025-03-06 01:13:57", | ||
| 935 | + "registration_end": "2025-03-18 01:13:57", | ||
| 936 | + "max_participants": 42, | ||
| 937 | + "participant_count": 40, | ||
| 938 | + "activity_type": "online", | ||
| 939 | + "location": null, | ||
| 940 | + "online_link": "Zoom线上会议,会议ID将提前发送", | ||
| 941 | + "is_published": true, | ||
| 942 | + "is_public": false, | ||
| 943 | + "tags": [ | ||
| 944 | + "古典文学", | ||
| 945 | + "哲学", | ||
| 946 | + "健康" | ||
| 947 | + ], | ||
| 948 | + "view_count": 772, | ||
| 949 | + "volunteer_positions": [], | ||
| 950 | + "created_at": "2025-03-05 01:13:57", | ||
| 951 | + "updated_at": "2025-03-06 07:13:57", | ||
| 952 | + "state": "past" | ||
| 953 | + }, | ||
| 954 | + { | ||
| 955 | + "id": "A0030", | ||
| 956 | + "title": "从《活着》看世界变迁", | ||
| 957 | + "organizer_id": "O0005", | ||
| 958 | + "organizer_name": "鹿鸣书店", | ||
| 959 | + "description": "本次读书会将围绕《活着》展开深入讨论。\n\n【活动内容】\n我们将共同探讨书中的核心思想,分享阅读感悟,碰撞思维火花。\n\n【活动安排】\n1. 开场与活动介绍(15分钟)2. 作品导读(30分钟)3. 分组讨论(45分钟)4. 交流分享(30分钟)5. 问答与总结(15分钟)\n\n【参与须知】\n活动结束后有半小时自由交流时间,欢迎书友们互相认识。\n\n让我们在书香中相遇,在思想的海洋里遨游。", | ||
| 960 | + "cover_image": "https://via.placeholder.com/1600x900.png?text=Activity_30_offline", | ||
| 961 | + "start_time": "2025-03-24 06:13:57", | ||
| 962 | + "end_time": "2025-03-24 07:13:57", | ||
| 963 | + "registration_start": "2025-03-13 02:13:57", | ||
| 964 | + "registration_end": "2025-03-24 02:13:57", | ||
| 965 | + "max_participants": 64, | ||
| 966 | + "participant_count": 60, | ||
| 967 | + "activity_type": "offline", | ||
| 968 | + "location": { | ||
| 969 | + "name": "大雁塔文化空间", | ||
| 970 | + "address": "西安市雁塔区雁塔西路68号", | ||
| 971 | + "city": "西安" | ||
| 972 | + }, | ||
| 973 | + "online_link": null, | ||
| 974 | + "is_published": true, | ||
| 975 | + "is_public": true, | ||
| 976 | + "tags": [ | ||
| 977 | + "教育" | ||
| 978 | + ], | ||
| 979 | + "view_count": 881, | ||
| 980 | + "volunteer_positions": [ | ||
| 981 | + "签到助手", | ||
| 982 | + "茶点准备", | ||
| 983 | + "场地布置", | ||
| 984 | + "活动总结" | ||
| 985 | + ], | ||
| 986 | + "created_at": "2025-03-11 02:13:57", | ||
| 987 | + "updated_at": "2025-03-13 12:13:57", | ||
| 988 | + "state": "past" | ||
| 989 | + } | ||
| 990 | +] | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
public/data/checkins.json
0 → 100644
| 1 | +[ | ||
| 2 | + { | ||
| 3 | + "id": "C0001", | ||
| 4 | + "activity_id": "A0001", | ||
| 5 | + "user_id": "U0010", | ||
| 6 | + "registration_id": "R0001", | ||
| 7 | + "checkin_time": "2025-04-02 06:15:17", | ||
| 8 | + "checkin_type": "QR code", | ||
| 9 | + "location": null, | ||
| 10 | + "staff_id": null, | ||
| 11 | + "status": "successful", | ||
| 12 | + "notes": "", | ||
| 13 | + "is_late": false | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "id": "C0002", | ||
| 17 | + "activity_id": "A0001", | ||
| 18 | + "user_id": "U0020", | ||
| 19 | + "registration_id": "R0002", | ||
| 20 | + "checkin_time": "2025-04-02 05:59:08", | ||
| 21 | + "checkin_type": "QR code", | ||
| 22 | + "location": null, | ||
| 23 | + "staff_id": null, | ||
| 24 | + "status": "successful", | ||
| 25 | + "notes": "", | ||
| 26 | + "is_late": false | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + "id": "C0003", | ||
| 30 | + "activity_id": "A0001", | ||
| 31 | + "user_id": "U0032", | ||
| 32 | + "registration_id": "R0004", | ||
| 33 | + "checkin_time": "2025-04-02 06:22:39", | ||
| 34 | + "checkin_type": "QR code", | ||
| 35 | + "location": null, | ||
| 36 | + "staff_id": null, | ||
| 37 | + "status": "successful", | ||
| 38 | + "notes": "", | ||
| 39 | + "is_late": true | ||
| 40 | + }, | ||
| 41 | + { | ||
| 42 | + "id": "C0004", | ||
| 43 | + "activity_id": "A0001", | ||
| 44 | + "user_id": "U0025", | ||
| 45 | + "registration_id": "R0005", | ||
| 46 | + "checkin_time": "2025-04-02 06:27:22", | ||
| 47 | + "checkin_type": "QR code", | ||
| 48 | + "location": null, | ||
| 49 | + "staff_id": null, | ||
| 50 | + "status": "successful", | ||
| 51 | + "notes": "", | ||
| 52 | + "is_late": false | ||
| 53 | + }, | ||
| 54 | + { | ||
| 55 | + "id": "C0005", | ||
| 56 | + "activity_id": "A0001", | ||
| 57 | + "user_id": "U0012", | ||
| 58 | + "registration_id": "R0006", | ||
| 59 | + "checkin_time": "2025-04-02 06:20:42", | ||
| 60 | + "checkin_type": "QR code", | ||
| 61 | + "location": null, | ||
| 62 | + "staff_id": null, | ||
| 63 | + "status": "successful", | ||
| 64 | + "notes": "", | ||
| 65 | + "is_late": true | ||
| 66 | + }, | ||
| 67 | + { | ||
| 68 | + "id": "C0006", | ||
| 69 | + "activity_id": "A0001", | ||
| 70 | + "user_id": "U0034", | ||
| 71 | + "registration_id": "R0008", | ||
| 72 | + "checkin_time": "2025-04-02 06:31:33", | ||
| 73 | + "checkin_type": "QR code", | ||
| 74 | + "location": null, | ||
| 75 | + "staff_id": null, | ||
| 76 | + "status": "successful", | ||
| 77 | + "notes": "", | ||
| 78 | + "is_late": false | ||
| 79 | + }, | ||
| 80 | + { | ||
| 81 | + "id": "C0007", | ||
| 82 | + "activity_id": "A0001", | ||
| 83 | + "user_id": "U0035", | ||
| 84 | + "registration_id": "R0010", | ||
| 85 | + "checkin_time": "2025-04-02 06:43:04", | ||
| 86 | + "checkin_type": "QR code", | ||
| 87 | + "location": null, | ||
| 88 | + "staff_id": null, | ||
| 89 | + "status": "successful", | ||
| 90 | + "notes": "", | ||
| 91 | + "is_late": false | ||
| 92 | + }, | ||
| 93 | + { | ||
| 94 | + "id": "C0008", | ||
| 95 | + "activity_id": "A0001", | ||
| 96 | + "user_id": "U0008", | ||
| 97 | + "registration_id": "R0011", | ||
| 98 | + "checkin_time": "2025-04-02 06:24:37", | ||
| 99 | + "checkin_type": "QR code", | ||
| 100 | + "location": null, | ||
| 101 | + "staff_id": null, | ||
| 102 | + "status": "successful", | ||
| 103 | + "notes": "带了书本", | ||
| 104 | + "is_late": false | ||
| 105 | + }, | ||
| 106 | + { | ||
| 107 | + "id": "C0009", | ||
| 108 | + "activity_id": "A0001", | ||
| 109 | + "user_id": "U0016", | ||
| 110 | + "registration_id": "R0012", | ||
| 111 | + "checkin_time": "2025-04-02 06:09:02", | ||
| 112 | + "checkin_type": "QR code", | ||
| 113 | + "location": null, | ||
| 114 | + "staff_id": null, | ||
| 115 | + "status": "successful", | ||
| 116 | + "notes": "", | ||
| 117 | + "is_late": false | ||
| 118 | + }, | ||
| 119 | + { | ||
| 120 | + "id": "C0010", | ||
| 121 | + "activity_id": "A0001", | ||
| 122 | + "user_id": "U0009", | ||
| 123 | + "registration_id": "R0014", | ||
| 124 | + "checkin_time": "2025-04-02 06:40:18", | ||
| 125 | + "checkin_type": "QR code", | ||
| 126 | + "location": null, | ||
| 127 | + "staff_id": null, | ||
| 128 | + "status": "successful", | ||
| 129 | + "notes": "带了书本", | ||
| 130 | + "is_late": false | ||
| 131 | + }, | ||
| 132 | + { | ||
| 133 | + "id": "C0011", | ||
| 134 | + "activity_id": "A0001", | ||
| 135 | + "user_id": "U0015", | ||
| 136 | + "registration_id": "R0015", | ||
| 137 | + "checkin_time": "2025-04-02 05:59:41", | ||
| 138 | + "checkin_type": "QR code", | ||
| 139 | + "location": null, | ||
| 140 | + "staff_id": null, | ||
| 141 | + "status": "successful", | ||
| 142 | + "notes": "", | ||
| 143 | + "is_late": false | ||
| 144 | + }, | ||
| 145 | + { | ||
| 146 | + "id": "C0012", | ||
| 147 | + "activity_id": "A0001", | ||
| 148 | + "user_id": "U0019", | ||
| 149 | + "registration_id": "R0016", | ||
| 150 | + "checkin_time": "2025-04-02 06:11:07", | ||
| 151 | + "checkin_type": "QR code", | ||
| 152 | + "location": null, | ||
| 153 | + "staff_id": null, | ||
| 154 | + "status": "successful", | ||
| 155 | + "notes": "", | ||
| 156 | + "is_late": false | ||
| 157 | + }, | ||
| 158 | + { | ||
| 159 | + "id": "C0013", | ||
| 160 | + "activity_id": "A0001", | ||
| 161 | + "user_id": "U0033", | ||
| 162 | + "registration_id": "R0017", | ||
| 163 | + "checkin_time": "2025-04-02 06:24:37", | ||
| 164 | + "checkin_type": "QR code", | ||
| 165 | + "location": null, | ||
| 166 | + "staff_id": null, | ||
| 167 | + "status": "successful", | ||
| 168 | + "notes": "", | ||
| 169 | + "is_late": false | ||
| 170 | + }, | ||
| 171 | + { | ||
| 172 | + "id": "C0014", | ||
| 173 | + "activity_id": "A0001", | ||
| 174 | + "user_id": "U0001", | ||
| 175 | + "registration_id": "R0018", | ||
| 176 | + "checkin_time": "2025-04-02 05:59:19", | ||
| 177 | + "checkin_type": "QR code", | ||
| 178 | + "location": null, | ||
| 179 | + "staff_id": null, | ||
| 180 | + "status": "successful", | ||
| 181 | + "notes": "热情参与讨论", | ||
| 182 | + "is_late": false | ||
| 183 | + }, | ||
| 184 | + { | ||
| 185 | + "id": "C0015", | ||
| 186 | + "activity_id": "A0001", | ||
| 187 | + "user_id": "U0036", | ||
| 188 | + "registration_id": "R0019", | ||
| 189 | + "checkin_time": "2025-04-02 06:06:21", | ||
| 190 | + "checkin_type": "QR code", | ||
| 191 | + "location": null, | ||
| 192 | + "staff_id": null, | ||
| 193 | + "status": "successful", | ||
| 194 | + "notes": "按时到达", | ||
| 195 | + "is_late": false | ||
| 196 | + }, | ||
| 197 | + { | ||
| 198 | + "id": "C0016", | ||
| 199 | + "activity_id": "A0001", | ||
| 200 | + "user_id": "U0004", | ||
| 201 | + "registration_id": "R0020", | ||
| 202 | + "checkin_time": "2025-04-02 06:20:20", | ||
| 203 | + "checkin_type": "manual", | ||
| 204 | + "location": null, | ||
| 205 | + "staff_id": "O0006", | ||
| 206 | + "status": "failed", | ||
| 207 | + "notes": "网络连接不稳定", | ||
| 208 | + "is_late": false | ||
| 209 | + }, | ||
| 210 | + { | ||
| 211 | + "id": "C0017", | ||
| 212 | + "activity_id": "A0001", | ||
| 213 | + "user_id": "U0029", | ||
| 214 | + "registration_id": "R0022", | ||
| 215 | + "checkin_time": "2025-04-02 06:26:13", | ||
| 216 | + "checkin_type": "QR code", | ||
| 217 | + "location": null, | ||
| 218 | + "staff_id": null, | ||
| 219 | + "status": "successful", | ||
| 220 | + "notes": "", | ||
| 221 | + "is_late": false | ||
| 222 | + }, | ||
| 223 | + { | ||
| 224 | + "id": "C0018", | ||
| 225 | + "activity_id": "A0001", | ||
| 226 | + "user_id": "U0031", | ||
| 227 | + "registration_id": "R0023", | ||
| 228 | + "checkin_time": "2025-04-02 06:01:47", | ||
| 229 | + "checkin_type": "self-service", | ||
| 230 | + "location": null, | ||
| 231 | + "staff_id": null, | ||
| 232 | + "status": "successful", | ||
| 233 | + "notes": "", | ||
| 234 | + "is_late": false | ||
| 235 | + }, | ||
| 236 | + { | ||
| 237 | + "id": "C0019", | ||
| 238 | + "activity_id": "A0001", | ||
| 239 | + "user_id": "U0011", | ||
| 240 | + "registration_id": "R0024", | ||
| 241 | + "checkin_time": "2025-04-02 06:01:25", | ||
| 242 | + "checkin_type": "self-service", | ||
| 243 | + "location": null, | ||
| 244 | + "staff_id": null, | ||
| 245 | + "status": "successful", | ||
| 246 | + "notes": "", | ||
| 247 | + "is_late": false | ||
| 248 | + }, | ||
| 249 | + { | ||
| 250 | + "id": "C0020", | ||
| 251 | + "activity_id": "A0001", | ||
| 252 | + "user_id": "U0040", | ||
| 253 | + "registration_id": "R0027", | ||
| 254 | + "checkin_time": "2025-04-02 06:14:06", | ||
| 255 | + "checkin_type": "self-service", | ||
| 256 | + "location": null, | ||
| 257 | + "staff_id": null, | ||
| 258 | + "status": "successful", | ||
| 259 | + "notes": "", | ||
| 260 | + "is_late": false | ||
| 261 | + }, | ||
| 262 | + { | ||
| 263 | + "id": "C0021", | ||
| 264 | + "activity_id": "A0001", | ||
| 265 | + "user_id": "U0003", | ||
| 266 | + "registration_id": "R0028", | ||
| 267 | + "checkin_time": "2025-04-02 05:59:24", | ||
| 268 | + "checkin_type": "self-service", | ||
| 269 | + "location": null, | ||
| 270 | + "staff_id": null, | ||
| 271 | + "status": "successful", | ||
| 272 | + "notes": "", | ||
| 273 | + "is_late": false | ||
| 274 | + }, | ||
| 275 | + { | ||
| 276 | + "id": "C0022", | ||
| 277 | + "activity_id": "A0001", | ||
| 278 | + "user_id": "U0017", | ||
| 279 | + "registration_id": "R0030", | ||
| 280 | + "checkin_time": "2025-04-02 06:18:33", | ||
| 281 | + "checkin_type": "QR code", | ||
| 282 | + "location": null, | ||
| 283 | + "staff_id": null, | ||
| 284 | + "status": "successful", | ||
| 285 | + "notes": "", | ||
| 286 | + "is_late": false | ||
| 287 | + }, | ||
| 288 | + { | ||
| 289 | + "id": "C0023", | ||
| 290 | + "activity_id": "A0001", | ||
| 291 | + "user_id": "U0038", | ||
| 292 | + "registration_id": "R0031", | ||
| 293 | + "checkin_time": "2025-04-02 06:10:30", | ||
| 294 | + "checkin_type": "manual", | ||
| 295 | + "location": null, | ||
| 296 | + "staff_id": "O0006", | ||
| 297 | + "status": "successful", | ||
| 298 | + "notes": "", | ||
| 299 | + "is_late": false | ||
| 300 | + }, | ||
| 301 | + { | ||
| 302 | + "id": "C0024", | ||
| 303 | + "activity_id": "A0001", | ||
| 304 | + "user_id": "U0030", | ||
| 305 | + "registration_id": "R0032", | ||
| 306 | + "checkin_time": "2025-04-02 06:15:42", | ||
| 307 | + "checkin_type": "manual", | ||
| 308 | + "location": null, | ||
| 309 | + "staff_id": "O0006", | ||
| 310 | + "status": "successful", | ||
| 311 | + "notes": "热情参与讨论", | ||
| 312 | + "is_late": false | ||
| 313 | + }, | ||
| 314 | + { | ||
| 315 | + "id": "C0025", | ||
| 316 | + "activity_id": "A0001", | ||
| 317 | + "user_id": "U0022", | ||
| 318 | + "registration_id": "R0033", | ||
| 319 | + "checkin_time": "2025-04-02 06:39:18", | ||
| 320 | + "checkin_type": "QR code", | ||
| 321 | + "location": null, | ||
| 322 | + "staff_id": null, | ||
| 323 | + "status": "successful", | ||
| 324 | + "notes": "带了书本", | ||
| 325 | + "is_late": false | ||
| 326 | + }, | ||
| 327 | + { | ||
| 328 | + "id": "C0026", | ||
| 329 | + "activity_id": "A0001", | ||
| 330 | + "user_id": "U0014", | ||
| 331 | + "registration_id": "R0034", | ||
| 332 | + "checkin_time": "2025-04-02 06:36:11", | ||
| 333 | + "checkin_type": "self-service", | ||
| 334 | + "location": null, | ||
| 335 | + "staff_id": null, | ||
| 336 | + "status": "successful", | ||
| 337 | + "notes": "提前到达", | ||
| 338 | + "is_late": false | ||
| 339 | + }, | ||
| 340 | + { | ||
| 341 | + "id": "C0027", | ||
| 342 | + "activity_id": "A0001", | ||
| 343 | + "user_id": "U0005", | ||
| 344 | + "registration_id": "R0035", | ||
| 345 | + "checkin_time": "2025-04-02 06:27:14", | ||
| 346 | + "checkin_type": "QR code", | ||
| 347 | + "location": null, | ||
| 348 | + "staff_id": null, | ||
| 349 | + "status": "successful", | ||
| 350 | + "notes": "提前到达", | ||
| 351 | + "is_late": false | ||
| 352 | + }, | ||
| 353 | + { | ||
| 354 | + "id": "C0028", | ||
| 355 | + "activity_id": "A0001", | ||
| 356 | + "user_id": "U0039", | ||
| 357 | + "registration_id": "R0037", | ||
| 358 | + "checkin_time": "2025-04-02 06:43:29", | ||
| 359 | + "checkin_type": "QR code", | ||
| 360 | + "location": null, | ||
| 361 | + "staff_id": null, | ||
| 362 | + "status": "successful", | ||
| 363 | + "notes": "", | ||
| 364 | + "is_late": false | ||
| 365 | + }, | ||
| 366 | + { | ||
| 367 | + "id": "C0029", | ||
| 368 | + "activity_id": "A0002", | ||
| 369 | + "user_id": "U0035", | ||
| 370 | + "registration_id": "R0038", | ||
| 371 | + "checkin_time": "2025-03-24 06:26:56", | ||
| 372 | + "checkin_type": "QR code", | ||
| 373 | + "location": { | ||
| 374 | + "name": "深蓝咖啡馆", | ||
| 375 | + "coordinates": "37.181720,114.507089" | ||
| 376 | + }, | ||
| 377 | + "staff_id": null, | ||
| 378 | + "status": "successful", | ||
| 379 | + "notes": "", | ||
| 380 | + "is_late": false | ||
| 381 | + }, | ||
| 382 | + { | ||
| 383 | + "id": "C0030", | ||
| 384 | + "activity_id": "A0002", | ||
| 385 | + "user_id": "U0031", | ||
| 386 | + "registration_id": "R0039", | ||
| 387 | + "checkin_time": "2025-03-24 06:40:17", | ||
| 388 | + "checkin_type": "QR code", | ||
| 389 | + "location": { | ||
| 390 | + "name": "深蓝咖啡馆", | ||
| 391 | + "coordinates": "38.496785,121.640291" | ||
| 392 | + }, | ||
| 393 | + "staff_id": null, | ||
| 394 | + "status": "successful", | ||
| 395 | + "notes": "", | ||
| 396 | + "is_late": false | ||
| 397 | + }, | ||
| 398 | + { | ||
| 399 | + "id": "C0031", | ||
| 400 | + "activity_id": "A0002", | ||
| 401 | + "user_id": "U0011", | ||
| 402 | + "registration_id": "R0040", | ||
| 403 | + "checkin_time": "2025-03-24 06:06:14", | ||
| 404 | + "checkin_type": "QR code", | ||
| 405 | + "location": { | ||
| 406 | + "name": "深蓝咖啡馆", | ||
| 407 | + "coordinates": "29.197808,115.186227" | ||
| 408 | + }, | ||
| 409 | + "staff_id": null, | ||
| 410 | + "status": "failed", | ||
| 411 | + "notes": "网络连接不稳定", | ||
| 412 | + "is_late": false | ||
| 413 | + }, | ||
| 414 | + { | ||
| 415 | + "id": "C0032", | ||
| 416 | + "activity_id": "A0002", | ||
| 417 | + "user_id": "U0032", | ||
| 418 | + "registration_id": "R0041", | ||
| 419 | + "checkin_time": "2025-03-24 06:17:34", | ||
| 420 | + "checkin_type": "QR code", | ||
| 421 | + "location": { | ||
| 422 | + "name": "深蓝咖啡馆", | ||
| 423 | + "coordinates": "36.369072,107.966159" | ||
| 424 | + }, | ||
| 425 | + "staff_id": null, | ||
| 426 | + "status": "successful", | ||
| 427 | + "notes": "", | ||
| 428 | + "is_late": true | ||
| 429 | + }, | ||
| 430 | + { | ||
| 431 | + "id": "C0033", | ||
| 432 | + "activity_id": "A0002", | ||
| 433 | + "user_id": "U0009", | ||
| 434 | + "registration_id": "R0043", | ||
| 435 | + "checkin_time": "2025-03-24 06:37:51", | ||
| 436 | + "checkin_type": "QR code", | ||
| 437 | + "location": { | ||
| 438 | + "name": "深蓝咖啡馆", | ||
| 439 | + "coordinates": "24.090606,121.419792" | ||
| 440 | + }, | ||
| 441 | + "staff_id": null, | ||
| 442 | + "status": "successful", | ||
| 443 | + "notes": "", | ||
| 444 | + "is_late": true | ||
| 445 | + }, | ||
| 446 | + { | ||
| 447 | + "id": "C0034", | ||
| 448 | + "activity_id": "A0002", | ||
| 449 | + "user_id": "U0018", | ||
| 450 | + "registration_id": "R0044", | ||
| 451 | + "checkin_time": "2025-03-24 06:37:28", | ||
| 452 | + "checkin_type": "QR code", | ||
| 453 | + "location": { | ||
| 454 | + "name": "深蓝咖啡馆", | ||
| 455 | + "coordinates": "24.317278,113.834895" | ||
| 456 | + }, | ||
| 457 | + "staff_id": null, | ||
| 458 | + "status": "successful", | ||
| 459 | + "notes": "", | ||
| 460 | + "is_late": false | ||
| 461 | + }, | ||
| 462 | + { | ||
| 463 | + "id": "C0035", | ||
| 464 | + "activity_id": "A0002", | ||
| 465 | + "user_id": "U0008", | ||
| 466 | + "registration_id": "R0045", | ||
| 467 | + "checkin_time": "2025-03-24 06:06:55", | ||
| 468 | + "checkin_type": "QR code", | ||
| 469 | + "location": { | ||
| 470 | + "name": "深蓝咖啡馆", | ||
| 471 | + "coordinates": "28.173906,120.708227" | ||
| 472 | + }, | ||
| 473 | + "staff_id": null, | ||
| 474 | + "status": "successful", | ||
| 475 | + "notes": "", | ||
| 476 | + "is_late": false | ||
| 477 | + }, | ||
| 478 | + { | ||
| 479 | + "id": "C0036", | ||
| 480 | + "activity_id": "A0002", | ||
| 481 | + "user_id": "U0025", | ||
| 482 | + "registration_id": "R0046", | ||
| 483 | + "checkin_time": "2025-03-24 06:26:03", | ||
| 484 | + "checkin_type": "manual", | ||
| 485 | + "location": { | ||
| 486 | + "name": "深蓝咖啡馆", | ||
| 487 | + "coordinates": "32.612174,103.031492" | ||
| 488 | + }, | ||
| 489 | + "staff_id": "O0003", | ||
| 490 | + "status": "successful", | ||
| 491 | + "notes": "", | ||
| 492 | + "is_late": false | ||
| 493 | + }, | ||
| 494 | + { | ||
| 495 | + "id": "C0037", | ||
| 496 | + "activity_id": "A0002", | ||
| 497 | + "user_id": "U0030", | ||
| 498 | + "registration_id": "R0047", | ||
| 499 | + "checkin_time": "2025-03-24 06:24:16", | ||
| 500 | + "checkin_type": "QR code", | ||
| 501 | + "location": { | ||
| 502 | + "name": "深蓝咖啡馆", | ||
| 503 | + "coordinates": "26.712645,111.630994" | ||
| 504 | + }, | ||
| 505 | + "staff_id": null, | ||
| 506 | + "status": "successful", | ||
| 507 | + "notes": "按时到达", | ||
| 508 | + "is_late": false | ||
| 509 | + }, | ||
| 510 | + { | ||
| 511 | + "id": "C0038", | ||
| 512 | + "activity_id": "A0002", | ||
| 513 | + "user_id": "U0022", | ||
| 514 | + "registration_id": "R0048", | ||
| 515 | + "checkin_time": "2025-03-24 06:12:56", | ||
| 516 | + "checkin_type": "QR code", | ||
| 517 | + "location": { | ||
| 518 | + "name": "深蓝咖啡馆", | ||
| 519 | + "coordinates": "24.159576,109.678518" | ||
| 520 | + }, | ||
| 521 | + "staff_id": null, | ||
| 522 | + "status": "successful", | ||
| 523 | + "notes": "带了书本", | ||
| 524 | + "is_late": false | ||
| 525 | + }, | ||
| 526 | + { | ||
| 527 | + "id": "C0039", | ||
| 528 | + "activity_id": "A0002", | ||
| 529 | + "user_id": "U0026", | ||
| 530 | + "registration_id": "R0049", | ||
| 531 | + "checkin_time": "2025-03-24 06:36:47", | ||
| 532 | + "checkin_type": "QR code", | ||
| 533 | + "location": { | ||
| 534 | + "name": "深蓝咖啡馆", | ||
| 535 | + "coordinates": "23.120311,112.843124" | ||
| 536 | + }, | ||
| 537 | + "staff_id": null, | ||
| 538 | + "status": "successful", | ||
| 539 | + "notes": "", | ||
| 540 | + "is_late": true | ||
| 541 | + }, | ||
| 542 | + { | ||
| 543 | + "id": "C0040", | ||
| 544 | + "activity_id": "A0002", | ||
| 545 | + "user_id": "U0016", | ||
| 546 | + "registration_id": "R0050", | ||
| 547 | + "checkin_time": "2025-03-24 06:08:26", | ||
| 548 | + "checkin_type": "manual", | ||
| 549 | + "location": { | ||
| 550 | + "name": "深蓝咖啡馆", | ||
| 551 | + "coordinates": "39.064207,125.051377" | ||
| 552 | + }, | ||
| 553 | + "staff_id": "O0003", | ||
| 554 | + "status": "successful", | ||
| 555 | + "notes": "", | ||
| 556 | + "is_late": false | ||
| 557 | + }, | ||
| 558 | + { | ||
| 559 | + "id": "C0041", | ||
| 560 | + "activity_id": "A0002", | ||
| 561 | + "user_id": "U0006", | ||
| 562 | + "registration_id": "R0051", | ||
| 563 | + "checkin_time": "2025-03-24 06:38:14", | ||
| 564 | + "checkin_type": "QR code", | ||
| 565 | + "location": { | ||
| 566 | + "name": "深蓝咖啡馆", | ||
| 567 | + "coordinates": "39.771853,103.340475" | ||
| 568 | + }, | ||
| 569 | + "staff_id": null, | ||
| 570 | + "status": "successful", | ||
| 571 | + "notes": "", | ||
| 572 | + "is_late": false | ||
| 573 | + }, | ||
| 574 | + { | ||
| 575 | + "id": "C0042", | ||
| 576 | + "activity_id": "A0002", | ||
| 577 | + "user_id": "U0017", | ||
| 578 | + "registration_id": "R0052", | ||
| 579 | + "checkin_time": "2025-03-24 06:38:41", | ||
| 580 | + "checkin_type": "QR code", | ||
| 581 | + "location": { | ||
| 582 | + "name": "深蓝咖啡馆", | ||
| 583 | + "coordinates": "28.109123,117.999368" | ||
| 584 | + }, | ||
| 585 | + "staff_id": null, | ||
| 586 | + "status": "failed", | ||
| 587 | + "notes": "未携带所需材料", | ||
| 588 | + "is_late": false | ||
| 589 | + }, | ||
| 590 | + { | ||
| 591 | + "id": "C0043", | ||
| 592 | + "activity_id": "A0002", | ||
| 593 | + "user_id": "U0023", | ||
| 594 | + "registration_id": "R0053", | ||
| 595 | + "checkin_time": "2025-03-24 06:28:37", | ||
| 596 | + "checkin_type": "QR code", | ||
| 597 | + "location": { | ||
| 598 | + "name": "深蓝咖啡馆", | ||
| 599 | + "coordinates": "26.399555,107.803150" | ||
| 600 | + }, | ||
| 601 | + "staff_id": null, | ||
| 602 | + "status": "successful", | ||
| 603 | + "notes": "", | ||
| 604 | + "is_late": false | ||
| 605 | + }, | ||
| 606 | + { | ||
| 607 | + "id": "C0044", | ||
| 608 | + "activity_id": "A0002", | ||
| 609 | + "user_id": "U0020", | ||
| 610 | + "registration_id": "R0054", | ||
| 611 | + "checkin_time": "2025-03-24 06:26:01", | ||
| 612 | + "checkin_type": "QR code", | ||
| 613 | + "location": { | ||
| 614 | + "name": "深蓝咖啡馆", | ||
| 615 | + "coordinates": "35.961689,105.194244" | ||
| 616 | + }, | ||
| 617 | + "staff_id": null, | ||
| 618 | + "status": "successful", | ||
| 619 | + "notes": "", | ||
| 620 | + "is_late": false | ||
| 621 | + }, | ||
| 622 | + { | ||
| 623 | + "id": "C0045", | ||
| 624 | + "activity_id": "A0002", | ||
| 625 | + "user_id": "U0002", | ||
| 626 | + "registration_id": "R0055", | ||
| 627 | + "checkin_time": "2025-03-24 06:17:24", | ||
| 628 | + "checkin_type": "QR code", | ||
| 629 | + "location": { | ||
| 630 | + "name": "深蓝咖啡馆", | ||
| 631 | + "coordinates": "38.805465,124.606647" | ||
| 632 | + }, | ||
| 633 | + "staff_id": null, | ||
| 634 | + "status": "successful", | ||
| 635 | + "notes": "", | ||
| 636 | + "is_late": true | ||
| 637 | + }, | ||
| 638 | + { | ||
| 639 | + "id": "C0046", | ||
| 640 | + "activity_id": "A0002", | ||
| 641 | + "user_id": "U0003", | ||
| 642 | + "registration_id": "R0057", | ||
| 643 | + "checkin_time": "2025-03-24 06:23:32", | ||
| 644 | + "checkin_type": "manual", | ||
| 645 | + "location": { | ||
| 646 | + "name": "深蓝咖啡馆", | ||
| 647 | + "coordinates": "26.842865,115.187406" | ||
| 648 | + }, | ||
| 649 | + "staff_id": "O0003", | ||
| 650 | + "status": "successful", | ||
| 651 | + "notes": "", | ||
| 652 | + "is_late": true | ||
| 653 | + }, | ||
| 654 | + { | ||
| 655 | + "id": "C0047", | ||
| 656 | + "activity_id": "A0002", | ||
| 657 | + "user_id": "U0021", | ||
| 658 | + "registration_id": "R0058", | ||
| 659 | + "checkin_time": "2025-03-24 06:01:19", | ||
| 660 | + "checkin_type": "QR code", | ||
| 661 | + "location": { | ||
| 662 | + "name": "深蓝咖啡馆", | ||
| 663 | + "coordinates": "31.048369,122.562894" | ||
| 664 | + }, | ||
| 665 | + "staff_id": null, | ||
| 666 | + "status": "successful", | ||
| 667 | + "notes": "提前到达", | ||
| 668 | + "is_late": false | ||
| 669 | + }, | ||
| 670 | + { | ||
| 671 | + "id": "C0048", | ||
| 672 | + "activity_id": "A0002", | ||
| 673 | + "user_id": "U0024", | ||
| 674 | + "registration_id": "R0059", | ||
| 675 | + "checkin_time": "2025-03-24 06:07:08", | ||
| 676 | + "checkin_type": "QR code", | ||
| 677 | + "location": { | ||
| 678 | + "name": "深蓝咖啡馆", | ||
| 679 | + "coordinates": "36.666997,102.016997" | ||
| 680 | + }, | ||
| 681 | + "staff_id": null, | ||
| 682 | + "status": "successful", | ||
| 683 | + "notes": "", | ||
| 684 | + "is_late": false | ||
| 685 | + }, | ||
| 686 | + { | ||
| 687 | + "id": "C0049", | ||
| 688 | + "activity_id": "A0002", | ||
| 689 | + "user_id": "U0037", | ||
| 690 | + "registration_id": "R0061", | ||
| 691 | + "checkin_time": "2025-03-24 06:39:21", | ||
| 692 | + "checkin_type": "QR code", | ||
| 693 | + "location": { | ||
| 694 | + "name": "深蓝咖啡馆", | ||
| 695 | + "coordinates": "26.657286,112.659843" | ||
| 696 | + }, | ||
| 697 | + "staff_id": null, | ||
| 698 | + "status": "successful", | ||
| 699 | + "notes": "", | ||
| 700 | + "is_late": true | ||
| 701 | + }, | ||
| 702 | + { | ||
| 703 | + "id": "C0050", | ||
| 704 | + "activity_id": "A0002", | ||
| 705 | + "user_id": "U0012", | ||
| 706 | + "registration_id": "R0063", | ||
| 707 | + "checkin_time": "2025-03-24 06:24:17", | ||
| 708 | + "checkin_type": "QR code", | ||
| 709 | + "location": { | ||
| 710 | + "name": "深蓝咖啡馆", | ||
| 711 | + "coordinates": "39.694284,109.014524" | ||
| 712 | + }, | ||
| 713 | + "staff_id": null, | ||
| 714 | + "status": "successful", | ||
| 715 | + "notes": "提前到达", | ||
| 716 | + "is_late": true | ||
| 717 | + }, | ||
| 718 | + { | ||
| 719 | + "id": "C0051", | ||
| 720 | + "activity_id": "A0002", | ||
| 721 | + "user_id": "U0014", | ||
| 722 | + "registration_id": "R0064", | ||
| 723 | + "checkin_time": "2025-03-24 06:19:52", | ||
| 724 | + "checkin_type": "manual", | ||
| 725 | + "location": { | ||
| 726 | + "name": "深蓝咖啡馆", | ||
| 727 | + "coordinates": "39.330172,105.342768" | ||
| 728 | + }, | ||
| 729 | + "staff_id": "O0003", | ||
| 730 | + "status": "successful", | ||
| 731 | + "notes": "", | ||
| 732 | + "is_late": false | ||
| 733 | + }, | ||
| 734 | + { | ||
| 735 | + "id": "C0052", | ||
| 736 | + "activity_id": "A0002", | ||
| 737 | + "user_id": "U0010", | ||
| 738 | + "registration_id": "R0065", | ||
| 739 | + "checkin_time": "2025-03-24 06:51:43", | ||
| 740 | + "checkin_type": "QR code", | ||
| 741 | + "location": { | ||
| 742 | + "name": "深蓝咖啡馆", | ||
| 743 | + "coordinates": "27.822307,110.880438" | ||
| 744 | + }, | ||
| 745 | + "staff_id": null, | ||
| 746 | + "status": "successful", | ||
| 747 | + "notes": "", | ||
| 748 | + "is_late": true | ||
| 749 | + }, | ||
| 750 | + { | ||
| 751 | + "id": "C0053", | ||
| 752 | + "activity_id": "A0002", | ||
| 753 | + "user_id": "U0034", | ||
| 754 | + "registration_id": "R0066", | ||
| 755 | + "checkin_time": "2025-03-24 06:24:07", | ||
| 756 | + "checkin_type": "QR code", | ||
| 757 | + "location": { | ||
| 758 | + "name": "深蓝咖啡馆", | ||
| 759 | + "coordinates": "37.010299,118.129043" | ||
| 760 | + }, | ||
| 761 | + "staff_id": null, | ||
| 762 | + "status": "successful", | ||
| 763 | + "notes": "", | ||
| 764 | + "is_late": false | ||
| 765 | + }, | ||
| 766 | + { | ||
| 767 | + "id": "C0054", | ||
| 768 | + "activity_id": "A0002", | ||
| 769 | + "user_id": "U0039", | ||
| 770 | + "registration_id": "R0067", | ||
| 771 | + "checkin_time": "2025-03-24 06:39:58", | ||
| 772 | + "checkin_type": "QR code", | ||
| 773 | + "location": { | ||
| 774 | + "name": "深蓝咖啡馆", | ||
| 775 | + "coordinates": "24.617110,119.003828" | ||
| 776 | + }, | ||
| 777 | + "staff_id": null, | ||
| 778 | + "status": "successful", | ||
| 779 | + "notes": "热情参与讨论", | ||
| 780 | + "is_late": false | ||
| 781 | + }, | ||
| 782 | + { | ||
| 783 | + "id": "C0055", | ||
| 784 | + "activity_id": "A0002", | ||
| 785 | + "user_id": "U0001", | ||
| 786 | + "registration_id": "R0068", | ||
| 787 | + "checkin_time": "2025-03-24 06:35:33", | ||
| 788 | + "checkin_type": "self-service", | ||
| 789 | + "location": { | ||
| 790 | + "name": "深蓝咖啡馆", | ||
| 791 | + "coordinates": "32.183967,110.892548" | ||
| 792 | + }, | ||
| 793 | + "staff_id": null, | ||
| 794 | + "status": "successful", | ||
| 795 | + "notes": "准备充分", | ||
| 796 | + "is_late": true | ||
| 797 | + }, | ||
| 798 | + { | ||
| 799 | + "id": "C0056", | ||
| 800 | + "activity_id": "A0002", | ||
| 801 | + "user_id": "U0028", | ||
| 802 | + "registration_id": "R0069", | ||
| 803 | + "checkin_time": "2025-03-24 06:22:47", | ||
| 804 | + "checkin_type": "self-service", | ||
| 805 | + "location": { | ||
| 806 | + "name": "深蓝咖啡馆", | ||
| 807 | + "coordinates": "37.102393,104.723842" | ||
| 808 | + }, | ||
| 809 | + "staff_id": null, | ||
| 810 | + "status": "successful", | ||
| 811 | + "notes": "", | ||
| 812 | + "is_late": false | ||
| 813 | + }, | ||
| 814 | + { | ||
| 815 | + "id": "C0057", | ||
| 816 | + "activity_id": "A0002", | ||
| 817 | + "user_id": "U0027", | ||
| 818 | + "registration_id": "R0070", | ||
| 819 | + "checkin_time": "2025-03-24 06:22:44", | ||
| 820 | + "checkin_type": "manual", | ||
| 821 | + "location": { | ||
| 822 | + "name": "深蓝咖啡馆", | ||
| 823 | + "coordinates": "35.022102,120.845595" | ||
| 824 | + }, | ||
| 825 | + "staff_id": "O0003", | ||
| 826 | + "status": "successful", | ||
| 827 | + "notes": "", | ||
| 828 | + "is_late": true | ||
| 829 | + }, | ||
| 830 | + { | ||
| 831 | + "id": "C0058", | ||
| 832 | + "activity_id": "A0002", | ||
| 833 | + "user_id": "U0013", | ||
| 834 | + "registration_id": "R0071", | ||
| 835 | + "checkin_time": "2025-03-24 06:29:54", | ||
| 836 | + "checkin_type": "QR code", | ||
| 837 | + "location": { | ||
| 838 | + "name": "深蓝咖啡馆", | ||
| 839 | + "coordinates": "27.520250,106.998565" | ||
| 840 | + }, | ||
| 841 | + "staff_id": null, | ||
| 842 | + "status": "successful", | ||
| 843 | + "notes": "", | ||
| 844 | + "is_late": false | ||
| 845 | + }, | ||
| 846 | + { | ||
| 847 | + "id": "C0059", | ||
| 848 | + "activity_id": "A0002", | ||
| 849 | + "user_id": "U0036", | ||
| 850 | + "registration_id": "R0072", | ||
| 851 | + "checkin_time": "2025-03-24 06:15:52", | ||
| 852 | + "checkin_type": "QR code", | ||
| 853 | + "location": { | ||
| 854 | + "name": "深蓝咖啡馆", | ||
| 855 | + "coordinates": "22.586642,106.806636" | ||
| 856 | + }, | ||
| 857 | + "staff_id": null, | ||
| 858 | + "status": "successful", | ||
| 859 | + "notes": "提前到达", | ||
| 860 | + "is_late": false | ||
| 861 | + }, | ||
| 862 | + { | ||
| 863 | + "id": "C0060", | ||
| 864 | + "activity_id": "A0002", | ||
| 865 | + "user_id": "U0004", | ||
| 866 | + "registration_id": "R0073", | ||
| 867 | + "checkin_time": "2025-03-24 06:14:19", | ||
| 868 | + "checkin_type": "QR code", | ||
| 869 | + "location": { | ||
| 870 | + "name": "深蓝咖啡馆", | ||
| 871 | + "coordinates": "34.054279,106.738680" | ||
| 872 | + }, | ||
| 873 | + "staff_id": null, | ||
| 874 | + "status": "successful", | ||
| 875 | + "notes": "按时到达", | ||
| 876 | + "is_late": false | ||
| 877 | + }, | ||
| 878 | + { | ||
| 879 | + "id": "C0061", | ||
| 880 | + "activity_id": "A0002", | ||
| 881 | + "user_id": "U0040", | ||
| 882 | + "registration_id": "R0074", | ||
| 883 | + "checkin_time": "2025-03-24 06:26:57", | ||
| 884 | + "checkin_type": "manual", | ||
| 885 | + "location": { | ||
| 886 | + "name": "深蓝咖啡馆", | ||
| 887 | + "coordinates": "35.010409,123.112389" | ||
| 888 | + }, | ||
| 889 | + "staff_id": "O0003", | ||
| 890 | + "status": "successful", | ||
| 891 | + "notes": "", | ||
| 892 | + "is_late": false | ||
| 893 | + }, | ||
| 894 | + { | ||
| 895 | + "id": "C0062", | ||
| 896 | + "activity_id": "A0002", | ||
| 897 | + "user_id": "U0005", | ||
| 898 | + "registration_id": "R0075", | ||
| 899 | + "checkin_time": "2025-03-24 06:34:07", | ||
| 900 | + "checkin_type": "QR code", | ||
| 901 | + "location": { | ||
| 902 | + "name": "深蓝咖啡馆", | ||
| 903 | + "coordinates": "29.606431,116.433917" | ||
| 904 | + }, | ||
| 905 | + "staff_id": null, | ||
| 906 | + "status": "successful", | ||
| 907 | + "notes": "", | ||
| 908 | + "is_late": false | ||
| 909 | + }, | ||
| 910 | + { | ||
| 911 | + "id": "C0063", | ||
| 912 | + "activity_id": "A0002", | ||
| 913 | + "user_id": "U0033", | ||
| 914 | + "registration_id": "R0077", | ||
| 915 | + "checkin_time": "2025-03-24 06:27:57", | ||
| 916 | + "checkin_type": "QR code", | ||
| 917 | + "location": { | ||
| 918 | + "name": "深蓝咖啡馆", | ||
| 919 | + "coordinates": "33.496844,120.165656" | ||
| 920 | + }, | ||
| 921 | + "staff_id": null, | ||
| 922 | + "status": "successful", | ||
| 923 | + "notes": "", | ||
| 924 | + "is_late": false | ||
| 925 | + }, | ||
| 926 | + { | ||
| 927 | + "id": "C0064", | ||
| 928 | + "activity_id": "A0007", | ||
| 929 | + "user_id": "U0031", | ||
| 930 | + "registration_id": "R0101", | ||
| 931 | + "checkin_time": "2025-04-03 05:12:17", | ||
| 932 | + "checkin_type": "QR code", | ||
| 933 | + "location": { | ||
| 934 | + "name": "熊猫书房", | ||
| 935 | + "coordinates": "37.519897,120.666728" | ||
| 936 | + }, | ||
| 937 | + "staff_id": null, | ||
| 938 | + "status": "successful", | ||
| 939 | + "notes": "准备充分", | ||
| 940 | + "is_late": false | ||
| 941 | + }, | ||
| 942 | + { | ||
| 943 | + "id": "C0065", | ||
| 944 | + "activity_id": "A0007", | ||
| 945 | + "user_id": "U0039", | ||
| 946 | + "registration_id": "R0102", | ||
| 947 | + "checkin_time": "2025-04-03 05:43:42", | ||
| 948 | + "checkin_type": "QR code", | ||
| 949 | + "location": { | ||
| 950 | + "name": "熊猫书房", | ||
| 951 | + "coordinates": "23.325053,124.389998" | ||
| 952 | + }, | ||
| 953 | + "staff_id": null, | ||
| 954 | + "status": "successful", | ||
| 955 | + "notes": "", | ||
| 956 | + "is_late": false | ||
| 957 | + }, | ||
| 958 | + { | ||
| 959 | + "id": "C0066", | ||
| 960 | + "activity_id": "A0007", | ||
| 961 | + "user_id": "U0040", | ||
| 962 | + "registration_id": "R0103", | ||
| 963 | + "checkin_time": "2025-04-03 05:36:39", | ||
| 964 | + "checkin_type": "manual", | ||
| 965 | + "location": { | ||
| 966 | + "name": "熊猫书房", | ||
| 967 | + "coordinates": "29.006041,121.944115" | ||
| 968 | + }, | ||
| 969 | + "staff_id": "O0006", | ||
| 970 | + "status": "successful", | ||
| 971 | + "notes": "", | ||
| 972 | + "is_late": false | ||
| 973 | + }, | ||
| 974 | + { | ||
| 975 | + "id": "C0067", | ||
| 976 | + "activity_id": "A0007", | ||
| 977 | + "user_id": "U0022", | ||
| 978 | + "registration_id": "R0104", | ||
| 979 | + "checkin_time": "2025-04-03 05:27:17", | ||
| 980 | + "checkin_type": "QR code", | ||
| 981 | + "location": { | ||
| 982 | + "name": "熊猫书房", | ||
| 983 | + "coordinates": "23.882683,105.402504" | ||
| 984 | + }, | ||
| 985 | + "staff_id": null, | ||
| 986 | + "status": "successful", | ||
| 987 | + "notes": "准备充分", | ||
| 988 | + "is_late": false | ||
| 989 | + }, | ||
| 990 | + { | ||
| 991 | + "id": "C0068", | ||
| 992 | + "activity_id": "A0007", | ||
| 993 | + "user_id": "U0015", | ||
| 994 | + "registration_id": "R0106", | ||
| 995 | + "checkin_time": "2025-04-03 05:27:01", | ||
| 996 | + "checkin_type": "QR code", | ||
| 997 | + "location": { | ||
| 998 | + "name": "熊猫书房", | ||
| 999 | + "coordinates": "37.561985,116.624272" | ||
| 1000 | + }, | ||
| 1001 | + "staff_id": null, | ||
| 1002 | + "status": "successful", | ||
| 1003 | + "notes": "", | ||
| 1004 | + "is_late": false | ||
| 1005 | + }, | ||
| 1006 | + { | ||
| 1007 | + "id": "C0069", | ||
| 1008 | + "activity_id": "A0007", | ||
| 1009 | + "user_id": "U0020", | ||
| 1010 | + "registration_id": "R0107", | ||
| 1011 | + "checkin_time": "2025-04-03 05:08:09", | ||
| 1012 | + "checkin_type": "QR code", | ||
| 1013 | + "location": { | ||
| 1014 | + "name": "熊猫书房", | ||
| 1015 | + "coordinates": "36.575256,121.636347" | ||
| 1016 | + }, | ||
| 1017 | + "staff_id": null, | ||
| 1018 | + "status": "successful", | ||
| 1019 | + "notes": "", | ||
| 1020 | + "is_late": false | ||
| 1021 | + }, | ||
| 1022 | + { | ||
| 1023 | + "id": "C0070", | ||
| 1024 | + "activity_id": "A0007", | ||
| 1025 | + "user_id": "U0038", | ||
| 1026 | + "registration_id": "R0108", | ||
| 1027 | + "checkin_time": "2025-04-03 05:21:29", | ||
| 1028 | + "checkin_type": "self-service", | ||
| 1029 | + "location": { | ||
| 1030 | + "name": "熊猫书房", | ||
| 1031 | + "coordinates": "27.958669,101.467384" | ||
| 1032 | + }, | ||
| 1033 | + "staff_id": null, | ||
| 1034 | + "status": "successful", | ||
| 1035 | + "notes": "", | ||
| 1036 | + "is_late": false | ||
| 1037 | + }, | ||
| 1038 | + { | ||
| 1039 | + "id": "C0071", | ||
| 1040 | + "activity_id": "A0007", | ||
| 1041 | + "user_id": "U0014", | ||
| 1042 | + "registration_id": "R0109", | ||
| 1043 | + "checkin_time": "2025-04-03 05:22:20", | ||
| 1044 | + "checkin_type": "self-service", | ||
| 1045 | + "location": { | ||
| 1046 | + "name": "熊猫书房", | ||
| 1047 | + "coordinates": "37.434346,114.067180" | ||
| 1048 | + }, | ||
| 1049 | + "staff_id": null, | ||
| 1050 | + "status": "successful", | ||
| 1051 | + "notes": "", | ||
| 1052 | + "is_late": false | ||
| 1053 | + }, | ||
| 1054 | + { | ||
| 1055 | + "id": "C0072", | ||
| 1056 | + "activity_id": "A0007", | ||
| 1057 | + "user_id": "U0011", | ||
| 1058 | + "registration_id": "R0110", | ||
| 1059 | + "checkin_time": "2025-04-03 05:08:27", | ||
| 1060 | + "checkin_type": "manual", | ||
| 1061 | + "location": { | ||
| 1062 | + "name": "熊猫书房", | ||
| 1063 | + "coordinates": "35.202228,124.219237" | ||
| 1064 | + }, | ||
| 1065 | + "staff_id": "O0006", | ||
| 1066 | + "status": "successful", | ||
| 1067 | + "notes": "热情参与讨论", | ||
| 1068 | + "is_late": false | ||
| 1069 | + }, | ||
| 1070 | + { | ||
| 1071 | + "id": "C0073", | ||
| 1072 | + "activity_id": "A0007", | ||
| 1073 | + "user_id": "U0034", | ||
| 1074 | + "registration_id": "R0111", | ||
| 1075 | + "checkin_time": "2025-04-03 05:35:07", | ||
| 1076 | + "checkin_type": "QR code", | ||
| 1077 | + "location": { | ||
| 1078 | + "name": "熊猫书房", | ||
| 1079 | + "coordinates": "30.140811,113.054793" | ||
| 1080 | + }, | ||
| 1081 | + "staff_id": null, | ||
| 1082 | + "status": "successful", | ||
| 1083 | + "notes": "", | ||
| 1084 | + "is_late": false | ||
| 1085 | + }, | ||
| 1086 | + { | ||
| 1087 | + "id": "C0074", | ||
| 1088 | + "activity_id": "A0007", | ||
| 1089 | + "user_id": "U0010", | ||
| 1090 | + "registration_id": "R0112", | ||
| 1091 | + "checkin_time": "2025-04-03 05:18:04", | ||
| 1092 | + "checkin_type": "QR code", | ||
| 1093 | + "location": { | ||
| 1094 | + "name": "熊猫书房", | ||
| 1095 | + "coordinates": "26.209453,123.344462" | ||
| 1096 | + }, | ||
| 1097 | + "staff_id": null, | ||
| 1098 | + "status": "failed", | ||
| 1099 | + "notes": "未携带所需材料", | ||
| 1100 | + "is_late": false | ||
| 1101 | + }, | ||
| 1102 | + { | ||
| 1103 | + "id": "C0075", | ||
| 1104 | + "activity_id": "A0007", | ||
| 1105 | + "user_id": "U0017", | ||
| 1106 | + "registration_id": "R0113", | ||
| 1107 | + "checkin_time": "2025-04-03 05:30:44", | ||
| 1108 | + "checkin_type": "QR code", | ||
| 1109 | + "location": { | ||
| 1110 | + "name": "熊猫书房", | ||
| 1111 | + "coordinates": "39.520586,111.230061" | ||
| 1112 | + }, | ||
| 1113 | + "staff_id": null, | ||
| 1114 | + "status": "successful", | ||
| 1115 | + "notes": "", | ||
| 1116 | + "is_late": false | ||
| 1117 | + }, | ||
| 1118 | + { | ||
| 1119 | + "id": "C0076", | ||
| 1120 | + "activity_id": "A0007", | ||
| 1121 | + "user_id": "U0006", | ||
| 1122 | + "registration_id": "R0115", | ||
| 1123 | + "checkin_time": "2025-04-03 05:35:32", | ||
| 1124 | + "checkin_type": "QR code", | ||
| 1125 | + "location": { | ||
| 1126 | + "name": "熊猫书房", | ||
| 1127 | + "coordinates": "22.854964,103.303204" | ||
| 1128 | + }, | ||
| 1129 | + "staff_id": null, | ||
| 1130 | + "status": "successful", | ||
| 1131 | + "notes": "按时到达", | ||
| 1132 | + "is_late": false | ||
| 1133 | + }, | ||
| 1134 | + { | ||
| 1135 | + "id": "C0077", | ||
| 1136 | + "activity_id": "A0007", | ||
| 1137 | + "user_id": "U0030", | ||
| 1138 | + "registration_id": "R0116", | ||
| 1139 | + "checkin_time": "2025-04-03 05:22:00", | ||
| 1140 | + "checkin_type": "self-service", | ||
| 1141 | + "location": { | ||
| 1142 | + "name": "熊猫书房", | ||
| 1143 | + "coordinates": "33.919211,117.039781" | ||
| 1144 | + }, | ||
| 1145 | + "staff_id": null, | ||
| 1146 | + "status": "successful", | ||
| 1147 | + "notes": "", | ||
| 1148 | + "is_late": false | ||
| 1149 | + }, | ||
| 1150 | + { | ||
| 1151 | + "id": "C0078", | ||
| 1152 | + "activity_id": "A0007", | ||
| 1153 | + "user_id": "U0036", | ||
| 1154 | + "registration_id": "R0117", | ||
| 1155 | + "checkin_time": "2025-04-03 05:14:00", | ||
| 1156 | + "checkin_type": "QR code", | ||
| 1157 | + "location": { | ||
| 1158 | + "name": "熊猫书房", | ||
| 1159 | + "coordinates": "22.389473,121.064134" | ||
| 1160 | + }, | ||
| 1161 | + "staff_id": null, | ||
| 1162 | + "status": "successful", | ||
| 1163 | + "notes": "", | ||
| 1164 | + "is_late": false | ||
| 1165 | + }, | ||
| 1166 | + { | ||
| 1167 | + "id": "C0079", | ||
| 1168 | + "activity_id": "A0007", | ||
| 1169 | + "user_id": "U0025", | ||
| 1170 | + "registration_id": "R0118", | ||
| 1171 | + "checkin_time": "2025-04-03 05:34:15", | ||
| 1172 | + "checkin_type": "manual", | ||
| 1173 | + "location": { | ||
| 1174 | + "name": "熊猫书房", | ||
| 1175 | + "coordinates": "23.279344,121.133817" | ||
| 1176 | + }, | ||
| 1177 | + "staff_id": "O0006", | ||
| 1178 | + "status": "successful", | ||
| 1179 | + "notes": "准备充分", | ||
| 1180 | + "is_late": false | ||
| 1181 | + }, | ||
| 1182 | + { | ||
| 1183 | + "id": "C0080", | ||
| 1184 | + "activity_id": "A0007", | ||
| 1185 | + "user_id": "U0008", | ||
| 1186 | + "registration_id": "R0120", | ||
| 1187 | + "checkin_time": "2025-04-03 05:29:55", | ||
| 1188 | + "checkin_type": "self-service", | ||
| 1189 | + "location": { | ||
| 1190 | + "name": "熊猫书房", | ||
| 1191 | + "coordinates": "26.897514,110.258579" | ||
| 1192 | + }, | ||
| 1193 | + "staff_id": null, | ||
| 1194 | + "status": "failed", | ||
| 1195 | + "notes": "未携带所需材料", | ||
| 1196 | + "is_late": false | ||
| 1197 | + }, | ||
| 1198 | + { | ||
| 1199 | + "id": "C0081", | ||
| 1200 | + "activity_id": "A0007", | ||
| 1201 | + "user_id": "U0009", | ||
| 1202 | + "registration_id": "R0122", | ||
| 1203 | + "checkin_time": "2025-04-03 05:19:05", | ||
| 1204 | + "checkin_type": "manual", | ||
| 1205 | + "location": { | ||
| 1206 | + "name": "熊猫书房", | ||
| 1207 | + "coordinates": "37.908705,105.332370" | ||
| 1208 | + }, | ||
| 1209 | + "staff_id": "O0006", | ||
| 1210 | + "status": "successful", | ||
| 1211 | + "notes": "", | ||
| 1212 | + "is_late": false | ||
| 1213 | + }, | ||
| 1214 | + { | ||
| 1215 | + "id": "C0082", | ||
| 1216 | + "activity_id": "A0007", | ||
| 1217 | + "user_id": "U0033", | ||
| 1218 | + "registration_id": "R0123", | ||
| 1219 | + "checkin_time": "2025-04-03 05:06:33", | ||
| 1220 | + "checkin_type": "QR code", | ||
| 1221 | + "location": { | ||
| 1222 | + "name": "熊猫书房", | ||
| 1223 | + "coordinates": "27.330438,106.622710" | ||
| 1224 | + }, | ||
| 1225 | + "staff_id": null, | ||
| 1226 | + "status": "successful", | ||
| 1227 | + "notes": "", | ||
| 1228 | + "is_late": false | ||
| 1229 | + }, | ||
| 1230 | + { | ||
| 1231 | + "id": "C0083", | ||
| 1232 | + "activity_id": "A0007", | ||
| 1233 | + "user_id": "U0028", | ||
| 1234 | + "registration_id": "R0124", | ||
| 1235 | + "checkin_time": "2025-04-03 05:06:45", | ||
| 1236 | + "checkin_type": "QR code", | ||
| 1237 | + "location": { | ||
| 1238 | + "name": "熊猫书房", | ||
| 1239 | + "coordinates": "22.012082,114.991471" | ||
| 1240 | + }, | ||
| 1241 | + "staff_id": null, | ||
| 1242 | + "status": "successful", | ||
| 1243 | + "notes": "", | ||
| 1244 | + "is_late": false | ||
| 1245 | + }, | ||
| 1246 | + { | ||
| 1247 | + "id": "C0084", | ||
| 1248 | + "activity_id": "A0007", | ||
| 1249 | + "user_id": "U0035", | ||
| 1250 | + "registration_id": "R0125", | ||
| 1251 | + "checkin_time": "2025-04-03 05:24:04", | ||
| 1252 | + "checkin_type": "QR code", | ||
| 1253 | + "location": { | ||
| 1254 | + "name": "熊猫书房", | ||
| 1255 | + "coordinates": "36.148959,100.254513" | ||
| 1256 | + }, | ||
| 1257 | + "staff_id": null, | ||
| 1258 | + "status": "successful", | ||
| 1259 | + "notes": "提前到达", | ||
| 1260 | + "is_late": false | ||
| 1261 | + }, | ||
| 1262 | + { | ||
| 1263 | + "id": "C0085", | ||
| 1264 | + "activity_id": "A0007", | ||
| 1265 | + "user_id": "U0032", | ||
| 1266 | + "registration_id": "R0127", | ||
| 1267 | + "checkin_time": "2025-04-03 05:25:34", | ||
| 1268 | + "checkin_type": "QR code", | ||
| 1269 | + "location": { | ||
| 1270 | + "name": "熊猫书房", | ||
| 1271 | + "coordinates": "26.064327,114.415219" | ||
| 1272 | + }, | ||
| 1273 | + "staff_id": null, | ||
| 1274 | + "status": "successful", | ||
| 1275 | + "notes": "", | ||
| 1276 | + "is_late": false | ||
| 1277 | + }, | ||
| 1278 | + { | ||
| 1279 | + "id": "C0086", | ||
| 1280 | + "activity_id": "A0007", | ||
| 1281 | + "user_id": "U0021", | ||
| 1282 | + "registration_id": "R0129", | ||
| 1283 | + "checkin_time": "2025-04-03 05:39:03", | ||
| 1284 | + "checkin_type": "manual", | ||
| 1285 | + "location": { | ||
| 1286 | + "name": "熊猫书房", | ||
| 1287 | + "coordinates": "32.406524,103.926679" | ||
| 1288 | + }, | ||
| 1289 | + "staff_id": "O0006", | ||
| 1290 | + "status": "successful", | ||
| 1291 | + "notes": "", | ||
| 1292 | + "is_late": false | ||
| 1293 | + }, | ||
| 1294 | + { | ||
| 1295 | + "id": "C0087", | ||
| 1296 | + "activity_id": "A0007", | ||
| 1297 | + "user_id": "U0002", | ||
| 1298 | + "registration_id": "R0130", | ||
| 1299 | + "checkin_time": "2025-04-03 05:16:57", | ||
| 1300 | + "checkin_type": "self-service", | ||
| 1301 | + "location": { | ||
| 1302 | + "name": "熊猫书房", | ||
| 1303 | + "coordinates": "34.129245,115.222974" | ||
| 1304 | + }, | ||
| 1305 | + "staff_id": null, | ||
| 1306 | + "status": "successful", | ||
| 1307 | + "notes": "带了书本", | ||
| 1308 | + "is_late": false | ||
| 1309 | + }, | ||
| 1310 | + { | ||
| 1311 | + "id": "C0088", | ||
| 1312 | + "activity_id": "A0007", | ||
| 1313 | + "user_id": "U0003", | ||
| 1314 | + "registration_id": "R0131", | ||
| 1315 | + "checkin_time": "2025-04-03 05:15:34", | ||
| 1316 | + "checkin_type": "QR code", | ||
| 1317 | + "location": { | ||
| 1318 | + "name": "熊猫书房", | ||
| 1319 | + "coordinates": "22.591087,120.597131" | ||
| 1320 | + }, | ||
| 1321 | + "staff_id": null, | ||
| 1322 | + "status": "successful", | ||
| 1323 | + "notes": "", | ||
| 1324 | + "is_late": false | ||
| 1325 | + }, | ||
| 1326 | + { | ||
| 1327 | + "id": "C0089", | ||
| 1328 | + "activity_id": "A0007", | ||
| 1329 | + "user_id": "U0019", | ||
| 1330 | + "registration_id": "R0132", | ||
| 1331 | + "checkin_time": "2025-04-03 05:50:38", | ||
| 1332 | + "checkin_type": "QR code", | ||
| 1333 | + "location": { | ||
| 1334 | + "name": "熊猫书房", | ||
| 1335 | + "coordinates": "36.712114,101.658613" | ||
| 1336 | + }, | ||
| 1337 | + "staff_id": null, | ||
| 1338 | + "status": "successful", | ||
| 1339 | + "notes": "", | ||
| 1340 | + "is_late": true | ||
| 1341 | + }, | ||
| 1342 | + { | ||
| 1343 | + "id": "C0090", | ||
| 1344 | + "activity_id": "A0008", | ||
| 1345 | + "user_id": "U0003", | ||
| 1346 | + "registration_id": "R0135", | ||
| 1347 | + "checkin_time": "2025-04-16 05:25:35", | ||
| 1348 | + "checkin_type": "self-service", | ||
| 1349 | + "location": { | ||
| 1350 | + "name": "紫金读书会", | ||
| 1351 | + "coordinates": "33.547392,111.581963" | ||
| 1352 | + }, | ||
| 1353 | + "staff_id": null, | ||
| 1354 | + "status": "successful", | ||
| 1355 | + "notes": "", | ||
| 1356 | + "is_late": false | ||
| 1357 | + }, | ||
| 1358 | + { | ||
| 1359 | + "id": "C0091", | ||
| 1360 | + "activity_id": "A0008", | ||
| 1361 | + "user_id": "U0031", | ||
| 1362 | + "registration_id": "R0136", | ||
| 1363 | + "checkin_time": "2025-04-16 05:32:36", | ||
| 1364 | + "checkin_type": "QR code", | ||
| 1365 | + "location": { | ||
| 1366 | + "name": "紫金读书会", | ||
| 1367 | + "coordinates": "26.534463,122.247619" | ||
| 1368 | + }, | ||
| 1369 | + "staff_id": null, | ||
| 1370 | + "status": "successful", | ||
| 1371 | + "notes": "带了书本", | ||
| 1372 | + "is_late": false | ||
| 1373 | + }, | ||
| 1374 | + { | ||
| 1375 | + "id": "C0092", | ||
| 1376 | + "activity_id": "A0008", | ||
| 1377 | + "user_id": "U0025", | ||
| 1378 | + "registration_id": "R0137", | ||
| 1379 | + "checkin_time": "2025-04-16 05:30:42", | ||
| 1380 | + "checkin_type": "QR code", | ||
| 1381 | + "location": { | ||
| 1382 | + "name": "紫金读书会", | ||
| 1383 | + "coordinates": "37.697400,124.784329" | ||
| 1384 | + }, | ||
| 1385 | + "staff_id": null, | ||
| 1386 | + "status": "successful", | ||
| 1387 | + "notes": "", | ||
| 1388 | + "is_late": false | ||
| 1389 | + }, | ||
| 1390 | + { | ||
| 1391 | + "id": "C0093", | ||
| 1392 | + "activity_id": "A0008", | ||
| 1393 | + "user_id": "U0010", | ||
| 1394 | + "registration_id": "R0139", | ||
| 1395 | + "checkin_time": "2025-04-16 05:52:05", | ||
| 1396 | + "checkin_type": "QR code", | ||
| 1397 | + "location": { | ||
| 1398 | + "name": "紫金读书会", | ||
| 1399 | + "coordinates": "37.840360,125.457487" | ||
| 1400 | + }, | ||
| 1401 | + "staff_id": null, | ||
| 1402 | + "status": "successful", | ||
| 1403 | + "notes": "", | ||
| 1404 | + "is_late": false | ||
| 1405 | + }, | ||
| 1406 | + { | ||
| 1407 | + "id": "C0094", | ||
| 1408 | + "activity_id": "A0008", | ||
| 1409 | + "user_id": "U0033", | ||
| 1410 | + "registration_id": "R0140", | ||
| 1411 | + "checkin_time": "2025-04-16 05:57:41", | ||
| 1412 | + "checkin_type": "self-service", | ||
| 1413 | + "location": { | ||
| 1414 | + "name": "紫金读书会", | ||
| 1415 | + "coordinates": "26.522240,113.936005" | ||
| 1416 | + }, | ||
| 1417 | + "staff_id": null, | ||
| 1418 | + "status": "successful", | ||
| 1419 | + "notes": "", | ||
| 1420 | + "is_late": false | ||
| 1421 | + }, | ||
| 1422 | + { | ||
| 1423 | + "id": "C0095", | ||
| 1424 | + "activity_id": "A0008", | ||
| 1425 | + "user_id": "U0038", | ||
| 1426 | + "registration_id": "R0143", | ||
| 1427 | + "checkin_time": "2025-04-16 05:34:49", | ||
| 1428 | + "checkin_type": "QR code", | ||
| 1429 | + "location": { | ||
| 1430 | + "name": "紫金读书会", | ||
| 1431 | + "coordinates": "32.237890,101.465566" | ||
| 1432 | + }, | ||
| 1433 | + "staff_id": null, | ||
| 1434 | + "status": "successful", | ||
| 1435 | + "notes": "", | ||
| 1436 | + "is_late": false | ||
| 1437 | + }, | ||
| 1438 | + { | ||
| 1439 | + "id": "C0096", | ||
| 1440 | + "activity_id": "A0008", | ||
| 1441 | + "user_id": "U0027", | ||
| 1442 | + "registration_id": "R0145", | ||
| 1443 | + "checkin_time": "2025-04-16 05:32:21", | ||
| 1444 | + "checkin_type": "QR code", | ||
| 1445 | + "location": { | ||
| 1446 | + "name": "紫金读书会", | ||
| 1447 | + "coordinates": "26.943107,117.949832" | ||
| 1448 | + }, | ||
| 1449 | + "staff_id": null, | ||
| 1450 | + "status": "successful", | ||
| 1451 | + "notes": "提前到达", | ||
| 1452 | + "is_late": true | ||
| 1453 | + }, | ||
| 1454 | + { | ||
| 1455 | + "id": "C0097", | ||
| 1456 | + "activity_id": "A0008", | ||
| 1457 | + "user_id": "U0030", | ||
| 1458 | + "registration_id": "R0146", | ||
| 1459 | + "checkin_time": "2025-04-16 05:24:26", | ||
| 1460 | + "checkin_type": "QR code", | ||
| 1461 | + "location": { | ||
| 1462 | + "name": "紫金读书会", | ||
| 1463 | + "coordinates": "26.658257,117.440716" | ||
| 1464 | + }, | ||
| 1465 | + "staff_id": null, | ||
| 1466 | + "status": "successful", | ||
| 1467 | + "notes": "", | ||
| 1468 | + "is_late": false | ||
| 1469 | + }, | ||
| 1470 | + { | ||
| 1471 | + "id": "C0098", | ||
| 1472 | + "activity_id": "A0008", | ||
| 1473 | + "user_id": "U0021", | ||
| 1474 | + "registration_id": "R0148", | ||
| 1475 | + "checkin_time": "2025-04-16 05:41:35", | ||
| 1476 | + "checkin_type": "QR code", | ||
| 1477 | + "location": { | ||
| 1478 | + "name": "紫金读书会", | ||
| 1479 | + "coordinates": "28.532310,111.835896" | ||
| 1480 | + }, | ||
| 1481 | + "staff_id": null, | ||
| 1482 | + "status": "successful", | ||
| 1483 | + "notes": "", | ||
| 1484 | + "is_late": true | ||
| 1485 | + }, | ||
| 1486 | + { | ||
| 1487 | + "id": "C0099", | ||
| 1488 | + "activity_id": "A0008", | ||
| 1489 | + "user_id": "U0004", | ||
| 1490 | + "registration_id": "R0149", | ||
| 1491 | + "checkin_time": "2025-04-16 05:16:49", | ||
| 1492 | + "checkin_type": "QR code", | ||
| 1493 | + "location": { | ||
| 1494 | + "name": "紫金读书会", | ||
| 1495 | + "coordinates": "24.072484,125.678064" | ||
| 1496 | + }, | ||
| 1497 | + "staff_id": null, | ||
| 1498 | + "status": "successful", | ||
| 1499 | + "notes": "", | ||
| 1500 | + "is_late": false | ||
| 1501 | + }, | ||
| 1502 | + { | ||
| 1503 | + "id": "C0100", | ||
| 1504 | + "activity_id": "A0012", | ||
| 1505 | + "user_id": "U0026", | ||
| 1506 | + "registration_id": "R0178", | ||
| 1507 | + "checkin_time": "2025-04-04 05:04:24", | ||
| 1508 | + "checkin_type": "QR code", | ||
| 1509 | + "location": null, | ||
| 1510 | + "staff_id": null, | ||
| 1511 | + "status": "successful", | ||
| 1512 | + "notes": "", | ||
| 1513 | + "is_late": false | ||
| 1514 | + }, | ||
| 1515 | + { | ||
| 1516 | + "id": "C0101", | ||
| 1517 | + "activity_id": "A0012", | ||
| 1518 | + "user_id": "U0009", | ||
| 1519 | + "registration_id": "R0181", | ||
| 1520 | + "checkin_time": "2025-04-04 05:09:34", | ||
| 1521 | + "checkin_type": "QR code", | ||
| 1522 | + "location": null, | ||
| 1523 | + "staff_id": null, | ||
| 1524 | + "status": "successful", | ||
| 1525 | + "notes": "", | ||
| 1526 | + "is_late": false | ||
| 1527 | + }, | ||
| 1528 | + { | ||
| 1529 | + "id": "C0102", | ||
| 1530 | + "activity_id": "A0012", | ||
| 1531 | + "user_id": "U0025", | ||
| 1532 | + "registration_id": "R0182", | ||
| 1533 | + "checkin_time": "2025-04-04 05:25:45", | ||
| 1534 | + "checkin_type": "self-service", | ||
| 1535 | + "location": null, | ||
| 1536 | + "staff_id": null, | ||
| 1537 | + "status": "successful", | ||
| 1538 | + "notes": "", | ||
| 1539 | + "is_late": true | ||
| 1540 | + }, | ||
| 1541 | + { | ||
| 1542 | + "id": "C0103", | ||
| 1543 | + "activity_id": "A0012", | ||
| 1544 | + "user_id": "U0002", | ||
| 1545 | + "registration_id": "R0183", | ||
| 1546 | + "checkin_time": "2025-04-04 05:27:11", | ||
| 1547 | + "checkin_type": "QR code", | ||
| 1548 | + "location": null, | ||
| 1549 | + "staff_id": null, | ||
| 1550 | + "status": "successful", | ||
| 1551 | + "notes": "", | ||
| 1552 | + "is_late": false | ||
| 1553 | + }, | ||
| 1554 | + { | ||
| 1555 | + "id": "C0104", | ||
| 1556 | + "activity_id": "A0012", | ||
| 1557 | + "user_id": "U0031", | ||
| 1558 | + "registration_id": "R0184", | ||
| 1559 | + "checkin_time": "2025-04-04 05:31:22", | ||
| 1560 | + "checkin_type": "manual", | ||
| 1561 | + "location": null, | ||
| 1562 | + "staff_id": "O0001", | ||
| 1563 | + "status": "successful", | ||
| 1564 | + "notes": "", | ||
| 1565 | + "is_late": false | ||
| 1566 | + }, | ||
| 1567 | + { | ||
| 1568 | + "id": "C0105", | ||
| 1569 | + "activity_id": "A0012", | ||
| 1570 | + "user_id": "U0015", | ||
| 1571 | + "registration_id": "R0185", | ||
| 1572 | + "checkin_time": "2025-04-04 05:36:53", | ||
| 1573 | + "checkin_type": "QR code", | ||
| 1574 | + "location": null, | ||
| 1575 | + "staff_id": null, | ||
| 1576 | + "status": "successful", | ||
| 1577 | + "notes": "带了书本", | ||
| 1578 | + "is_late": false | ||
| 1579 | + }, | ||
| 1580 | + { | ||
| 1581 | + "id": "C0106", | ||
| 1582 | + "activity_id": "A0012", | ||
| 1583 | + "user_id": "U0039", | ||
| 1584 | + "registration_id": "R0187", | ||
| 1585 | + "checkin_time": "2025-04-04 05:48:01", | ||
| 1586 | + "checkin_type": "QR code", | ||
| 1587 | + "location": null, | ||
| 1588 | + "staff_id": null, | ||
| 1589 | + "status": "successful", | ||
| 1590 | + "notes": "", | ||
| 1591 | + "is_late": true | ||
| 1592 | + }, | ||
| 1593 | + { | ||
| 1594 | + "id": "C0107", | ||
| 1595 | + "activity_id": "A0012", | ||
| 1596 | + "user_id": "U0006", | ||
| 1597 | + "registration_id": "R0188", | ||
| 1598 | + "checkin_time": "2025-04-04 05:18:54", | ||
| 1599 | + "checkin_type": "QR code", | ||
| 1600 | + "location": null, | ||
| 1601 | + "staff_id": null, | ||
| 1602 | + "status": "successful", | ||
| 1603 | + "notes": "带了书本", | ||
| 1604 | + "is_late": false | ||
| 1605 | + }, | ||
| 1606 | + { | ||
| 1607 | + "id": "C0108", | ||
| 1608 | + "activity_id": "A0012", | ||
| 1609 | + "user_id": "U0020", | ||
| 1610 | + "registration_id": "R0189", | ||
| 1611 | + "checkin_time": "2025-04-04 05:55:49", | ||
| 1612 | + "checkin_type": "QR code", | ||
| 1613 | + "location": null, | ||
| 1614 | + "staff_id": null, | ||
| 1615 | + "status": "successful", | ||
| 1616 | + "notes": "准备充分", | ||
| 1617 | + "is_late": true | ||
| 1618 | + }, | ||
| 1619 | + { | ||
| 1620 | + "id": "C0109", | ||
| 1621 | + "activity_id": "A0012", | ||
| 1622 | + "user_id": "U0034", | ||
| 1623 | + "registration_id": "R0190", | ||
| 1624 | + "checkin_time": "2025-04-04 05:08:51", | ||
| 1625 | + "checkin_type": "QR code", | ||
| 1626 | + "location": null, | ||
| 1627 | + "staff_id": null, | ||
| 1628 | + "status": "successful", | ||
| 1629 | + "notes": "提前到达", | ||
| 1630 | + "is_late": false | ||
| 1631 | + }, | ||
| 1632 | + { | ||
| 1633 | + "id": "C0110", | ||
| 1634 | + "activity_id": "A0012", | ||
| 1635 | + "user_id": "U0010", | ||
| 1636 | + "registration_id": "R0191", | ||
| 1637 | + "checkin_time": "2025-04-04 05:48:49", | ||
| 1638 | + "checkin_type": "QR code", | ||
| 1639 | + "location": null, | ||
| 1640 | + "staff_id": null, | ||
| 1641 | + "status": "successful", | ||
| 1642 | + "notes": "", | ||
| 1643 | + "is_late": true | ||
| 1644 | + }, | ||
| 1645 | + { | ||
| 1646 | + "id": "C0111", | ||
| 1647 | + "activity_id": "A0012", | ||
| 1648 | + "user_id": "U0005", | ||
| 1649 | + "registration_id": "R0192", | ||
| 1650 | + "checkin_time": "2025-04-04 05:09:19", | ||
| 1651 | + "checkin_type": "QR code", | ||
| 1652 | + "location": null, | ||
| 1653 | + "staff_id": null, | ||
| 1654 | + "status": "successful", | ||
| 1655 | + "notes": "准备充分", | ||
| 1656 | + "is_late": false | ||
| 1657 | + }, | ||
| 1658 | + { | ||
| 1659 | + "id": "C0112", | ||
| 1660 | + "activity_id": "A0012", | ||
| 1661 | + "user_id": "U0032", | ||
| 1662 | + "registration_id": "R0193", | ||
| 1663 | + "checkin_time": "2025-04-04 05:00:54", | ||
| 1664 | + "checkin_type": "QR code", | ||
| 1665 | + "location": null, | ||
| 1666 | + "staff_id": null, | ||
| 1667 | + "status": "successful", | ||
| 1668 | + "notes": "", | ||
| 1669 | + "is_late": false | ||
| 1670 | + }, | ||
| 1671 | + { | ||
| 1672 | + "id": "C0113", | ||
| 1673 | + "activity_id": "A0012", | ||
| 1674 | + "user_id": "U0012", | ||
| 1675 | + "registration_id": "R0194", | ||
| 1676 | + "checkin_time": "2025-04-04 05:44:20", | ||
| 1677 | + "checkin_type": "QR code", | ||
| 1678 | + "location": null, | ||
| 1679 | + "staff_id": null, | ||
| 1680 | + "status": "successful", | ||
| 1681 | + "notes": "", | ||
| 1682 | + "is_late": true | ||
| 1683 | + }, | ||
| 1684 | + { | ||
| 1685 | + "id": "C0114", | ||
| 1686 | + "activity_id": "A0012", | ||
| 1687 | + "user_id": "U0023", | ||
| 1688 | + "registration_id": "R0195", | ||
| 1689 | + "checkin_time": "2025-04-04 05:24:39", | ||
| 1690 | + "checkin_type": "QR code", | ||
| 1691 | + "location": null, | ||
| 1692 | + "staff_id": null, | ||
| 1693 | + "status": "successful", | ||
| 1694 | + "notes": "", | ||
| 1695 | + "is_late": false | ||
| 1696 | + }, | ||
| 1697 | + { | ||
| 1698 | + "id": "C0115", | ||
| 1699 | + "activity_id": "A0012", | ||
| 1700 | + "user_id": "U0021", | ||
| 1701 | + "registration_id": "R0196", | ||
| 1702 | + "checkin_time": "2025-04-04 05:00:48", | ||
| 1703 | + "checkin_type": "QR code", | ||
| 1704 | + "location": null, | ||
| 1705 | + "staff_id": null, | ||
| 1706 | + "status": "successful", | ||
| 1707 | + "notes": "", | ||
| 1708 | + "is_late": false | ||
| 1709 | + }, | ||
| 1710 | + { | ||
| 1711 | + "id": "C0116", | ||
| 1712 | + "activity_id": "A0012", | ||
| 1713 | + "user_id": "U0004", | ||
| 1714 | + "registration_id": "R0199", | ||
| 1715 | + "checkin_time": "2025-04-04 05:47:11", | ||
| 1716 | + "checkin_type": "manual", | ||
| 1717 | + "location": null, | ||
| 1718 | + "staff_id": "O0001", | ||
| 1719 | + "status": "successful", | ||
| 1720 | + "notes": "", | ||
| 1721 | + "is_late": true | ||
| 1722 | + }, | ||
| 1723 | + { | ||
| 1724 | + "id": "C0117", | ||
| 1725 | + "activity_id": "A0012", | ||
| 1726 | + "user_id": "U0033", | ||
| 1727 | + "registration_id": "R0200", | ||
| 1728 | + "checkin_time": "2025-04-04 05:26:28", | ||
| 1729 | + "checkin_type": "manual", | ||
| 1730 | + "location": null, | ||
| 1731 | + "staff_id": "O0001", | ||
| 1732 | + "status": "successful", | ||
| 1733 | + "notes": "准备充分", | ||
| 1734 | + "is_late": false | ||
| 1735 | + }, | ||
| 1736 | + { | ||
| 1737 | + "id": "C0118", | ||
| 1738 | + "activity_id": "A0012", | ||
| 1739 | + "user_id": "U0018", | ||
| 1740 | + "registration_id": "R0201", | ||
| 1741 | + "checkin_time": "2025-04-04 05:27:24", | ||
| 1742 | + "checkin_type": "QR code", | ||
| 1743 | + "location": null, | ||
| 1744 | + "staff_id": null, | ||
| 1745 | + "status": "successful", | ||
| 1746 | + "notes": "", | ||
| 1747 | + "is_late": false | ||
| 1748 | + }, | ||
| 1749 | + { | ||
| 1750 | + "id": "C0119", | ||
| 1751 | + "activity_id": "A0012", | ||
| 1752 | + "user_id": "U0017", | ||
| 1753 | + "registration_id": "R0202", | ||
| 1754 | + "checkin_time": "2025-04-04 05:15:29", | ||
| 1755 | + "checkin_type": "QR code", | ||
| 1756 | + "location": null, | ||
| 1757 | + "staff_id": null, | ||
| 1758 | + "status": "successful", | ||
| 1759 | + "notes": "", | ||
| 1760 | + "is_late": false | ||
| 1761 | + }, | ||
| 1762 | + { | ||
| 1763 | + "id": "C0120", | ||
| 1764 | + "activity_id": "A0012", | ||
| 1765 | + "user_id": "U0030", | ||
| 1766 | + "registration_id": "R0203", | ||
| 1767 | + "checkin_time": "2025-04-04 06:00:53", | ||
| 1768 | + "checkin_type": "manual", | ||
| 1769 | + "location": null, | ||
| 1770 | + "staff_id": "O0001", | ||
| 1771 | + "status": "successful", | ||
| 1772 | + "notes": "", | ||
| 1773 | + "is_late": true | ||
| 1774 | + }, | ||
| 1775 | + { | ||
| 1776 | + "id": "C0121", | ||
| 1777 | + "activity_id": "A0012", | ||
| 1778 | + "user_id": "U0040", | ||
| 1779 | + "registration_id": "R0204", | ||
| 1780 | + "checkin_time": "2025-04-04 05:39:19", | ||
| 1781 | + "checkin_type": "self-service", | ||
| 1782 | + "location": null, | ||
| 1783 | + "staff_id": null, | ||
| 1784 | + "status": "successful", | ||
| 1785 | + "notes": "", | ||
| 1786 | + "is_late": false | ||
| 1787 | + }, | ||
| 1788 | + { | ||
| 1789 | + "id": "C0122", | ||
| 1790 | + "activity_id": "A0012", | ||
| 1791 | + "user_id": "U0035", | ||
| 1792 | + "registration_id": "R0205", | ||
| 1793 | + "checkin_time": "2025-04-04 04:59:03", | ||
| 1794 | + "checkin_type": "manual", | ||
| 1795 | + "location": null, | ||
| 1796 | + "staff_id": "O0001", | ||
| 1797 | + "status": "successful", | ||
| 1798 | + "notes": "", | ||
| 1799 | + "is_late": false | ||
| 1800 | + }, | ||
| 1801 | + { | ||
| 1802 | + "id": "C0123", | ||
| 1803 | + "activity_id": "A0012", | ||
| 1804 | + "user_id": "U0008", | ||
| 1805 | + "registration_id": "R0206", | ||
| 1806 | + "checkin_time": "2025-04-04 05:18:37", | ||
| 1807 | + "checkin_type": "QR code", | ||
| 1808 | + "location": null, | ||
| 1809 | + "staff_id": null, | ||
| 1810 | + "status": "successful", | ||
| 1811 | + "notes": "", | ||
| 1812 | + "is_late": false | ||
| 1813 | + }, | ||
| 1814 | + { | ||
| 1815 | + "id": "C0124", | ||
| 1816 | + "activity_id": "A0012", | ||
| 1817 | + "user_id": "U0029", | ||
| 1818 | + "registration_id": "R0207", | ||
| 1819 | + "checkin_time": "2025-04-04 05:05:57", | ||
| 1820 | + "checkin_type": "manual", | ||
| 1821 | + "location": null, | ||
| 1822 | + "staff_id": "O0001", | ||
| 1823 | + "status": "successful", | ||
| 1824 | + "notes": "", | ||
| 1825 | + "is_late": false | ||
| 1826 | + }, | ||
| 1827 | + { | ||
| 1828 | + "id": "C0125", | ||
| 1829 | + "activity_id": "A0012", | ||
| 1830 | + "user_id": "U0028", | ||
| 1831 | + "registration_id": "R0208", | ||
| 1832 | + "checkin_time": "2025-04-04 05:12:11", | ||
| 1833 | + "checkin_type": "manual", | ||
| 1834 | + "location": null, | ||
| 1835 | + "staff_id": "O0001", | ||
| 1836 | + "status": "successful", | ||
| 1837 | + "notes": "", | ||
| 1838 | + "is_late": false | ||
| 1839 | + }, | ||
| 1840 | + { | ||
| 1841 | + "id": "C0126", | ||
| 1842 | + "activity_id": "A0012", | ||
| 1843 | + "user_id": "U0027", | ||
| 1844 | + "registration_id": "R0209", | ||
| 1845 | + "checkin_time": "2025-04-04 05:25:32", | ||
| 1846 | + "checkin_type": "QR code", | ||
| 1847 | + "location": null, | ||
| 1848 | + "staff_id": null, | ||
| 1849 | + "status": "successful", | ||
| 1850 | + "notes": "带了书本", | ||
| 1851 | + "is_late": true | ||
| 1852 | + }, | ||
| 1853 | + { | ||
| 1854 | + "id": "C0127", | ||
| 1855 | + "activity_id": "A0012", | ||
| 1856 | + "user_id": "U0022", | ||
| 1857 | + "registration_id": "R0211", | ||
| 1858 | + "checkin_time": "2025-04-04 05:37:40", | ||
| 1859 | + "checkin_type": "QR code", | ||
| 1860 | + "location": null, | ||
| 1861 | + "staff_id": null, | ||
| 1862 | + "status": "successful", | ||
| 1863 | + "notes": "热情参与讨论", | ||
| 1864 | + "is_late": true | ||
| 1865 | + }, | ||
| 1866 | + { | ||
| 1867 | + "id": "C0128", | ||
| 1868 | + "activity_id": "A0012", | ||
| 1869 | + "user_id": "U0016", | ||
| 1870 | + "registration_id": "R0213", | ||
| 1871 | + "checkin_time": "2025-04-04 05:02:22", | ||
| 1872 | + "checkin_type": "self-service", | ||
| 1873 | + "location": null, | ||
| 1874 | + "staff_id": null, | ||
| 1875 | + "status": "successful", | ||
| 1876 | + "notes": "热情参与讨论", | ||
| 1877 | + "is_late": false | ||
| 1878 | + }, | ||
| 1879 | + { | ||
| 1880 | + "id": "C0129", | ||
| 1881 | + "activity_id": "A0012", | ||
| 1882 | + "user_id": "U0011", | ||
| 1883 | + "registration_id": "R0214", | ||
| 1884 | + "checkin_time": "2025-04-04 05:29:01", | ||
| 1885 | + "checkin_type": "self-service", | ||
| 1886 | + "location": null, | ||
| 1887 | + "staff_id": null, | ||
| 1888 | + "status": "successful", | ||
| 1889 | + "notes": "按时到达", | ||
| 1890 | + "is_late": false | ||
| 1891 | + }, | ||
| 1892 | + { | ||
| 1893 | + "id": "C0130", | ||
| 1894 | + "activity_id": "A0012", | ||
| 1895 | + "user_id": "U0036", | ||
| 1896 | + "registration_id": "R0215", | ||
| 1897 | + "checkin_time": "2025-04-04 05:42:57", | ||
| 1898 | + "checkin_type": "QR code", | ||
| 1899 | + "location": null, | ||
| 1900 | + "staff_id": null, | ||
| 1901 | + "status": "successful", | ||
| 1902 | + "notes": "", | ||
| 1903 | + "is_late": false | ||
| 1904 | + }, | ||
| 1905 | + { | ||
| 1906 | + "id": "C0131", | ||
| 1907 | + "activity_id": "A0012", | ||
| 1908 | + "user_id": "U0019", | ||
| 1909 | + "registration_id": "R0216", | ||
| 1910 | + "checkin_time": "2025-04-04 05:12:01", | ||
| 1911 | + "checkin_type": "QR code", | ||
| 1912 | + "location": null, | ||
| 1913 | + "staff_id": null, | ||
| 1914 | + "status": "successful", | ||
| 1915 | + "notes": "", | ||
| 1916 | + "is_late": false | ||
| 1917 | + }, | ||
| 1918 | + { | ||
| 1919 | + "id": "C0132", | ||
| 1920 | + "activity_id": "A0012", | ||
| 1921 | + "user_id": "U0037", | ||
| 1922 | + "registration_id": "R0217", | ||
| 1923 | + "checkin_time": "2025-04-04 05:43:15", | ||
| 1924 | + "checkin_type": "QR code", | ||
| 1925 | + "location": null, | ||
| 1926 | + "staff_id": null, | ||
| 1927 | + "status": "successful", | ||
| 1928 | + "notes": "准备充分", | ||
| 1929 | + "is_late": false | ||
| 1930 | + }, | ||
| 1931 | + { | ||
| 1932 | + "id": "C0133", | ||
| 1933 | + "activity_id": "A0013", | ||
| 1934 | + "user_id": "U0021", | ||
| 1935 | + "registration_id": "R0219", | ||
| 1936 | + "checkin_time": "2025-04-16 06:30:48", | ||
| 1937 | + "checkin_type": "QR code", | ||
| 1938 | + "location": { | ||
| 1939 | + "name": "深蓝咖啡馆", | ||
| 1940 | + "coordinates": "31.314481,112.706910" | ||
| 1941 | + }, | ||
| 1942 | + "staff_id": null, | ||
| 1943 | + "status": "successful", | ||
| 1944 | + "notes": "", | ||
| 1945 | + "is_late": false | ||
| 1946 | + }, | ||
| 1947 | + { | ||
| 1948 | + "id": "C0134", | ||
| 1949 | + "activity_id": "A0013", | ||
| 1950 | + "user_id": "U0034", | ||
| 1951 | + "registration_id": "R0220", | ||
| 1952 | + "checkin_time": "2025-04-16 06:28:10", | ||
| 1953 | + "checkin_type": "QR code", | ||
| 1954 | + "location": { | ||
| 1955 | + "name": "深蓝咖啡馆", | ||
| 1956 | + "coordinates": "27.233821,118.026442" | ||
| 1957 | + }, | ||
| 1958 | + "staff_id": null, | ||
| 1959 | + "status": "successful", | ||
| 1960 | + "notes": "", | ||
| 1961 | + "is_late": false | ||
| 1962 | + }, | ||
| 1963 | + { | ||
| 1964 | + "id": "C0135", | ||
| 1965 | + "activity_id": "A0013", | ||
| 1966 | + "user_id": "U0024", | ||
| 1967 | + "registration_id": "R0222", | ||
| 1968 | + "checkin_time": "2025-04-16 06:19:07", | ||
| 1969 | + "checkin_type": "QR code", | ||
| 1970 | + "location": { | ||
| 1971 | + "name": "深蓝咖啡馆", | ||
| 1972 | + "coordinates": "26.304584,117.374957" | ||
| 1973 | + }, | ||
| 1974 | + "staff_id": null, | ||
| 1975 | + "status": "successful", | ||
| 1976 | + "notes": "", | ||
| 1977 | + "is_late": false | ||
| 1978 | + }, | ||
| 1979 | + { | ||
| 1980 | + "id": "C0136", | ||
| 1981 | + "activity_id": "A0013", | ||
| 1982 | + "user_id": "U0006", | ||
| 1983 | + "registration_id": "R0226", | ||
| 1984 | + "checkin_time": "2025-04-16 06:47:15", | ||
| 1985 | + "checkin_type": "QR code", | ||
| 1986 | + "location": { | ||
| 1987 | + "name": "深蓝咖啡馆", | ||
| 1988 | + "coordinates": "26.656372,107.313507" | ||
| 1989 | + }, | ||
| 1990 | + "staff_id": null, | ||
| 1991 | + "status": "successful", | ||
| 1992 | + "notes": "带了书本", | ||
| 1993 | + "is_late": true | ||
| 1994 | + }, | ||
| 1995 | + { | ||
| 1996 | + "id": "C0137", | ||
| 1997 | + "activity_id": "A0013", | ||
| 1998 | + "user_id": "U0016", | ||
| 1999 | + "registration_id": "R0228", | ||
| 2000 | + "checkin_time": "2025-04-16 06:02:25", | ||
| 2001 | + "checkin_type": "manual", | ||
| 2002 | + "location": { | ||
| 2003 | + "name": "深蓝咖啡馆", | ||
| 2004 | + "coordinates": "22.619492,111.165082" | ||
| 2005 | + }, | ||
| 2006 | + "staff_id": "O0003", | ||
| 2007 | + "status": "successful", | ||
| 2008 | + "notes": "带了书本", | ||
| 2009 | + "is_late": false | ||
| 2010 | + }, | ||
| 2011 | + { | ||
| 2012 | + "id": "C0138", | ||
| 2013 | + "activity_id": "A0013", | ||
| 2014 | + "user_id": "U0039", | ||
| 2015 | + "registration_id": "R0230", | ||
| 2016 | + "checkin_time": "2025-04-16 06:19:57", | ||
| 2017 | + "checkin_type": "QR code", | ||
| 2018 | + "location": { | ||
| 2019 | + "name": "深蓝咖啡馆", | ||
| 2020 | + "coordinates": "28.583453,100.061289" | ||
| 2021 | + }, | ||
| 2022 | + "staff_id": null, | ||
| 2023 | + "status": "successful", | ||
| 2024 | + "notes": "", | ||
| 2025 | + "is_late": false | ||
| 2026 | + }, | ||
| 2027 | + { | ||
| 2028 | + "id": "C0139", | ||
| 2029 | + "activity_id": "A0013", | ||
| 2030 | + "user_id": "U0033", | ||
| 2031 | + "registration_id": "R0231", | ||
| 2032 | + "checkin_time": "2025-04-16 05:48:13", | ||
| 2033 | + "checkin_type": "QR code", | ||
| 2034 | + "location": { | ||
| 2035 | + "name": "深蓝咖啡馆", | ||
| 2036 | + "coordinates": "39.928726,103.865093" | ||
| 2037 | + }, | ||
| 2038 | + "staff_id": null, | ||
| 2039 | + "status": "successful", | ||
| 2040 | + "notes": "", | ||
| 2041 | + "is_late": false | ||
| 2042 | + }, | ||
| 2043 | + { | ||
| 2044 | + "id": "C0140", | ||
| 2045 | + "activity_id": "A0013", | ||
| 2046 | + "user_id": "U0013", | ||
| 2047 | + "registration_id": "R0232", | ||
| 2048 | + "checkin_time": "2025-04-16 06:22:37", | ||
| 2049 | + "checkin_type": "manual", | ||
| 2050 | + "location": { | ||
| 2051 | + "name": "深蓝咖啡馆", | ||
| 2052 | + "coordinates": "30.206263,116.407620" | ||
| 2053 | + }, | ||
| 2054 | + "staff_id": "O0003", | ||
| 2055 | + "status": "successful", | ||
| 2056 | + "notes": "", | ||
| 2057 | + "is_late": false | ||
| 2058 | + }, | ||
| 2059 | + { | ||
| 2060 | + "id": "C0141", | ||
| 2061 | + "activity_id": "A0013", | ||
| 2062 | + "user_id": "U0017", | ||
| 2063 | + "registration_id": "R0237", | ||
| 2064 | + "checkin_time": "2025-04-16 05:51:41", | ||
| 2065 | + "checkin_type": "QR code", | ||
| 2066 | + "location": { | ||
| 2067 | + "name": "深蓝咖啡馆", | ||
| 2068 | + "coordinates": "26.353654,112.348033" | ||
| 2069 | + }, | ||
| 2070 | + "staff_id": null, | ||
| 2071 | + "status": "successful", | ||
| 2072 | + "notes": "", | ||
| 2073 | + "is_late": false | ||
| 2074 | + }, | ||
| 2075 | + { | ||
| 2076 | + "id": "C0142", | ||
| 2077 | + "activity_id": "A0013", | ||
| 2078 | + "user_id": "U0040", | ||
| 2079 | + "registration_id": "R0238", | ||
| 2080 | + "checkin_time": "2025-04-16 05:59:42", | ||
| 2081 | + "checkin_type": "manual", | ||
| 2082 | + "location": { | ||
| 2083 | + "name": "深蓝咖啡馆", | ||
| 2084 | + "coordinates": "29.536559,121.926857" | ||
| 2085 | + }, | ||
| 2086 | + "staff_id": "O0003", | ||
| 2087 | + "status": "successful", | ||
| 2088 | + "notes": "按时到达", | ||
| 2089 | + "is_late": false | ||
| 2090 | + }, | ||
| 2091 | + { | ||
| 2092 | + "id": "C0143", | ||
| 2093 | + "activity_id": "A0013", | ||
| 2094 | + "user_id": "U0028", | ||
| 2095 | + "registration_id": "R0239", | ||
| 2096 | + "checkin_time": "2025-04-16 06:03:43", | ||
| 2097 | + "checkin_type": "QR code", | ||
| 2098 | + "location": { | ||
| 2099 | + "name": "深蓝咖啡馆", | ||
| 2100 | + "coordinates": "38.445453,111.849643" | ||
| 2101 | + }, | ||
| 2102 | + "staff_id": null, | ||
| 2103 | + "status": "successful", | ||
| 2104 | + "notes": "热情参与讨论", | ||
| 2105 | + "is_late": false | ||
| 2106 | + }, | ||
| 2107 | + { | ||
| 2108 | + "id": "C0144", | ||
| 2109 | + "activity_id": "A0013", | ||
| 2110 | + "user_id": "U0015", | ||
| 2111 | + "registration_id": "R0240", | ||
| 2112 | + "checkin_time": "2025-04-16 06:15:58", | ||
| 2113 | + "checkin_type": "QR code", | ||
| 2114 | + "location": { | ||
| 2115 | + "name": "深蓝咖啡馆", | ||
| 2116 | + "coordinates": "38.987819,109.828606" | ||
| 2117 | + }, | ||
| 2118 | + "staff_id": null, | ||
| 2119 | + "status": "failed", | ||
| 2120 | + "notes": "网络连接不稳定", | ||
| 2121 | + "is_late": false | ||
| 2122 | + }, | ||
| 2123 | + { | ||
| 2124 | + "id": "C0145", | ||
| 2125 | + "activity_id": "A0013", | ||
| 2126 | + "user_id": "U0023", | ||
| 2127 | + "registration_id": "R0242", | ||
| 2128 | + "checkin_time": "2025-04-16 06:21:50", | ||
| 2129 | + "checkin_type": "manual", | ||
| 2130 | + "location": { | ||
| 2131 | + "name": "深蓝咖啡馆", | ||
| 2132 | + "coordinates": "38.259928,108.439322" | ||
| 2133 | + }, | ||
| 2134 | + "staff_id": "O0003", | ||
| 2135 | + "status": "successful", | ||
| 2136 | + "notes": "", | ||
| 2137 | + "is_late": false | ||
| 2138 | + }, | ||
| 2139 | + { | ||
| 2140 | + "id": "C0146", | ||
| 2141 | + "activity_id": "A0013", | ||
| 2142 | + "user_id": "U0012", | ||
| 2143 | + "registration_id": "R0243", | ||
| 2144 | + "checkin_time": "2025-04-16 06:22:16", | ||
| 2145 | + "checkin_type": "QR code", | ||
| 2146 | + "location": { | ||
| 2147 | + "name": "深蓝咖啡馆", | ||
| 2148 | + "coordinates": "30.354202,113.504246" | ||
| 2149 | + }, | ||
| 2150 | + "staff_id": null, | ||
| 2151 | + "status": "successful", | ||
| 2152 | + "notes": "准备充分", | ||
| 2153 | + "is_late": false | ||
| 2154 | + }, | ||
| 2155 | + { | ||
| 2156 | + "id": "C0147", | ||
| 2157 | + "activity_id": "A0013", | ||
| 2158 | + "user_id": "U0020", | ||
| 2159 | + "registration_id": "R0244", | ||
| 2160 | + "checkin_time": "2025-04-16 06:14:18", | ||
| 2161 | + "checkin_type": "QR code", | ||
| 2162 | + "location": { | ||
| 2163 | + "name": "深蓝咖啡馆", | ||
| 2164 | + "coordinates": "38.643924,120.520059" | ||
| 2165 | + }, | ||
| 2166 | + "staff_id": null, | ||
| 2167 | + "status": "successful", | ||
| 2168 | + "notes": "", | ||
| 2169 | + "is_late": false | ||
| 2170 | + }, | ||
| 2171 | + { | ||
| 2172 | + "id": "C0148", | ||
| 2173 | + "activity_id": "A0013", | ||
| 2174 | + "user_id": "U0022", | ||
| 2175 | + "registration_id": "R0246", | ||
| 2176 | + "checkin_time": "2025-04-16 06:03:06", | ||
| 2177 | + "checkin_type": "QR code", | ||
| 2178 | + "location": { | ||
| 2179 | + "name": "深蓝咖啡馆", | ||
| 2180 | + "coordinates": "31.559993,119.096261" | ||
| 2181 | + }, | ||
| 2182 | + "staff_id": null, | ||
| 2183 | + "status": "successful", | ||
| 2184 | + "notes": "", | ||
| 2185 | + "is_late": false | ||
| 2186 | + }, | ||
| 2187 | + { | ||
| 2188 | + "id": "C0149", | ||
| 2189 | + "activity_id": "A0013", | ||
| 2190 | + "user_id": "U0003", | ||
| 2191 | + "registration_id": "R0247", | ||
| 2192 | + "checkin_time": "2025-04-16 05:52:52", | ||
| 2193 | + "checkin_type": "self-service", | ||
| 2194 | + "location": { | ||
| 2195 | + "name": "深蓝咖啡馆", | ||
| 2196 | + "coordinates": "39.656725,112.033980" | ||
| 2197 | + }, | ||
| 2198 | + "staff_id": null, | ||
| 2199 | + "status": "successful", | ||
| 2200 | + "notes": "", | ||
| 2201 | + "is_late": false | ||
| 2202 | + }, | ||
| 2203 | + { | ||
| 2204 | + "id": "C0150", | ||
| 2205 | + "activity_id": "A0013", | ||
| 2206 | + "user_id": "U0001", | ||
| 2207 | + "registration_id": "R0249", | ||
| 2208 | + "checkin_time": "2025-04-16 05:53:42", | ||
| 2209 | + "checkin_type": "QR code", | ||
| 2210 | + "location": { | ||
| 2211 | + "name": "深蓝咖啡馆", | ||
| 2212 | + "coordinates": "35.419700,117.373079" | ||
| 2213 | + }, | ||
| 2214 | + "staff_id": null, | ||
| 2215 | + "status": "successful", | ||
| 2216 | + "notes": "", | ||
| 2217 | + "is_late": false | ||
| 2218 | + }, | ||
| 2219 | + { | ||
| 2220 | + "id": "C0151", | ||
| 2221 | + "activity_id": "A0013", | ||
| 2222 | + "user_id": "U0036", | ||
| 2223 | + "registration_id": "R0250", | ||
| 2224 | + "checkin_time": "2025-04-16 06:22:22", | ||
| 2225 | + "checkin_type": "self-service", | ||
| 2226 | + "location": { | ||
| 2227 | + "name": "深蓝咖啡馆", | ||
| 2228 | + "coordinates": "22.718087,103.176777" | ||
| 2229 | + }, | ||
| 2230 | + "staff_id": null, | ||
| 2231 | + "status": "successful", | ||
| 2232 | + "notes": "", | ||
| 2233 | + "is_late": true | ||
| 2234 | + }, | ||
| 2235 | + { | ||
| 2236 | + "id": "C0152", | ||
| 2237 | + "activity_id": "A0013", | ||
| 2238 | + "user_id": "U0037", | ||
| 2239 | + "registration_id": "R0251", | ||
| 2240 | + "checkin_time": "2025-04-16 06:04:16", | ||
| 2241 | + "checkin_type": "QR code", | ||
| 2242 | + "location": { | ||
| 2243 | + "name": "深蓝咖啡馆", | ||
| 2244 | + "coordinates": "36.437377,116.319798" | ||
| 2245 | + }, | ||
| 2246 | + "staff_id": null, | ||
| 2247 | + "status": "successful", | ||
| 2248 | + "notes": "", | ||
| 2249 | + "is_late": false | ||
| 2250 | + }, | ||
| 2251 | + { | ||
| 2252 | + "id": "C0153", | ||
| 2253 | + "activity_id": "A0013", | ||
| 2254 | + "user_id": "U0010", | ||
| 2255 | + "registration_id": "R0252", | ||
| 2256 | + "checkin_time": "2025-04-16 06:06:45", | ||
| 2257 | + "checkin_type": "QR code", | ||
| 2258 | + "location": { | ||
| 2259 | + "name": "深蓝咖啡馆", | ||
| 2260 | + "coordinates": "25.502640,110.555487" | ||
| 2261 | + }, | ||
| 2262 | + "staff_id": null, | ||
| 2263 | + "status": "failed", | ||
| 2264 | + "notes": "设备问题", | ||
| 2265 | + "is_late": false | ||
| 2266 | + }, | ||
| 2267 | + { | ||
| 2268 | + "id": "C0154", | ||
| 2269 | + "activity_id": "A0013", | ||
| 2270 | + "user_id": "U0004", | ||
| 2271 | + "registration_id": "R0254", | ||
| 2272 | + "checkin_time": "2025-04-16 06:00:23", | ||
| 2273 | + "checkin_type": "QR code", | ||
| 2274 | + "location": { | ||
| 2275 | + "name": "深蓝咖啡馆", | ||
| 2276 | + "coordinates": "38.473438,101.763058" | ||
| 2277 | + }, | ||
| 2278 | + "staff_id": null, | ||
| 2279 | + "status": "successful", | ||
| 2280 | + "notes": "", | ||
| 2281 | + "is_late": false | ||
| 2282 | + }, | ||
| 2283 | + { | ||
| 2284 | + "id": "C0155", | ||
| 2285 | + "activity_id": "A0013", | ||
| 2286 | + "user_id": "U0005", | ||
| 2287 | + "registration_id": "R0255", | ||
| 2288 | + "checkin_time": "2025-04-16 06:50:21", | ||
| 2289 | + "checkin_type": "QR code", | ||
| 2290 | + "location": { | ||
| 2291 | + "name": "深蓝咖啡馆", | ||
| 2292 | + "coordinates": "25.433843,111.547821" | ||
| 2293 | + }, | ||
| 2294 | + "staff_id": null, | ||
| 2295 | + "status": "successful", | ||
| 2296 | + "notes": "", | ||
| 2297 | + "is_late": true | ||
| 2298 | + }, | ||
| 2299 | + { | ||
| 2300 | + "id": "C0156", | ||
| 2301 | + "activity_id": "A0013", | ||
| 2302 | + "user_id": "U0025", | ||
| 2303 | + "registration_id": "R0256", | ||
| 2304 | + "checkin_time": "2025-04-16 06:06:05", | ||
| 2305 | + "checkin_type": "manual", | ||
| 2306 | + "location": { | ||
| 2307 | + "name": "深蓝咖啡馆", | ||
| 2308 | + "coordinates": "33.246812,102.422719" | ||
| 2309 | + }, | ||
| 2310 | + "staff_id": "O0003", | ||
| 2311 | + "status": "successful", | ||
| 2312 | + "notes": "", | ||
| 2313 | + "is_late": false | ||
| 2314 | + }, | ||
| 2315 | + { | ||
| 2316 | + "id": "C0157", | ||
| 2317 | + "activity_id": "A0015", | ||
| 2318 | + "user_id": "U0035", | ||
| 2319 | + "registration_id": "R0263", | ||
| 2320 | + "checkin_time": "2025-04-16 06:21:26", | ||
| 2321 | + "checkin_type": "QR code", | ||
| 2322 | + "location": null, | ||
| 2323 | + "staff_id": null, | ||
| 2324 | + "status": "successful", | ||
| 2325 | + "notes": "", | ||
| 2326 | + "is_late": false | ||
| 2327 | + }, | ||
| 2328 | + { | ||
| 2329 | + "id": "C0158", | ||
| 2330 | + "activity_id": "A0015", | ||
| 2331 | + "user_id": "U0010", | ||
| 2332 | + "registration_id": "R0264", | ||
| 2333 | + "checkin_time": "2025-04-16 06:35:32", | ||
| 2334 | + "checkin_type": "QR code", | ||
| 2335 | + "location": null, | ||
| 2336 | + "staff_id": null, | ||
| 2337 | + "status": "successful", | ||
| 2338 | + "notes": "", | ||
| 2339 | + "is_late": true | ||
| 2340 | + }, | ||
| 2341 | + { | ||
| 2342 | + "id": "C0159", | ||
| 2343 | + "activity_id": "A0015", | ||
| 2344 | + "user_id": "U0015", | ||
| 2345 | + "registration_id": "R0265", | ||
| 2346 | + "checkin_time": "2025-04-16 05:52:07", | ||
| 2347 | + "checkin_type": "QR code", | ||
| 2348 | + "location": null, | ||
| 2349 | + "staff_id": null, | ||
| 2350 | + "status": "successful", | ||
| 2351 | + "notes": "", | ||
| 2352 | + "is_late": false | ||
| 2353 | + }, | ||
| 2354 | + { | ||
| 2355 | + "id": "C0160", | ||
| 2356 | + "activity_id": "A0015", | ||
| 2357 | + "user_id": "U0005", | ||
| 2358 | + "registration_id": "R0266", | ||
| 2359 | + "checkin_time": "2025-04-16 06:18:17", | ||
| 2360 | + "checkin_type": "QR code", | ||
| 2361 | + "location": null, | ||
| 2362 | + "staff_id": null, | ||
| 2363 | + "status": "successful", | ||
| 2364 | + "notes": "", | ||
| 2365 | + "is_late": false | ||
| 2366 | + }, | ||
| 2367 | + { | ||
| 2368 | + "id": "C0161", | ||
| 2369 | + "activity_id": "A0015", | ||
| 2370 | + "user_id": "U0001", | ||
| 2371 | + "registration_id": "R0267", | ||
| 2372 | + "checkin_time": "2025-04-16 06:05:44", | ||
| 2373 | + "checkin_type": "self-service", | ||
| 2374 | + "location": null, | ||
| 2375 | + "staff_id": null, | ||
| 2376 | + "status": "successful", | ||
| 2377 | + "notes": "准备充分", | ||
| 2378 | + "is_late": true | ||
| 2379 | + }, | ||
| 2380 | + { | ||
| 2381 | + "id": "C0162", | ||
| 2382 | + "activity_id": "A0015", | ||
| 2383 | + "user_id": "U0025", | ||
| 2384 | + "registration_id": "R0270", | ||
| 2385 | + "checkin_time": "2025-04-16 06:32:13", | ||
| 2386 | + "checkin_type": "QR code", | ||
| 2387 | + "location": null, | ||
| 2388 | + "staff_id": null, | ||
| 2389 | + "status": "successful", | ||
| 2390 | + "notes": "提前到达", | ||
| 2391 | + "is_late": false | ||
| 2392 | + }, | ||
| 2393 | + { | ||
| 2394 | + "id": "C0163", | ||
| 2395 | + "activity_id": "A0015", | ||
| 2396 | + "user_id": "U0018", | ||
| 2397 | + "registration_id": "R0274", | ||
| 2398 | + "checkin_time": "2025-04-16 06:25:01", | ||
| 2399 | + "checkin_type": "QR code", | ||
| 2400 | + "location": null, | ||
| 2401 | + "staff_id": null, | ||
| 2402 | + "status": "successful", | ||
| 2403 | + "notes": "提前到达", | ||
| 2404 | + "is_late": true | ||
| 2405 | + }, | ||
| 2406 | + { | ||
| 2407 | + "id": "C0164", | ||
| 2408 | + "activity_id": "A0015", | ||
| 2409 | + "user_id": "U0019", | ||
| 2410 | + "registration_id": "R0275", | ||
| 2411 | + "checkin_time": "2025-04-16 06:13:07", | ||
| 2412 | + "checkin_type": "QR code", | ||
| 2413 | + "location": null, | ||
| 2414 | + "staff_id": null, | ||
| 2415 | + "status": "successful", | ||
| 2416 | + "notes": "", | ||
| 2417 | + "is_late": false | ||
| 2418 | + }, | ||
| 2419 | + { | ||
| 2420 | + "id": "C0165", | ||
| 2421 | + "activity_id": "A0022", | ||
| 2422 | + "user_id": "U0026", | ||
| 2423 | + "registration_id": "R0304", | ||
| 2424 | + "checkin_time": "2025-04-16 07:15:52", | ||
| 2425 | + "checkin_type": "manual", | ||
| 2426 | + "location": { | ||
| 2427 | + "name": "大雁塔文化空间", | ||
| 2428 | + "coordinates": "26.580414,125.344607" | ||
| 2429 | + }, | ||
| 2430 | + "staff_id": "O0005", | ||
| 2431 | + "status": "successful", | ||
| 2432 | + "notes": "", | ||
| 2433 | + "is_late": true | ||
| 2434 | + }, | ||
| 2435 | + { | ||
| 2436 | + "id": "C0166", | ||
| 2437 | + "activity_id": "A0022", | ||
| 2438 | + "user_id": "U0016", | ||
| 2439 | + "registration_id": "R0307", | ||
| 2440 | + "checkin_time": "2025-04-16 06:48:22", | ||
| 2441 | + "checkin_type": "QR code", | ||
| 2442 | + "location": { | ||
| 2443 | + "name": "大雁塔文化空间", | ||
| 2444 | + "coordinates": "24.470878,121.132080" | ||
| 2445 | + }, | ||
| 2446 | + "staff_id": null, | ||
| 2447 | + "status": "successful", | ||
| 2448 | + "notes": "", | ||
| 2449 | + "is_late": false | ||
| 2450 | + }, | ||
| 2451 | + { | ||
| 2452 | + "id": "C0167", | ||
| 2453 | + "activity_id": "A0022", | ||
| 2454 | + "user_id": "U0001", | ||
| 2455 | + "registration_id": "R0310", | ||
| 2456 | + "checkin_time": "2025-04-16 06:28:54", | ||
| 2457 | + "checkin_type": "QR code", | ||
| 2458 | + "location": { | ||
| 2459 | + "name": "大雁塔文化空间", | ||
| 2460 | + "coordinates": "28.449496,109.032109" | ||
| 2461 | + }, | ||
| 2462 | + "staff_id": null, | ||
| 2463 | + "status": "successful", | ||
| 2464 | + "notes": "按时到达", | ||
| 2465 | + "is_late": false | ||
| 2466 | + }, | ||
| 2467 | + { | ||
| 2468 | + "id": "C0168", | ||
| 2469 | + "activity_id": "A0022", | ||
| 2470 | + "user_id": "U0008", | ||
| 2471 | + "registration_id": "R0312", | ||
| 2472 | + "checkin_time": "2025-04-16 06:55:34", | ||
| 2473 | + "checkin_type": "QR code", | ||
| 2474 | + "location": { | ||
| 2475 | + "name": "大雁塔文化空间", | ||
| 2476 | + "coordinates": "36.733507,110.478652" | ||
| 2477 | + }, | ||
| 2478 | + "staff_id": null, | ||
| 2479 | + "status": "successful", | ||
| 2480 | + "notes": "", | ||
| 2481 | + "is_late": false | ||
| 2482 | + }, | ||
| 2483 | + { | ||
| 2484 | + "id": "C0169", | ||
| 2485 | + "activity_id": "A0022", | ||
| 2486 | + "user_id": "U0021", | ||
| 2487 | + "registration_id": "R0313", | ||
| 2488 | + "checkin_time": "2025-04-16 06:27:02", | ||
| 2489 | + "checkin_type": "self-service", | ||
| 2490 | + "location": { | ||
| 2491 | + "name": "大雁塔文化空间", | ||
| 2492 | + "coordinates": "38.460924,120.561687" | ||
| 2493 | + }, | ||
| 2494 | + "staff_id": null, | ||
| 2495 | + "status": "successful", | ||
| 2496 | + "notes": "", | ||
| 2497 | + "is_late": false | ||
| 2498 | + }, | ||
| 2499 | + { | ||
| 2500 | + "id": "C0170", | ||
| 2501 | + "activity_id": "A0022", | ||
| 2502 | + "user_id": "U0035", | ||
| 2503 | + "registration_id": "R0314", | ||
| 2504 | + "checkin_time": "2025-04-16 06:31:10", | ||
| 2505 | + "checkin_type": "QR code", | ||
| 2506 | + "location": { | ||
| 2507 | + "name": "大雁塔文化空间", | ||
| 2508 | + "coordinates": "26.603106,100.136011" | ||
| 2509 | + }, | ||
| 2510 | + "staff_id": null, | ||
| 2511 | + "status": "successful", | ||
| 2512 | + "notes": "", | ||
| 2513 | + "is_late": false | ||
| 2514 | + }, | ||
| 2515 | + { | ||
| 2516 | + "id": "C0171", | ||
| 2517 | + "activity_id": "A0022", | ||
| 2518 | + "user_id": "U0009", | ||
| 2519 | + "registration_id": "R0316", | ||
| 2520 | + "checkin_time": "2025-04-16 06:23:40", | ||
| 2521 | + "checkin_type": "manual", | ||
| 2522 | + "location": { | ||
| 2523 | + "name": "大雁塔文化空间", | ||
| 2524 | + "coordinates": "34.533322,104.144383" | ||
| 2525 | + }, | ||
| 2526 | + "staff_id": "O0005", | ||
| 2527 | + "status": "successful", | ||
| 2528 | + "notes": "", | ||
| 2529 | + "is_late": false | ||
| 2530 | + }, | ||
| 2531 | + { | ||
| 2532 | + "id": "C0172", | ||
| 2533 | + "activity_id": "A0022", | ||
| 2534 | + "user_id": "U0015", | ||
| 2535 | + "registration_id": "R0317", | ||
| 2536 | + "checkin_time": "2025-04-16 06:55:20", | ||
| 2537 | + "checkin_type": "QR code", | ||
| 2538 | + "location": { | ||
| 2539 | + "name": "大雁塔文化空间", | ||
| 2540 | + "coordinates": "23.284204,106.163339" | ||
| 2541 | + }, | ||
| 2542 | + "staff_id": null, | ||
| 2543 | + "status": "successful", | ||
| 2544 | + "notes": "热情参与讨论", | ||
| 2545 | + "is_late": false | ||
| 2546 | + }, | ||
| 2547 | + { | ||
| 2548 | + "id": "C0173", | ||
| 2549 | + "activity_id": "A0022", | ||
| 2550 | + "user_id": "U0036", | ||
| 2551 | + "registration_id": "R0318", | ||
| 2552 | + "checkin_time": "2025-04-16 06:47:27", | ||
| 2553 | + "checkin_type": "QR code", | ||
| 2554 | + "location": { | ||
| 2555 | + "name": "大雁塔文化空间", | ||
| 2556 | + "coordinates": "32.940263,122.500088" | ||
| 2557 | + }, | ||
| 2558 | + "staff_id": null, | ||
| 2559 | + "status": "successful", | ||
| 2560 | + "notes": "", | ||
| 2561 | + "is_late": true | ||
| 2562 | + }, | ||
| 2563 | + { | ||
| 2564 | + "id": "C0174", | ||
| 2565 | + "activity_id": "A0022", | ||
| 2566 | + "user_id": "U0012", | ||
| 2567 | + "registration_id": "R0319", | ||
| 2568 | + "checkin_time": "2025-04-16 06:35:18", | ||
| 2569 | + "checkin_type": "QR code", | ||
| 2570 | + "location": { | ||
| 2571 | + "name": "大雁塔文化空间", | ||
| 2572 | + "coordinates": "23.633884,125.935592" | ||
| 2573 | + }, | ||
| 2574 | + "staff_id": null, | ||
| 2575 | + "status": "successful", | ||
| 2576 | + "notes": "", | ||
| 2577 | + "is_late": false | ||
| 2578 | + }, | ||
| 2579 | + { | ||
| 2580 | + "id": "C0175", | ||
| 2581 | + "activity_id": "A0022", | ||
| 2582 | + "user_id": "U0020", | ||
| 2583 | + "registration_id": "R0320", | ||
| 2584 | + "checkin_time": "2025-04-16 06:44:24", | ||
| 2585 | + "checkin_type": "manual", | ||
| 2586 | + "location": { | ||
| 2587 | + "name": "大雁塔文化空间", | ||
| 2588 | + "coordinates": "30.891166,113.054445" | ||
| 2589 | + }, | ||
| 2590 | + "staff_id": "O0005", | ||
| 2591 | + "status": "successful", | ||
| 2592 | + "notes": "", | ||
| 2593 | + "is_late": false | ||
| 2594 | + }, | ||
| 2595 | + { | ||
| 2596 | + "id": "C0176", | ||
| 2597 | + "activity_id": "A0022", | ||
| 2598 | + "user_id": "U0017", | ||
| 2599 | + "registration_id": "R0321", | ||
| 2600 | + "checkin_time": "2025-04-16 06:18:29", | ||
| 2601 | + "checkin_type": "QR code", | ||
| 2602 | + "location": { | ||
| 2603 | + "name": "大雁塔文化空间", | ||
| 2604 | + "coordinates": "38.287921,119.065611" | ||
| 2605 | + }, | ||
| 2606 | + "staff_id": null, | ||
| 2607 | + "status": "successful", | ||
| 2608 | + "notes": "", | ||
| 2609 | + "is_late": false | ||
| 2610 | + }, | ||
| 2611 | + { | ||
| 2612 | + "id": "C0177", | ||
| 2613 | + "activity_id": "A0022", | ||
| 2614 | + "user_id": "U0004", | ||
| 2615 | + "registration_id": "R0324", | ||
| 2616 | + "checkin_time": "2025-04-16 06:48:23", | ||
| 2617 | + "checkin_type": "QR code", | ||
| 2618 | + "location": { | ||
| 2619 | + "name": "大雁塔文化空间", | ||
| 2620 | + "coordinates": "30.466273,121.305050" | ||
| 2621 | + }, | ||
| 2622 | + "staff_id": null, | ||
| 2623 | + "status": "successful", | ||
| 2624 | + "notes": "提前到达", | ||
| 2625 | + "is_late": false | ||
| 2626 | + }, | ||
| 2627 | + { | ||
| 2628 | + "id": "C0178", | ||
| 2629 | + "activity_id": "A0022", | ||
| 2630 | + "user_id": "U0031", | ||
| 2631 | + "registration_id": "R0327", | ||
| 2632 | + "checkin_time": "2025-04-16 06:22:20", | ||
| 2633 | + "checkin_type": "QR code", | ||
| 2634 | + "location": { | ||
| 2635 | + "name": "大雁塔文化空间", | ||
| 2636 | + "coordinates": "30.379818,116.809350" | ||
| 2637 | + }, | ||
| 2638 | + "staff_id": null, | ||
| 2639 | + "status": "successful", | ||
| 2640 | + "notes": "", | ||
| 2641 | + "is_late": false | ||
| 2642 | + }, | ||
| 2643 | + { | ||
| 2644 | + "id": "C0179", | ||
| 2645 | + "activity_id": "A0022", | ||
| 2646 | + "user_id": "U0037", | ||
| 2647 | + "registration_id": "R0328", | ||
| 2648 | + "checkin_time": "2025-04-16 06:28:39", | ||
| 2649 | + "checkin_type": "QR code", | ||
| 2650 | + "location": { | ||
| 2651 | + "name": "大雁塔文化空间", | ||
| 2652 | + "coordinates": "26.477816,122.575710" | ||
| 2653 | + }, | ||
| 2654 | + "staff_id": null, | ||
| 2655 | + "status": "successful", | ||
| 2656 | + "notes": "", | ||
| 2657 | + "is_late": false | ||
| 2658 | + }, | ||
| 2659 | + { | ||
| 2660 | + "id": "C0180", | ||
| 2661 | + "activity_id": "A0022", | ||
| 2662 | + "user_id": "U0007", | ||
| 2663 | + "registration_id": "R0329", | ||
| 2664 | + "checkin_time": "2025-04-16 06:37:26", | ||
| 2665 | + "checkin_type": "QR code", | ||
| 2666 | + "location": { | ||
| 2667 | + "name": "大雁塔文化空间", | ||
| 2668 | + "coordinates": "25.742254,108.270197" | ||
| 2669 | + }, | ||
| 2670 | + "staff_id": null, | ||
| 2671 | + "status": "successful", | ||
| 2672 | + "notes": "", | ||
| 2673 | + "is_late": false | ||
| 2674 | + }, | ||
| 2675 | + { | ||
| 2676 | + "id": "C0181", | ||
| 2677 | + "activity_id": "A0022", | ||
| 2678 | + "user_id": "U0018", | ||
| 2679 | + "registration_id": "R0331", | ||
| 2680 | + "checkin_time": "2025-04-16 06:59:00", | ||
| 2681 | + "checkin_type": "QR code", | ||
| 2682 | + "location": { | ||
| 2683 | + "name": "大雁塔文化空间", | ||
| 2684 | + "coordinates": "27.938128,105.012614" | ||
| 2685 | + }, | ||
| 2686 | + "staff_id": null, | ||
| 2687 | + "status": "successful", | ||
| 2688 | + "notes": "", | ||
| 2689 | + "is_late": false | ||
| 2690 | + }, | ||
| 2691 | + { | ||
| 2692 | + "id": "C0182", | ||
| 2693 | + "activity_id": "A0022", | ||
| 2694 | + "user_id": "U0030", | ||
| 2695 | + "registration_id": "R0332", | ||
| 2696 | + "checkin_time": "2025-04-16 07:01:36", | ||
| 2697 | + "checkin_type": "manual", | ||
| 2698 | + "location": { | ||
| 2699 | + "name": "大雁塔文化空间", | ||
| 2700 | + "coordinates": "39.677261,117.105251" | ||
| 2701 | + }, | ||
| 2702 | + "staff_id": "O0005", | ||
| 2703 | + "status": "successful", | ||
| 2704 | + "notes": "", | ||
| 2705 | + "is_late": true | ||
| 2706 | + }, | ||
| 2707 | + { | ||
| 2708 | + "id": "C0183", | ||
| 2709 | + "activity_id": "A0022", | ||
| 2710 | + "user_id": "U0006", | ||
| 2711 | + "registration_id": "R0333", | ||
| 2712 | + "checkin_time": "2025-04-16 06:51:37", | ||
| 2713 | + "checkin_type": "QR code", | ||
| 2714 | + "location": { | ||
| 2715 | + "name": "大雁塔文化空间", | ||
| 2716 | + "coordinates": "26.249063,116.245331" | ||
| 2717 | + }, | ||
| 2718 | + "staff_id": null, | ||
| 2719 | + "status": "successful", | ||
| 2720 | + "notes": "", | ||
| 2721 | + "is_late": false | ||
| 2722 | + }, | ||
| 2723 | + { | ||
| 2724 | + "id": "C0184", | ||
| 2725 | + "activity_id": "A0022", | ||
| 2726 | + "user_id": "U0014", | ||
| 2727 | + "registration_id": "R0336", | ||
| 2728 | + "checkin_time": "2025-04-16 06:33:41", | ||
| 2729 | + "checkin_type": "QR code", | ||
| 2730 | + "location": { | ||
| 2731 | + "name": "大雁塔文化空间", | ||
| 2732 | + "coordinates": "32.162403,115.813070" | ||
| 2733 | + }, | ||
| 2734 | + "staff_id": null, | ||
| 2735 | + "status": "successful", | ||
| 2736 | + "notes": "", | ||
| 2737 | + "is_late": false | ||
| 2738 | + }, | ||
| 2739 | + { | ||
| 2740 | + "id": "C0185", | ||
| 2741 | + "activity_id": "A0022", | ||
| 2742 | + "user_id": "U0024", | ||
| 2743 | + "registration_id": "R0338", | ||
| 2744 | + "checkin_time": "2025-04-16 06:54:14", | ||
| 2745 | + "checkin_type": "QR code", | ||
| 2746 | + "location": { | ||
| 2747 | + "name": "大雁塔文化空间", | ||
| 2748 | + "coordinates": "25.927681,123.295939" | ||
| 2749 | + }, | ||
| 2750 | + "staff_id": null, | ||
| 2751 | + "status": "successful", | ||
| 2752 | + "notes": "", | ||
| 2753 | + "is_late": false | ||
| 2754 | + }, | ||
| 2755 | + { | ||
| 2756 | + "id": "C0186", | ||
| 2757 | + "activity_id": "A0022", | ||
| 2758 | + "user_id": "U0003", | ||
| 2759 | + "registration_id": "R0339", | ||
| 2760 | + "checkin_time": "2025-04-16 06:37:10", | ||
| 2761 | + "checkin_type": "QR code", | ||
| 2762 | + "location": { | ||
| 2763 | + "name": "大雁塔文化空间", | ||
| 2764 | + "coordinates": "24.967249,100.833877" | ||
| 2765 | + }, | ||
| 2766 | + "staff_id": null, | ||
| 2767 | + "status": "successful", | ||
| 2768 | + "notes": "", | ||
| 2769 | + "is_late": false | ||
| 2770 | + }, | ||
| 2771 | + { | ||
| 2772 | + "id": "C0187", | ||
| 2773 | + "activity_id": "A0022", | ||
| 2774 | + "user_id": "U0033", | ||
| 2775 | + "registration_id": "R0340", | ||
| 2776 | + "checkin_time": "2025-04-16 06:40:31", | ||
| 2777 | + "checkin_type": "QR code", | ||
| 2778 | + "location": { | ||
| 2779 | + "name": "大雁塔文化空间", | ||
| 2780 | + "coordinates": "34.843743,113.933664" | ||
| 2781 | + }, | ||
| 2782 | + "staff_id": null, | ||
| 2783 | + "status": "successful", | ||
| 2784 | + "notes": "", | ||
| 2785 | + "is_late": false | ||
| 2786 | + }, | ||
| 2787 | + { | ||
| 2788 | + "id": "C0188", | ||
| 2789 | + "activity_id": "A0022", | ||
| 2790 | + "user_id": "U0011", | ||
| 2791 | + "registration_id": "R0342", | ||
| 2792 | + "checkin_time": "2025-04-16 06:44:31", | ||
| 2793 | + "checkin_type": "QR code", | ||
| 2794 | + "location": { | ||
| 2795 | + "name": "大雁塔文化空间", | ||
| 2796 | + "coordinates": "38.968901,123.655330" | ||
| 2797 | + }, | ||
| 2798 | + "staff_id": null, | ||
| 2799 | + "status": "successful", | ||
| 2800 | + "notes": "", | ||
| 2801 | + "is_late": true | ||
| 2802 | + }, | ||
| 2803 | + { | ||
| 2804 | + "id": "C0189", | ||
| 2805 | + "activity_id": "A0022", | ||
| 2806 | + "user_id": "U0005", | ||
| 2807 | + "registration_id": "R0343", | ||
| 2808 | + "checkin_time": "2025-04-16 06:18:06", | ||
| 2809 | + "checkin_type": "self-service", | ||
| 2810 | + "location": { | ||
| 2811 | + "name": "大雁塔文化空间", | ||
| 2812 | + "coordinates": "22.517659,116.229674" | ||
| 2813 | + }, | ||
| 2814 | + "staff_id": null, | ||
| 2815 | + "status": "successful", | ||
| 2816 | + "notes": "", | ||
| 2817 | + "is_late": false | ||
| 2818 | + }, | ||
| 2819 | + { | ||
| 2820 | + "id": "C0190", | ||
| 2821 | + "activity_id": "A0023", | ||
| 2822 | + "user_id": "U0014", | ||
| 2823 | + "registration_id": "R0344", | ||
| 2824 | + "checkin_time": "2025-03-27 05:16:40", | ||
| 2825 | + "checkin_type": "QR code", | ||
| 2826 | + "location": null, | ||
| 2827 | + "staff_id": null, | ||
| 2828 | + "status": "successful", | ||
| 2829 | + "notes": "提前到达", | ||
| 2830 | + "is_late": false | ||
| 2831 | + }, | ||
| 2832 | + { | ||
| 2833 | + "id": "C0191", | ||
| 2834 | + "activity_id": "A0023", | ||
| 2835 | + "user_id": "U0006", | ||
| 2836 | + "registration_id": "R0346", | ||
| 2837 | + "checkin_time": "2025-03-27 05:35:36", | ||
| 2838 | + "checkin_type": "QR code", | ||
| 2839 | + "location": null, | ||
| 2840 | + "staff_id": null, | ||
| 2841 | + "status": "successful", | ||
| 2842 | + "notes": "提前到达", | ||
| 2843 | + "is_late": false | ||
| 2844 | + }, | ||
| 2845 | + { | ||
| 2846 | + "id": "C0192", | ||
| 2847 | + "activity_id": "A0023", | ||
| 2848 | + "user_id": "U0030", | ||
| 2849 | + "registration_id": "R0347", | ||
| 2850 | + "checkin_time": "2025-03-27 05:23:26", | ||
| 2851 | + "checkin_type": "QR code", | ||
| 2852 | + "location": null, | ||
| 2853 | + "staff_id": null, | ||
| 2854 | + "status": "successful", | ||
| 2855 | + "notes": "", | ||
| 2856 | + "is_late": false | ||
| 2857 | + }, | ||
| 2858 | + { | ||
| 2859 | + "id": "C0193", | ||
| 2860 | + "activity_id": "A0023", | ||
| 2861 | + "user_id": "U0035", | ||
| 2862 | + "registration_id": "R0348", | ||
| 2863 | + "checkin_time": "2025-03-27 05:11:26", | ||
| 2864 | + "checkin_type": "QR code", | ||
| 2865 | + "location": null, | ||
| 2866 | + "staff_id": null, | ||
| 2867 | + "status": "successful", | ||
| 2868 | + "notes": "", | ||
| 2869 | + "is_late": false | ||
| 2870 | + }, | ||
| 2871 | + { | ||
| 2872 | + "id": "C0194", | ||
| 2873 | + "activity_id": "A0023", | ||
| 2874 | + "user_id": "U0007", | ||
| 2875 | + "registration_id": "R0350", | ||
| 2876 | + "checkin_time": "2025-03-27 05:05:40", | ||
| 2877 | + "checkin_type": "QR code", | ||
| 2878 | + "location": null, | ||
| 2879 | + "staff_id": null, | ||
| 2880 | + "status": "failed", | ||
| 2881 | + "notes": "签到后临时离开", | ||
| 2882 | + "is_late": false | ||
| 2883 | + }, | ||
| 2884 | + { | ||
| 2885 | + "id": "C0195", | ||
| 2886 | + "activity_id": "A0023", | ||
| 2887 | + "user_id": "U0016", | ||
| 2888 | + "registration_id": "R0351", | ||
| 2889 | + "checkin_time": "2025-03-27 05:30:46", | ||
| 2890 | + "checkin_type": "QR code", | ||
| 2891 | + "location": null, | ||
| 2892 | + "staff_id": null, | ||
| 2893 | + "status": "successful", | ||
| 2894 | + "notes": "", | ||
| 2895 | + "is_late": true | ||
| 2896 | + }, | ||
| 2897 | + { | ||
| 2898 | + "id": "C0196", | ||
| 2899 | + "activity_id": "A0023", | ||
| 2900 | + "user_id": "U0011", | ||
| 2901 | + "registration_id": "R0352", | ||
| 2902 | + "checkin_time": "2025-03-27 05:32:44", | ||
| 2903 | + "checkin_type": "manual", | ||
| 2904 | + "location": null, | ||
| 2905 | + "staff_id": "O0007", | ||
| 2906 | + "status": "successful", | ||
| 2907 | + "notes": "", | ||
| 2908 | + "is_late": false | ||
| 2909 | + }, | ||
| 2910 | + { | ||
| 2911 | + "id": "C0197", | ||
| 2912 | + "activity_id": "A0023", | ||
| 2913 | + "user_id": "U0003", | ||
| 2914 | + "registration_id": "R0353", | ||
| 2915 | + "checkin_time": "2025-03-27 05:31:42", | ||
| 2916 | + "checkin_type": "QR code", | ||
| 2917 | + "location": null, | ||
| 2918 | + "staff_id": null, | ||
| 2919 | + "status": "successful", | ||
| 2920 | + "notes": "提前到达", | ||
| 2921 | + "is_late": false | ||
| 2922 | + }, | ||
| 2923 | + { | ||
| 2924 | + "id": "C0198", | ||
| 2925 | + "activity_id": "A0023", | ||
| 2926 | + "user_id": "U0029", | ||
| 2927 | + "registration_id": "R0354", | ||
| 2928 | + "checkin_time": "2025-03-27 04:59:34", | ||
| 2929 | + "checkin_type": "QR code", | ||
| 2930 | + "location": null, | ||
| 2931 | + "staff_id": null, | ||
| 2932 | + "status": "successful", | ||
| 2933 | + "notes": "", | ||
| 2934 | + "is_late": false | ||
| 2935 | + }, | ||
| 2936 | + { | ||
| 2937 | + "id": "C0199", | ||
| 2938 | + "activity_id": "A0023", | ||
| 2939 | + "user_id": "U0034", | ||
| 2940 | + "registration_id": "R0355", | ||
| 2941 | + "checkin_time": "2025-03-27 05:32:02", | ||
| 2942 | + "checkin_type": "manual", | ||
| 2943 | + "location": null, | ||
| 2944 | + "staff_id": "O0007", | ||
| 2945 | + "status": "successful", | ||
| 2946 | + "notes": "", | ||
| 2947 | + "is_late": true | ||
| 2948 | + }, | ||
| 2949 | + { | ||
| 2950 | + "id": "C0200", | ||
| 2951 | + "activity_id": "A0023", | ||
| 2952 | + "user_id": "U0002", | ||
| 2953 | + "registration_id": "R0356", | ||
| 2954 | + "checkin_time": "2025-03-27 05:26:35", | ||
| 2955 | + "checkin_type": "QR code", | ||
| 2956 | + "location": null, | ||
| 2957 | + "staff_id": null, | ||
| 2958 | + "status": "successful", | ||
| 2959 | + "notes": "", | ||
| 2960 | + "is_late": false | ||
| 2961 | + }, | ||
| 2962 | + { | ||
| 2963 | + "id": "C0201", | ||
| 2964 | + "activity_id": "A0023", | ||
| 2965 | + "user_id": "U0026", | ||
| 2966 | + "registration_id": "R0357", | ||
| 2967 | + "checkin_time": "2025-03-27 05:05:43", | ||
| 2968 | + "checkin_type": "manual", | ||
| 2969 | + "location": null, | ||
| 2970 | + "staff_id": "O0007", | ||
| 2971 | + "status": "successful", | ||
| 2972 | + "notes": "按时到达", | ||
| 2973 | + "is_late": false | ||
| 2974 | + }, | ||
| 2975 | + { | ||
| 2976 | + "id": "C0202", | ||
| 2977 | + "activity_id": "A0023", | ||
| 2978 | + "user_id": "U0008", | ||
| 2979 | + "registration_id": "R0358", | ||
| 2980 | + "checkin_time": "2025-03-27 05:26:39", | ||
| 2981 | + "checkin_type": "manual", | ||
| 2982 | + "location": null, | ||
| 2983 | + "staff_id": "O0007", | ||
| 2984 | + "status": "successful", | ||
| 2985 | + "notes": "", | ||
| 2986 | + "is_late": false | ||
| 2987 | + }, | ||
| 2988 | + { | ||
| 2989 | + "id": "C0203", | ||
| 2990 | + "activity_id": "A0023", | ||
| 2991 | + "user_id": "U0020", | ||
| 2992 | + "registration_id": "R0360", | ||
| 2993 | + "checkin_time": "2025-03-27 05:57:08", | ||
| 2994 | + "checkin_type": "manual", | ||
| 2995 | + "location": null, | ||
| 2996 | + "staff_id": "O0007", | ||
| 2997 | + "status": "successful", | ||
| 2998 | + "notes": "", | ||
| 2999 | + "is_late": true | ||
| 3000 | + }, | ||
| 3001 | + { | ||
| 3002 | + "id": "C0204", | ||
| 3003 | + "activity_id": "A0023", | ||
| 3004 | + "user_id": "U0038", | ||
| 3005 | + "registration_id": "R0361", | ||
| 3006 | + "checkin_time": "2025-03-27 05:23:01", | ||
| 3007 | + "checkin_type": "QR code", | ||
| 3008 | + "location": null, | ||
| 3009 | + "staff_id": null, | ||
| 3010 | + "status": "successful", | ||
| 3011 | + "notes": "热情参与讨论", | ||
| 3012 | + "is_late": false | ||
| 3013 | + }, | ||
| 3014 | + { | ||
| 3015 | + "id": "C0205", | ||
| 3016 | + "activity_id": "A0023", | ||
| 3017 | + "user_id": "U0024", | ||
| 3018 | + "registration_id": "R0362", | ||
| 3019 | + "checkin_time": "2025-03-27 05:33:56", | ||
| 3020 | + "checkin_type": "QR code", | ||
| 3021 | + "location": null, | ||
| 3022 | + "staff_id": null, | ||
| 3023 | + "status": "successful", | ||
| 3024 | + "notes": "", | ||
| 3025 | + "is_late": false | ||
| 3026 | + }, | ||
| 3027 | + { | ||
| 3028 | + "id": "C0206", | ||
| 3029 | + "activity_id": "A0023", | ||
| 3030 | + "user_id": "U0025", | ||
| 3031 | + "registration_id": "R0363", | ||
| 3032 | + "checkin_time": "2025-03-27 05:23:06", | ||
| 3033 | + "checkin_type": "self-service", | ||
| 3034 | + "location": null, | ||
| 3035 | + "staff_id": null, | ||
| 3036 | + "status": "successful", | ||
| 3037 | + "notes": "", | ||
| 3038 | + "is_late": false | ||
| 3039 | + }, | ||
| 3040 | + { | ||
| 3041 | + "id": "C0207", | ||
| 3042 | + "activity_id": "A0023", | ||
| 3043 | + "user_id": "U0001", | ||
| 3044 | + "registration_id": "R0365", | ||
| 3045 | + "checkin_time": "2025-03-27 05:18:27", | ||
| 3046 | + "checkin_type": "QR code", | ||
| 3047 | + "location": null, | ||
| 3048 | + "staff_id": null, | ||
| 3049 | + "status": "successful", | ||
| 3050 | + "notes": "", | ||
| 3051 | + "is_late": true | ||
| 3052 | + }, | ||
| 3053 | + { | ||
| 3054 | + "id": "C0208", | ||
| 3055 | + "activity_id": "A0023", | ||
| 3056 | + "user_id": "U0019", | ||
| 3057 | + "registration_id": "R0366", | ||
| 3058 | + "checkin_time": "2025-03-27 05:34:53", | ||
| 3059 | + "checkin_type": "QR code", | ||
| 3060 | + "location": null, | ||
| 3061 | + "staff_id": null, | ||
| 3062 | + "status": "successful", | ||
| 3063 | + "notes": "", | ||
| 3064 | + "is_late": false | ||
| 3065 | + }, | ||
| 3066 | + { | ||
| 3067 | + "id": "C0209", | ||
| 3068 | + "activity_id": "A0023", | ||
| 3069 | + "user_id": "U0027", | ||
| 3070 | + "registration_id": "R0370", | ||
| 3071 | + "checkin_time": "2025-03-27 05:33:23", | ||
| 3072 | + "checkin_type": "QR code", | ||
| 3073 | + "location": null, | ||
| 3074 | + "staff_id": null, | ||
| 3075 | + "status": "successful", | ||
| 3076 | + "notes": "提前到达", | ||
| 3077 | + "is_late": true | ||
| 3078 | + }, | ||
| 3079 | + { | ||
| 3080 | + "id": "C0210", | ||
| 3081 | + "activity_id": "A0023", | ||
| 3082 | + "user_id": "U0036", | ||
| 3083 | + "registration_id": "R0371", | ||
| 3084 | + "checkin_time": "2025-03-27 05:22:50", | ||
| 3085 | + "checkin_type": "manual", | ||
| 3086 | + "location": null, | ||
| 3087 | + "staff_id": "O0007", | ||
| 3088 | + "status": "successful", | ||
| 3089 | + "notes": "", | ||
| 3090 | + "is_late": false | ||
| 3091 | + }, | ||
| 3092 | + { | ||
| 3093 | + "id": "C0211", | ||
| 3094 | + "activity_id": "A0023", | ||
| 3095 | + "user_id": "U0031", | ||
| 3096 | + "registration_id": "R0373", | ||
| 3097 | + "checkin_time": "2025-03-27 05:34:33", | ||
| 3098 | + "checkin_type": "manual", | ||
| 3099 | + "location": null, | ||
| 3100 | + "staff_id": "O0007", | ||
| 3101 | + "status": "successful", | ||
| 3102 | + "notes": "提前到达", | ||
| 3103 | + "is_late": false | ||
| 3104 | + }, | ||
| 3105 | + { | ||
| 3106 | + "id": "C0212", | ||
| 3107 | + "activity_id": "A0023", | ||
| 3108 | + "user_id": "U0037", | ||
| 3109 | + "registration_id": "R0374", | ||
| 3110 | + "checkin_time": "2025-03-27 05:27:34", | ||
| 3111 | + "checkin_type": "QR code", | ||
| 3112 | + "location": null, | ||
| 3113 | + "staff_id": null, | ||
| 3114 | + "status": "successful", | ||
| 3115 | + "notes": "热情参与讨论", | ||
| 3116 | + "is_late": false | ||
| 3117 | + }, | ||
| 3118 | + { | ||
| 3119 | + "id": "C0213", | ||
| 3120 | + "activity_id": "A0023", | ||
| 3121 | + "user_id": "U0013", | ||
| 3122 | + "registration_id": "R0375", | ||
| 3123 | + "checkin_time": "2025-03-27 05:23:16", | ||
| 3124 | + "checkin_type": "QR code", | ||
| 3125 | + "location": null, | ||
| 3126 | + "staff_id": null, | ||
| 3127 | + "status": "successful", | ||
| 3128 | + "notes": "带了书本", | ||
| 3129 | + "is_late": false | ||
| 3130 | + }, | ||
| 3131 | + { | ||
| 3132 | + "id": "C0214", | ||
| 3133 | + "activity_id": "A0023", | ||
| 3134 | + "user_id": "U0005", | ||
| 3135 | + "registration_id": "R0376", | ||
| 3136 | + "checkin_time": "2025-03-27 05:11:53", | ||
| 3137 | + "checkin_type": "QR code", | ||
| 3138 | + "location": null, | ||
| 3139 | + "staff_id": null, | ||
| 3140 | + "status": "failed", | ||
| 3141 | + "notes": "网络连接不稳定", | ||
| 3142 | + "is_late": false | ||
| 3143 | + }, | ||
| 3144 | + { | ||
| 3145 | + "id": "C0215", | ||
| 3146 | + "activity_id": "A0023", | ||
| 3147 | + "user_id": "U0039", | ||
| 3148 | + "registration_id": "R0377", | ||
| 3149 | + "checkin_time": "2025-03-27 05:01:36", | ||
| 3150 | + "checkin_type": "manual", | ||
| 3151 | + "location": null, | ||
| 3152 | + "staff_id": "O0007", | ||
| 3153 | + "status": "successful", | ||
| 3154 | + "notes": "", | ||
| 3155 | + "is_late": false | ||
| 3156 | + }, | ||
| 3157 | + { | ||
| 3158 | + "id": "C0216", | ||
| 3159 | + "activity_id": "A0023", | ||
| 3160 | + "user_id": "U0017", | ||
| 3161 | + "registration_id": "R0379", | ||
| 3162 | + "checkin_time": "2025-03-27 05:31:07", | ||
| 3163 | + "checkin_type": "QR code", | ||
| 3164 | + "location": null, | ||
| 3165 | + "staff_id": null, | ||
| 3166 | + "status": "successful", | ||
| 3167 | + "notes": "", | ||
| 3168 | + "is_late": false | ||
| 3169 | + }, | ||
| 3170 | + { | ||
| 3171 | + "id": "C0217", | ||
| 3172 | + "activity_id": "A0023", | ||
| 3173 | + "user_id": "U0004", | ||
| 3174 | + "registration_id": "R0380", | ||
| 3175 | + "checkin_time": "2025-03-27 05:42:59", | ||
| 3176 | + "checkin_type": "manual", | ||
| 3177 | + "location": null, | ||
| 3178 | + "staff_id": "O0007", | ||
| 3179 | + "status": "successful", | ||
| 3180 | + "notes": "准备充分", | ||
| 3181 | + "is_late": false | ||
| 3182 | + }, | ||
| 3183 | + { | ||
| 3184 | + "id": "C0218", | ||
| 3185 | + "activity_id": "A0023", | ||
| 3186 | + "user_id": "U0015", | ||
| 3187 | + "registration_id": "R0381", | ||
| 3188 | + "checkin_time": "2025-03-27 05:45:54", | ||
| 3189 | + "checkin_type": "self-service", | ||
| 3190 | + "location": null, | ||
| 3191 | + "staff_id": null, | ||
| 3192 | + "status": "successful", | ||
| 3193 | + "notes": "", | ||
| 3194 | + "is_late": true | ||
| 3195 | + }, | ||
| 3196 | + { | ||
| 3197 | + "id": "C0219", | ||
| 3198 | + "activity_id": "A0023", | ||
| 3199 | + "user_id": "U0009", | ||
| 3200 | + "registration_id": "R0382", | ||
| 3201 | + "checkin_time": "2025-03-27 05:26:18", | ||
| 3202 | + "checkin_type": "manual", | ||
| 3203 | + "location": null, | ||
| 3204 | + "staff_id": "O0007", | ||
| 3205 | + "status": "successful", | ||
| 3206 | + "notes": "带了书本", | ||
| 3207 | + "is_late": true | ||
| 3208 | + }, | ||
| 3209 | + { | ||
| 3210 | + "id": "C0220", | ||
| 3211 | + "activity_id": "A0023", | ||
| 3212 | + "user_id": "U0040", | ||
| 3213 | + "registration_id": "R0383", | ||
| 3214 | + "checkin_time": "2025-03-27 05:30:24", | ||
| 3215 | + "checkin_type": "QR code", | ||
| 3216 | + "location": null, | ||
| 3217 | + "staff_id": null, | ||
| 3218 | + "status": "successful", | ||
| 3219 | + "notes": "", | ||
| 3220 | + "is_late": false | ||
| 3221 | + }, | ||
| 3222 | + { | ||
| 3223 | + "id": "C0221", | ||
| 3224 | + "activity_id": "A0027", | ||
| 3225 | + "user_id": "U0017", | ||
| 3226 | + "registration_id": "R0407", | ||
| 3227 | + "checkin_time": "2025-04-16 05:32:53", | ||
| 3228 | + "checkin_type": "QR code", | ||
| 3229 | + "location": { | ||
| 3230 | + "name": "大雁塔文化空间", | ||
| 3231 | + "coordinates": "38.833814,114.514317" | ||
| 3232 | + }, | ||
| 3233 | + "staff_id": null, | ||
| 3234 | + "status": "successful", | ||
| 3235 | + "notes": "提前到达", | ||
| 3236 | + "is_late": true | ||
| 3237 | + }, | ||
| 3238 | + { | ||
| 3239 | + "id": "C0222", | ||
| 3240 | + "activity_id": "A0027", | ||
| 3241 | + "user_id": "U0031", | ||
| 3242 | + "registration_id": "R0408", | ||
| 3243 | + "checkin_time": "2025-04-16 05:46:08", | ||
| 3244 | + "checkin_type": "self-service", | ||
| 3245 | + "location": { | ||
| 3246 | + "name": "大雁塔文化空间", | ||
| 3247 | + "coordinates": "27.781089,102.822173" | ||
| 3248 | + }, | ||
| 3249 | + "staff_id": null, | ||
| 3250 | + "status": "successful", | ||
| 3251 | + "notes": "", | ||
| 3252 | + "is_late": false | ||
| 3253 | + }, | ||
| 3254 | + { | ||
| 3255 | + "id": "C0223", | ||
| 3256 | + "activity_id": "A0027", | ||
| 3257 | + "user_id": "U0029", | ||
| 3258 | + "registration_id": "R0410", | ||
| 3259 | + "checkin_time": "2025-04-16 05:47:53", | ||
| 3260 | + "checkin_type": "QR code", | ||
| 3261 | + "location": { | ||
| 3262 | + "name": "大雁塔文化空间", | ||
| 3263 | + "coordinates": "27.308599,114.704434" | ||
| 3264 | + }, | ||
| 3265 | + "staff_id": null, | ||
| 3266 | + "status": "successful", | ||
| 3267 | + "notes": "", | ||
| 3268 | + "is_late": false | ||
| 3269 | + }, | ||
| 3270 | + { | ||
| 3271 | + "id": "C0224", | ||
| 3272 | + "activity_id": "A0027", | ||
| 3273 | + "user_id": "U0007", | ||
| 3274 | + "registration_id": "R0411", | ||
| 3275 | + "checkin_time": "2025-04-16 05:40:07", | ||
| 3276 | + "checkin_type": "QR code", | ||
| 3277 | + "location": { | ||
| 3278 | + "name": "大雁塔文化空间", | ||
| 3279 | + "coordinates": "38.156809,110.024987" | ||
| 3280 | + }, | ||
| 3281 | + "staff_id": null, | ||
| 3282 | + "status": "successful", | ||
| 3283 | + "notes": "", | ||
| 3284 | + "is_late": false | ||
| 3285 | + }, | ||
| 3286 | + { | ||
| 3287 | + "id": "C0225", | ||
| 3288 | + "activity_id": "A0027", | ||
| 3289 | + "user_id": "U0022", | ||
| 3290 | + "registration_id": "R0414", | ||
| 3291 | + "checkin_time": "2025-04-16 05:55:30", | ||
| 3292 | + "checkin_type": "QR code", | ||
| 3293 | + "location": { | ||
| 3294 | + "name": "大雁塔文化空间", | ||
| 3295 | + "coordinates": "30.231849,102.497485" | ||
| 3296 | + }, | ||
| 3297 | + "staff_id": null, | ||
| 3298 | + "status": "successful", | ||
| 3299 | + "notes": "", | ||
| 3300 | + "is_late": true | ||
| 3301 | + }, | ||
| 3302 | + { | ||
| 3303 | + "id": "C0226", | ||
| 3304 | + "activity_id": "A0027", | ||
| 3305 | + "user_id": "U0027", | ||
| 3306 | + "registration_id": "R0417", | ||
| 3307 | + "checkin_time": "2025-04-16 05:54:23", | ||
| 3308 | + "checkin_type": "QR code", | ||
| 3309 | + "location": { | ||
| 3310 | + "name": "大雁塔文化空间", | ||
| 3311 | + "coordinates": "30.564601,104.408038" | ||
| 3312 | + }, | ||
| 3313 | + "staff_id": null, | ||
| 3314 | + "status": "successful", | ||
| 3315 | + "notes": "", | ||
| 3316 | + "is_late": true | ||
| 3317 | + }, | ||
| 3318 | + { | ||
| 3319 | + "id": "C0227", | ||
| 3320 | + "activity_id": "A0027", | ||
| 3321 | + "user_id": "U0005", | ||
| 3322 | + "registration_id": "R0418", | ||
| 3323 | + "checkin_time": "2025-04-16 05:47:45", | ||
| 3324 | + "checkin_type": "QR code", | ||
| 3325 | + "location": { | ||
| 3326 | + "name": "大雁塔文化空间", | ||
| 3327 | + "coordinates": "24.122715,109.827973" | ||
| 3328 | + }, | ||
| 3329 | + "staff_id": null, | ||
| 3330 | + "status": "successful", | ||
| 3331 | + "notes": "", | ||
| 3332 | + "is_late": false | ||
| 3333 | + }, | ||
| 3334 | + { | ||
| 3335 | + "id": "C0228", | ||
| 3336 | + "activity_id": "A0027", | ||
| 3337 | + "user_id": "U0013", | ||
| 3338 | + "registration_id": "R0419", | ||
| 3339 | + "checkin_time": "2025-04-16 05:27:24", | ||
| 3340 | + "checkin_type": "QR code", | ||
| 3341 | + "location": { | ||
| 3342 | + "name": "大雁塔文化空间", | ||
| 3343 | + "coordinates": "25.549267,111.522543" | ||
| 3344 | + }, | ||
| 3345 | + "staff_id": null, | ||
| 3346 | + "status": "successful", | ||
| 3347 | + "notes": "", | ||
| 3348 | + "is_late": true | ||
| 3349 | + }, | ||
| 3350 | + { | ||
| 3351 | + "id": "C0229", | ||
| 3352 | + "activity_id": "A0027", | ||
| 3353 | + "user_id": "U0037", | ||
| 3354 | + "registration_id": "R0421", | ||
| 3355 | + "checkin_time": "2025-04-16 05:22:07", | ||
| 3356 | + "checkin_type": "QR code", | ||
| 3357 | + "location": { | ||
| 3358 | + "name": "大雁塔文化空间", | ||
| 3359 | + "coordinates": "26.680011,113.731917" | ||
| 3360 | + }, | ||
| 3361 | + "staff_id": null, | ||
| 3362 | + "status": "successful", | ||
| 3363 | + "notes": "准备充分", | ||
| 3364 | + "is_late": true | ||
| 3365 | + }, | ||
| 3366 | + { | ||
| 3367 | + "id": "C0230", | ||
| 3368 | + "activity_id": "A0027", | ||
| 3369 | + "user_id": "U0012", | ||
| 3370 | + "registration_id": "R0422", | ||
| 3371 | + "checkin_time": "2025-04-16 05:08:30", | ||
| 3372 | + "checkin_type": "QR code", | ||
| 3373 | + "location": { | ||
| 3374 | + "name": "大雁塔文化空间", | ||
| 3375 | + "coordinates": "30.777704,110.012542" | ||
| 3376 | + }, | ||
| 3377 | + "staff_id": null, | ||
| 3378 | + "status": "successful", | ||
| 3379 | + "notes": "按时到达", | ||
| 3380 | + "is_late": false | ||
| 3381 | + }, | ||
| 3382 | + { | ||
| 3383 | + "id": "C0231", | ||
| 3384 | + "activity_id": "A0027", | ||
| 3385 | + "user_id": "U0024", | ||
| 3386 | + "registration_id": "R0423", | ||
| 3387 | + "checkin_time": "2025-04-16 05:24:15", | ||
| 3388 | + "checkin_type": "QR code", | ||
| 3389 | + "location": { | ||
| 3390 | + "name": "大雁塔文化空间", | ||
| 3391 | + "coordinates": "30.010222,103.940968" | ||
| 3392 | + }, | ||
| 3393 | + "staff_id": null, | ||
| 3394 | + "status": "successful", | ||
| 3395 | + "notes": "提前到达", | ||
| 3396 | + "is_late": true | ||
| 3397 | + }, | ||
| 3398 | + { | ||
| 3399 | + "id": "C0232", | ||
| 3400 | + "activity_id": "A0027", | ||
| 3401 | + "user_id": "U0006", | ||
| 3402 | + "registration_id": "R0424", | ||
| 3403 | + "checkin_time": "2025-04-16 05:08:05", | ||
| 3404 | + "checkin_type": "QR code", | ||
| 3405 | + "location": { | ||
| 3406 | + "name": "大雁塔文化空间", | ||
| 3407 | + "coordinates": "33.278353,101.387988" | ||
| 3408 | + }, | ||
| 3409 | + "staff_id": null, | ||
| 3410 | + "status": "successful", | ||
| 3411 | + "notes": "", | ||
| 3412 | + "is_late": false | ||
| 3413 | + }, | ||
| 3414 | + { | ||
| 3415 | + "id": "C0233", | ||
| 3416 | + "activity_id": "A0030", | ||
| 3417 | + "user_id": "U0022", | ||
| 3418 | + "registration_id": "R0441", | ||
| 3419 | + "checkin_time": "2025-03-24 06:13:41", | ||
| 3420 | + "checkin_type": "QR code", | ||
| 3421 | + "location": { | ||
| 3422 | + "name": "大雁塔文化空间", | ||
| 3423 | + "coordinates": "28.787895,119.435720" | ||
| 3424 | + }, | ||
| 3425 | + "staff_id": null, | ||
| 3426 | + "status": "successful", | ||
| 3427 | + "notes": "按时到达", | ||
| 3428 | + "is_late": false | ||
| 3429 | + }, | ||
| 3430 | + { | ||
| 3431 | + "id": "C0234", | ||
| 3432 | + "activity_id": "A0030", | ||
| 3433 | + "user_id": "U0031", | ||
| 3434 | + "registration_id": "R0442", | ||
| 3435 | + "checkin_time": "2025-03-24 06:14:40", | ||
| 3436 | + "checkin_type": "manual", | ||
| 3437 | + "location": { | ||
| 3438 | + "name": "大雁塔文化空间", | ||
| 3439 | + "coordinates": "38.127912,104.147554" | ||
| 3440 | + }, | ||
| 3441 | + "staff_id": "O0005", | ||
| 3442 | + "status": "successful", | ||
| 3443 | + "notes": "", | ||
| 3444 | + "is_late": false | ||
| 3445 | + }, | ||
| 3446 | + { | ||
| 3447 | + "id": "C0235", | ||
| 3448 | + "activity_id": "A0030", | ||
| 3449 | + "user_id": "U0003", | ||
| 3450 | + "registration_id": "R0443", | ||
| 3451 | + "checkin_time": "2025-03-24 06:12:05", | ||
| 3452 | + "checkin_type": "QR code", | ||
| 3453 | + "location": { | ||
| 3454 | + "name": "大雁塔文化空间", | ||
| 3455 | + "coordinates": "36.552893,123.319240" | ||
| 3456 | + }, | ||
| 3457 | + "staff_id": null, | ||
| 3458 | + "status": "successful", | ||
| 3459 | + "notes": "", | ||
| 3460 | + "is_late": false | ||
| 3461 | + }, | ||
| 3462 | + { | ||
| 3463 | + "id": "C0236", | ||
| 3464 | + "activity_id": "A0030", | ||
| 3465 | + "user_id": "U0030", | ||
| 3466 | + "registration_id": "R0444", | ||
| 3467 | + "checkin_time": "2025-03-24 06:35:57", | ||
| 3468 | + "checkin_type": "QR code", | ||
| 3469 | + "location": { | ||
| 3470 | + "name": "大雁塔文化空间", | ||
| 3471 | + "coordinates": "37.606920,110.862144" | ||
| 3472 | + }, | ||
| 3473 | + "staff_id": null, | ||
| 3474 | + "status": "successful", | ||
| 3475 | + "notes": "", | ||
| 3476 | + "is_late": false | ||
| 3477 | + }, | ||
| 3478 | + { | ||
| 3479 | + "id": "C0237", | ||
| 3480 | + "activity_id": "A0030", | ||
| 3481 | + "user_id": "U0028", | ||
| 3482 | + "registration_id": "R0445", | ||
| 3483 | + "checkin_time": "2025-03-24 06:21:00", | ||
| 3484 | + "checkin_type": "manual", | ||
| 3485 | + "location": { | ||
| 3486 | + "name": "大雁塔文化空间", | ||
| 3487 | + "coordinates": "36.680083,106.083682" | ||
| 3488 | + }, | ||
| 3489 | + "staff_id": "O0005", | ||
| 3490 | + "status": "successful", | ||
| 3491 | + "notes": "", | ||
| 3492 | + "is_late": true | ||
| 3493 | + }, | ||
| 3494 | + { | ||
| 3495 | + "id": "C0238", | ||
| 3496 | + "activity_id": "A0030", | ||
| 3497 | + "user_id": "U0007", | ||
| 3498 | + "registration_id": "R0446", | ||
| 3499 | + "checkin_time": "2025-03-24 06:14:08", | ||
| 3500 | + "checkin_type": "QR code", | ||
| 3501 | + "location": { | ||
| 3502 | + "name": "大雁塔文化空间", | ||
| 3503 | + "coordinates": "39.916319,120.798035" | ||
| 3504 | + }, | ||
| 3505 | + "staff_id": null, | ||
| 3506 | + "status": "failed", | ||
| 3507 | + "notes": "未携带所需材料", | ||
| 3508 | + "is_late": false | ||
| 3509 | + }, | ||
| 3510 | + { | ||
| 3511 | + "id": "C0239", | ||
| 3512 | + "activity_id": "A0030", | ||
| 3513 | + "user_id": "U0034", | ||
| 3514 | + "registration_id": "R0447", | ||
| 3515 | + "checkin_time": "2025-03-24 06:21:39", | ||
| 3516 | + "checkin_type": "manual", | ||
| 3517 | + "location": { | ||
| 3518 | + "name": "大雁塔文化空间", | ||
| 3519 | + "coordinates": "35.329186,107.028931" | ||
| 3520 | + }, | ||
| 3521 | + "staff_id": "O0005", | ||
| 3522 | + "status": "successful", | ||
| 3523 | + "notes": "", | ||
| 3524 | + "is_late": false | ||
| 3525 | + }, | ||
| 3526 | + { | ||
| 3527 | + "id": "C0240", | ||
| 3528 | + "activity_id": "A0030", | ||
| 3529 | + "user_id": "U0032", | ||
| 3530 | + "registration_id": "R0449", | ||
| 3531 | + "checkin_time": "2025-03-24 06:19:22", | ||
| 3532 | + "checkin_type": "QR code", | ||
| 3533 | + "location": { | ||
| 3534 | + "name": "大雁塔文化空间", | ||
| 3535 | + "coordinates": "30.944494,124.919253" | ||
| 3536 | + }, | ||
| 3537 | + "staff_id": null, | ||
| 3538 | + "status": "failed", | ||
| 3539 | + "notes": "迟到超过30分钟", | ||
| 3540 | + "is_late": false | ||
| 3541 | + }, | ||
| 3542 | + { | ||
| 3543 | + "id": "C0241", | ||
| 3544 | + "activity_id": "A0030", | ||
| 3545 | + "user_id": "U0016", | ||
| 3546 | + "registration_id": "R0450", | ||
| 3547 | + "checkin_time": "2025-03-24 06:31:18", | ||
| 3548 | + "checkin_type": "self-service", | ||
| 3549 | + "location": { | ||
| 3550 | + "name": "大雁塔文化空间", | ||
| 3551 | + "coordinates": "30.156234,121.488007" | ||
| 3552 | + }, | ||
| 3553 | + "staff_id": null, | ||
| 3554 | + "status": "failed", | ||
| 3555 | + "notes": "网络连接不稳定", | ||
| 3556 | + "is_late": false | ||
| 3557 | + }, | ||
| 3558 | + { | ||
| 3559 | + "id": "C0242", | ||
| 3560 | + "activity_id": "A0030", | ||
| 3561 | + "user_id": "U0002", | ||
| 3562 | + "registration_id": "R0451", | ||
| 3563 | + "checkin_time": "2025-03-24 06:32:07", | ||
| 3564 | + "checkin_type": "QR code", | ||
| 3565 | + "location": { | ||
| 3566 | + "name": "大雁塔文化空间", | ||
| 3567 | + "coordinates": "36.425545,115.307617" | ||
| 3568 | + }, | ||
| 3569 | + "staff_id": null, | ||
| 3570 | + "status": "successful", | ||
| 3571 | + "notes": "", | ||
| 3572 | + "is_late": false | ||
| 3573 | + }, | ||
| 3574 | + { | ||
| 3575 | + "id": "C0243", | ||
| 3576 | + "activity_id": "A0030", | ||
| 3577 | + "user_id": "U0029", | ||
| 3578 | + "registration_id": "R0453", | ||
| 3579 | + "checkin_time": "2025-03-24 06:04:37", | ||
| 3580 | + "checkin_type": "self-service", | ||
| 3581 | + "location": { | ||
| 3582 | + "name": "大雁塔文化空间", | ||
| 3583 | + "coordinates": "30.531905,106.376309" | ||
| 3584 | + }, | ||
| 3585 | + "staff_id": null, | ||
| 3586 | + "status": "successful", | ||
| 3587 | + "notes": "", | ||
| 3588 | + "is_late": false | ||
| 3589 | + }, | ||
| 3590 | + { | ||
| 3591 | + "id": "C0244", | ||
| 3592 | + "activity_id": "A0030", | ||
| 3593 | + "user_id": "U0038", | ||
| 3594 | + "registration_id": "R0454", | ||
| 3595 | + "checkin_time": "2025-03-24 06:16:33", | ||
| 3596 | + "checkin_type": "self-service", | ||
| 3597 | + "location": { | ||
| 3598 | + "name": "大雁塔文化空间", | ||
| 3599 | + "coordinates": "30.017986,114.083724" | ||
| 3600 | + }, | ||
| 3601 | + "staff_id": null, | ||
| 3602 | + "status": "successful", | ||
| 3603 | + "notes": "", | ||
| 3604 | + "is_late": true | ||
| 3605 | + }, | ||
| 3606 | + { | ||
| 3607 | + "id": "C0245", | ||
| 3608 | + "activity_id": "A0030", | ||
| 3609 | + "user_id": "U0021", | ||
| 3610 | + "registration_id": "R0455", | ||
| 3611 | + "checkin_time": "2025-03-24 06:11:23", | ||
| 3612 | + "checkin_type": "QR code", | ||
| 3613 | + "location": { | ||
| 3614 | + "name": "大雁塔文化空间", | ||
| 3615 | + "coordinates": "27.571855,119.718238" | ||
| 3616 | + }, | ||
| 3617 | + "staff_id": null, | ||
| 3618 | + "status": "successful", | ||
| 3619 | + "notes": "", | ||
| 3620 | + "is_late": false | ||
| 3621 | + }, | ||
| 3622 | + { | ||
| 3623 | + "id": "C0246", | ||
| 3624 | + "activity_id": "A0030", | ||
| 3625 | + "user_id": "U0027", | ||
| 3626 | + "registration_id": "R0456", | ||
| 3627 | + "checkin_time": "2025-03-24 06:24:43", | ||
| 3628 | + "checkin_type": "QR code", | ||
| 3629 | + "location": { | ||
| 3630 | + "name": "大雁塔文化空间", | ||
| 3631 | + "coordinates": "38.706085,113.113853" | ||
| 3632 | + }, | ||
| 3633 | + "staff_id": null, | ||
| 3634 | + "status": "successful", | ||
| 3635 | + "notes": "", | ||
| 3636 | + "is_late": false | ||
| 3637 | + }, | ||
| 3638 | + { | ||
| 3639 | + "id": "C0247", | ||
| 3640 | + "activity_id": "A0030", | ||
| 3641 | + "user_id": "U0012", | ||
| 3642 | + "registration_id": "R0457", | ||
| 3643 | + "checkin_time": "2025-03-24 06:31:03", | ||
| 3644 | + "checkin_type": "manual", | ||
| 3645 | + "location": { | ||
| 3646 | + "name": "大雁塔文化空间", | ||
| 3647 | + "coordinates": "36.627228,124.621240" | ||
| 3648 | + }, | ||
| 3649 | + "staff_id": "O0005", | ||
| 3650 | + "status": "successful", | ||
| 3651 | + "notes": "", | ||
| 3652 | + "is_late": false | ||
| 3653 | + }, | ||
| 3654 | + { | ||
| 3655 | + "id": "C0248", | ||
| 3656 | + "activity_id": "A0030", | ||
| 3657 | + "user_id": "U0009", | ||
| 3658 | + "registration_id": "R0458", | ||
| 3659 | + "checkin_time": "2025-03-24 06:24:40", | ||
| 3660 | + "checkin_type": "QR code", | ||
| 3661 | + "location": { | ||
| 3662 | + "name": "大雁塔文化空间", | ||
| 3663 | + "coordinates": "28.284668,120.174935" | ||
| 3664 | + }, | ||
| 3665 | + "staff_id": null, | ||
| 3666 | + "status": "successful", | ||
| 3667 | + "notes": "", | ||
| 3668 | + "is_late": false | ||
| 3669 | + }, | ||
| 3670 | + { | ||
| 3671 | + "id": "C0249", | ||
| 3672 | + "activity_id": "A0030", | ||
| 3673 | + "user_id": "U0035", | ||
| 3674 | + "registration_id": "R0459", | ||
| 3675 | + "checkin_time": "2025-03-24 06:22:22", | ||
| 3676 | + "checkin_type": "QR code", | ||
| 3677 | + "location": { | ||
| 3678 | + "name": "大雁塔文化空间", | ||
| 3679 | + "coordinates": "25.338185,120.506832" | ||
| 3680 | + }, | ||
| 3681 | + "staff_id": null, | ||
| 3682 | + "status": "successful", | ||
| 3683 | + "notes": "提前到达", | ||
| 3684 | + "is_late": true | ||
| 3685 | + }, | ||
| 3686 | + { | ||
| 3687 | + "id": "C0250", | ||
| 3688 | + "activity_id": "A0030", | ||
| 3689 | + "user_id": "U0036", | ||
| 3690 | + "registration_id": "R0460", | ||
| 3691 | + "checkin_time": "2025-03-24 06:10:36", | ||
| 3692 | + "checkin_type": "QR code", | ||
| 3693 | + "location": { | ||
| 3694 | + "name": "大雁塔文化空间", | ||
| 3695 | + "coordinates": "39.576489,123.708963" | ||
| 3696 | + }, | ||
| 3697 | + "staff_id": null, | ||
| 3698 | + "status": "successful", | ||
| 3699 | + "notes": "", | ||
| 3700 | + "is_late": false | ||
| 3701 | + }, | ||
| 3702 | + { | ||
| 3703 | + "id": "C0251", | ||
| 3704 | + "activity_id": "A0030", | ||
| 3705 | + "user_id": "U0010", | ||
| 3706 | + "registration_id": "R0461", | ||
| 3707 | + "checkin_time": "2025-03-24 06:30:17", | ||
| 3708 | + "checkin_type": "QR code", | ||
| 3709 | + "location": { | ||
| 3710 | + "name": "大雁塔文化空间", | ||
| 3711 | + "coordinates": "25.560215,113.066388" | ||
| 3712 | + }, | ||
| 3713 | + "staff_id": null, | ||
| 3714 | + "status": "successful", | ||
| 3715 | + "notes": "", | ||
| 3716 | + "is_late": false | ||
| 3717 | + }, | ||
| 3718 | + { | ||
| 3719 | + "id": "C0252", | ||
| 3720 | + "activity_id": "A0030", | ||
| 3721 | + "user_id": "U0011", | ||
| 3722 | + "registration_id": "R0462", | ||
| 3723 | + "checkin_time": "2025-03-24 06:53:26", | ||
| 3724 | + "checkin_type": "QR code", | ||
| 3725 | + "location": { | ||
| 3726 | + "name": "大雁塔文化空间", | ||
| 3727 | + "coordinates": "24.201619,102.148571" | ||
| 3728 | + }, | ||
| 3729 | + "staff_id": null, | ||
| 3730 | + "status": "successful", | ||
| 3731 | + "notes": "热情参与讨论", | ||
| 3732 | + "is_late": true | ||
| 3733 | + }, | ||
| 3734 | + { | ||
| 3735 | + "id": "C0253", | ||
| 3736 | + "activity_id": "A0030", | ||
| 3737 | + "user_id": "U0040", | ||
| 3738 | + "registration_id": "R0464", | ||
| 3739 | + "checkin_time": "2025-03-24 06:28:18", | ||
| 3740 | + "checkin_type": "manual", | ||
| 3741 | + "location": { | ||
| 3742 | + "name": "大雁塔文化空间", | ||
| 3743 | + "coordinates": "27.166876,110.472657" | ||
| 3744 | + }, | ||
| 3745 | + "staff_id": "O0005", | ||
| 3746 | + "status": "successful", | ||
| 3747 | + "notes": "准备充分", | ||
| 3748 | + "is_late": false | ||
| 3749 | + }, | ||
| 3750 | + { | ||
| 3751 | + "id": "C0254", | ||
| 3752 | + "activity_id": "A0030", | ||
| 3753 | + "user_id": "U0005", | ||
| 3754 | + "registration_id": "R0465", | ||
| 3755 | + "checkin_time": "2025-03-24 06:16:32", | ||
| 3756 | + "checkin_type": "QR code", | ||
| 3757 | + "location": { | ||
| 3758 | + "name": "大雁塔文化空间", | ||
| 3759 | + "coordinates": "39.765965,102.449461" | ||
| 3760 | + }, | ||
| 3761 | + "staff_id": null, | ||
| 3762 | + "status": "successful", | ||
| 3763 | + "notes": "准备充分", | ||
| 3764 | + "is_late": false | ||
| 3765 | + }, | ||
| 3766 | + { | ||
| 3767 | + "id": "C0255", | ||
| 3768 | + "activity_id": "A0030", | ||
| 3769 | + "user_id": "U0017", | ||
| 3770 | + "registration_id": "R0466", | ||
| 3771 | + "checkin_time": "2025-03-24 06:26:07", | ||
| 3772 | + "checkin_type": "manual", | ||
| 3773 | + "location": { | ||
| 3774 | + "name": "大雁塔文化空间", | ||
| 3775 | + "coordinates": "35.381179,100.310767" | ||
| 3776 | + }, | ||
| 3777 | + "staff_id": "O0005", | ||
| 3778 | + "status": "successful", | ||
| 3779 | + "notes": "", | ||
| 3780 | + "is_late": true | ||
| 3781 | + }, | ||
| 3782 | + { | ||
| 3783 | + "id": "C0256", | ||
| 3784 | + "activity_id": "A0030", | ||
| 3785 | + "user_id": "U0006", | ||
| 3786 | + "registration_id": "R0467", | ||
| 3787 | + "checkin_time": "2025-03-24 06:08:21", | ||
| 3788 | + "checkin_type": "QR code", | ||
| 3789 | + "location": { | ||
| 3790 | + "name": "大雁塔文化空间", | ||
| 3791 | + "coordinates": "30.564468,110.716545" | ||
| 3792 | + }, | ||
| 3793 | + "staff_id": null, | ||
| 3794 | + "status": "successful", | ||
| 3795 | + "notes": "", | ||
| 3796 | + "is_late": false | ||
| 3797 | + }, | ||
| 3798 | + { | ||
| 3799 | + "id": "C0257", | ||
| 3800 | + "activity_id": "A0030", | ||
| 3801 | + "user_id": "U0013", | ||
| 3802 | + "registration_id": "R0468", | ||
| 3803 | + "checkin_time": "2025-03-24 06:34:50", | ||
| 3804 | + "checkin_type": "QR code", | ||
| 3805 | + "location": { | ||
| 3806 | + "name": "大雁塔文化空间", | ||
| 3807 | + "coordinates": "38.552870,102.806985" | ||
| 3808 | + }, | ||
| 3809 | + "staff_id": null, | ||
| 3810 | + "status": "successful", | ||
| 3811 | + "notes": "", | ||
| 3812 | + "is_late": false | ||
| 3813 | + }, | ||
| 3814 | + { | ||
| 3815 | + "id": "C0258", | ||
| 3816 | + "activity_id": "A0030", | ||
| 3817 | + "user_id": "U0014", | ||
| 3818 | + "registration_id": "R0469", | ||
| 3819 | + "checkin_time": "2025-03-24 06:11:44", | ||
| 3820 | + "checkin_type": "manual", | ||
| 3821 | + "location": { | ||
| 3822 | + "name": "大雁塔文化空间", | ||
| 3823 | + "coordinates": "28.615959,124.683004" | ||
| 3824 | + }, | ||
| 3825 | + "staff_id": "O0005", | ||
| 3826 | + "status": "successful", | ||
| 3827 | + "notes": "", | ||
| 3828 | + "is_late": false | ||
| 3829 | + }, | ||
| 3830 | + { | ||
| 3831 | + "id": "C0259", | ||
| 3832 | + "activity_id": "A0030", | ||
| 3833 | + "user_id": "U0024", | ||
| 3834 | + "registration_id": "R0470", | ||
| 3835 | + "checkin_time": "2025-03-24 06:21:59", | ||
| 3836 | + "checkin_type": "QR code", | ||
| 3837 | + "location": { | ||
| 3838 | + "name": "大雁塔文化空间", | ||
| 3839 | + "coordinates": "32.650324,122.567416" | ||
| 3840 | + }, | ||
| 3841 | + "staff_id": null, | ||
| 3842 | + "status": "successful", | ||
| 3843 | + "notes": "", | ||
| 3844 | + "is_late": false | ||
| 3845 | + }, | ||
| 3846 | + { | ||
| 3847 | + "id": "C0260", | ||
| 3848 | + "activity_id": "A0030", | ||
| 3849 | + "user_id": "U0023", | ||
| 3850 | + "registration_id": "R0471", | ||
| 3851 | + "checkin_time": "2025-03-24 06:19:00", | ||
| 3852 | + "checkin_type": "QR code", | ||
| 3853 | + "location": { | ||
| 3854 | + "name": "大雁塔文化空间", | ||
| 3855 | + "coordinates": "33.643347,118.704871" | ||
| 3856 | + }, | ||
| 3857 | + "staff_id": null, | ||
| 3858 | + "status": "successful", | ||
| 3859 | + "notes": "", | ||
| 3860 | + "is_late": false | ||
| 3861 | + }, | ||
| 3862 | + { | ||
| 3863 | + "id": "C0261", | ||
| 3864 | + "activity_id": "A0030", | ||
| 3865 | + "user_id": "U0018", | ||
| 3866 | + "registration_id": "R0472", | ||
| 3867 | + "checkin_time": "2025-03-24 06:11:01", | ||
| 3868 | + "checkin_type": "QR code", | ||
| 3869 | + "location": { | ||
| 3870 | + "name": "大雁塔文化空间", | ||
| 3871 | + "coordinates": "29.846041,119.659244" | ||
| 3872 | + }, | ||
| 3873 | + "staff_id": null, | ||
| 3874 | + "status": "successful", | ||
| 3875 | + "notes": "热情参与讨论", | ||
| 3876 | + "is_late": false | ||
| 3877 | + }, | ||
| 3878 | + { | ||
| 3879 | + "id": "C0262", | ||
| 3880 | + "activity_id": "A0030", | ||
| 3881 | + "user_id": "U0020", | ||
| 3882 | + "registration_id": "R0474", | ||
| 3883 | + "checkin_time": "2025-03-24 06:35:07", | ||
| 3884 | + "checkin_type": "QR code", | ||
| 3885 | + "location": { | ||
| 3886 | + "name": "大雁塔文化空间", | ||
| 3887 | + "coordinates": "25.709511,106.061221" | ||
| 3888 | + }, | ||
| 3889 | + "staff_id": null, | ||
| 3890 | + "status": "successful", | ||
| 3891 | + "notes": "", | ||
| 3892 | + "is_late": true | ||
| 3893 | + }, | ||
| 3894 | + { | ||
| 3895 | + "id": "C0263", | ||
| 3896 | + "activity_id": "A0030", | ||
| 3897 | + "user_id": "U0008", | ||
| 3898 | + "registration_id": "R0475", | ||
| 3899 | + "checkin_time": "2025-03-24 06:39:17", | ||
| 3900 | + "checkin_type": "manual", | ||
| 3901 | + "location": { | ||
| 3902 | + "name": "大雁塔文化空间", | ||
| 3903 | + "coordinates": "32.647541,101.108562" | ||
| 3904 | + }, | ||
| 3905 | + "staff_id": "O0005", | ||
| 3906 | + "status": "successful", | ||
| 3907 | + "notes": "", | ||
| 3908 | + "is_late": false | ||
| 3909 | + }, | ||
| 3910 | + { | ||
| 3911 | + "id": "C0264", | ||
| 3912 | + "activity_id": "A0030", | ||
| 3913 | + "user_id": "U0039", | ||
| 3914 | + "registration_id": "R0476", | ||
| 3915 | + "checkin_time": "2025-03-24 06:08:49", | ||
| 3916 | + "checkin_type": "QR code", | ||
| 3917 | + "location": { | ||
| 3918 | + "name": "大雁塔文化空间", | ||
| 3919 | + "coordinates": "23.752600,113.568037" | ||
| 3920 | + }, | ||
| 3921 | + "staff_id": null, | ||
| 3922 | + "status": "successful", | ||
| 3923 | + "notes": "准备充分", | ||
| 3924 | + "is_late": false | ||
| 3925 | + }, | ||
| 3926 | + { | ||
| 3927 | + "id": "C0265", | ||
| 3928 | + "activity_id": "A0030", | ||
| 3929 | + "user_id": "U0025", | ||
| 3930 | + "registration_id": "R0477", | ||
| 3931 | + "checkin_time": "2025-03-24 06:14:21", | ||
| 3932 | + "checkin_type": "QR code", | ||
| 3933 | + "location": { | ||
| 3934 | + "name": "大雁塔文化空间", | ||
| 3935 | + "coordinates": "27.951622,124.171448" | ||
| 3936 | + }, | ||
| 3937 | + "staff_id": null, | ||
| 3938 | + "status": "successful", | ||
| 3939 | + "notes": "", | ||
| 3940 | + "is_late": false | ||
| 3941 | + }, | ||
| 3942 | + { | ||
| 3943 | + "id": "C0266", | ||
| 3944 | + "activity_id": "A0030", | ||
| 3945 | + "user_id": "U0004", | ||
| 3946 | + "registration_id": "R0478", | ||
| 3947 | + "checkin_time": "2025-03-24 06:28:35", | ||
| 3948 | + "checkin_type": "QR code", | ||
| 3949 | + "location": { | ||
| 3950 | + "name": "大雁塔文化空间", | ||
| 3951 | + "coordinates": "39.931468,121.020079" | ||
| 3952 | + }, | ||
| 3953 | + "staff_id": null, | ||
| 3954 | + "status": "successful", | ||
| 3955 | + "notes": "准备充分", | ||
| 3956 | + "is_late": false | ||
| 3957 | + }, | ||
| 3958 | + { | ||
| 3959 | + "id": "C0267", | ||
| 3960 | + "activity_id": "A0030", | ||
| 3961 | + "user_id": "U0037", | ||
| 3962 | + "registration_id": "R0479", | ||
| 3963 | + "checkin_time": "2025-03-24 06:07:58", | ||
| 3964 | + "checkin_type": "manual", | ||
| 3965 | + "location": { | ||
| 3966 | + "name": "大雁塔文化空间", | ||
| 3967 | + "coordinates": "34.700797,103.276532" | ||
| 3968 | + }, | ||
| 3969 | + "staff_id": "O0005", | ||
| 3970 | + "status": "successful", | ||
| 3971 | + "notes": "", | ||
| 3972 | + "is_late": false | ||
| 3973 | + }, | ||
| 3974 | + { | ||
| 3975 | + "id": "C0268", | ||
| 3976 | + "activity_id": "A0030", | ||
| 3977 | + "user_id": "U0001", | ||
| 3978 | + "registration_id": "R0480", | ||
| 3979 | + "checkin_time": "2025-03-24 06:28:46", | ||
| 3980 | + "checkin_type": "QR code", | ||
| 3981 | + "location": { | ||
| 3982 | + "name": "大雁塔文化空间", | ||
| 3983 | + "coordinates": "39.529239,117.178983" | ||
| 3984 | + }, | ||
| 3985 | + "staff_id": null, | ||
| 3986 | + "status": "successful", | ||
| 3987 | + "notes": "带了书本", | ||
| 3988 | + "is_late": false | ||
| 3989 | + } | ||
| 3990 | +] | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
public/data/example.json
0 → 100644
public/data/messages.json
0 → 100644
This diff could not be displayed because it is too large.
public/data/registrations.json
0 → 100644
This diff could not be displayed because it is too large.
public/data/users.json
0 → 100644
| 1 | +[ | ||
| 2 | + { | ||
| 3 | + "id": "U0001", | ||
| 4 | + "username": "philosopher915", | ||
| 5 | + "name": "陈静", | ||
| 6 | + "avatar": "https://randomuser.me/api/portraits/women/33.jpg", | ||
| 7 | + "phone": "15242619085", | ||
| 8 | + "email": "philosopher915@outlook.com", | ||
| 9 | + "gender": "男", | ||
| 10 | + "age_group": "31-35岁", | ||
| 11 | + "education": "高中", | ||
| 12 | + "registration_date": "2024-10-15 07:11:49", | ||
| 13 | + "location": "南京", | ||
| 14 | + "bio": "观点,交流,生活,发现,认知,情感,情感,交流,兴趣", | ||
| 15 | + "interests": [ | ||
| 16 | + "历史", | ||
| 17 | + "古典文学", | ||
| 18 | + "教育", | ||
| 19 | + "社会科学", | ||
| 20 | + "政治" | ||
| 21 | + ], | ||
| 22 | + "is_organizer": false, | ||
| 23 | + "organization": null, | ||
| 24 | + "activity_count": 10, | ||
| 25 | + "follow_count": 7, | ||
| 26 | + "followers_count": 13, | ||
| 27 | + "is_new_user": false | ||
| 28 | + }, | ||
| 29 | + { | ||
| 30 | + "id": "U0002", | ||
| 31 | + "username": "bibliophile888", | ||
| 32 | + "name": "林杰", | ||
| 33 | + "avatar": "https://randomuser.me/api/portraits/men/71.jpg", | ||
| 34 | + "phone": "18639598797", | ||
| 35 | + "email": "bibliophile888@foxmail.com", | ||
| 36 | + "gender": "女", | ||
| 37 | + "age_group": "31-35岁", | ||
| 38 | + "education": "本科", | ||
| 39 | + "registration_date": "2023-11-12 07:11:49", | ||
| 40 | + "location": "西安", | ||
| 41 | + "bio": "生活,未来,读书,思考,知识,思考,感悟,视野,思想,坚持,热爱,工作,沟通,坚持,知识,生活,理解,坚持", | ||
| 42 | + "interests": [ | ||
| 43 | + "推理", | ||
| 44 | + "诗歌", | ||
| 45 | + "音乐", | ||
| 46 | + "政治", | ||
| 47 | + "旅行" | ||
| 48 | + ], | ||
| 49 | + "is_organizer": false, | ||
| 50 | + "organization": null, | ||
| 51 | + "activity_count": 9, | ||
| 52 | + "follow_count": 37, | ||
| 53 | + "followers_count": 14, | ||
| 54 | + "is_new_user": false | ||
| 55 | + }, | ||
| 56 | + { | ||
| 57 | + "id": "U0003", | ||
| 58 | + "username": "sage560", | ||
| 59 | + "name": "胡秀英", | ||
| 60 | + "avatar": "https://randomuser.me/api/portraits/men/25.jpg", | ||
| 61 | + "phone": "13039456917", | ||
| 62 | + "email": "sage560@gmail.com", | ||
| 63 | + "gender": "女", | ||
| 64 | + "age_group": "41-50岁", | ||
| 65 | + "education": "硕士", | ||
| 66 | + "registration_date": "2024-03-12 07:11:49", | ||
| 67 | + "location": "北京", | ||
| 68 | + "bio": "思想,学习,沟通,坚持,启发,认知,经验,创造,理解,观点,精神,认知,思想,视野,探索,知识,文化,", | ||
| 69 | + "interests": [ | ||
| 70 | + "艺术", | ||
| 71 | + "哲学", | ||
| 72 | + "旅行", | ||
| 73 | + "政治", | ||
| 74 | + "教育" | ||
| 75 | + ], | ||
| 76 | + "is_organizer": false, | ||
| 77 | + "organization": null, | ||
| 78 | + "activity_count": 5, | ||
| 79 | + "follow_count": 13, | ||
| 80 | + "followers_count": 15, | ||
| 81 | + "is_new_user": false | ||
| 82 | + }, | ||
| 83 | + { | ||
| 84 | + "id": "U0004", | ||
| 85 | + "username": "reader777", | ||
| 86 | + "name": "陈勇", | ||
| 87 | + "avatar": "https://randomuser.me/api/portraits/men/92.jpg", | ||
| 88 | + "phone": "13678802250", | ||
| 89 | + "email": "reader777@163.com", | ||
| 90 | + "gender": "女", | ||
| 91 | + "age_group": "36-40岁", | ||
| 92 | + "education": "硕士", | ||
| 93 | + "registration_date": "2023-05-28 07:11:49", | ||
| 94 | + "location": "重庆", | ||
| 95 | + "bio": "生活,教育,分享,交流,启发,观点,沟通,情感,观点,发现,认知,价值,视野", | ||
| 96 | + "interests": [ | ||
| 97 | + "旅行", | ||
| 98 | + "外国文学", | ||
| 99 | + "古典文学", | ||
| 100 | + "推理", | ||
| 101 | + "经济" | ||
| 102 | + ], | ||
| 103 | + "is_organizer": false, | ||
| 104 | + "organization": null, | ||
| 105 | + "activity_count": 9, | ||
| 106 | + "follow_count": 18, | ||
| 107 | + "followers_count": 22, | ||
| 108 | + "is_new_user": false | ||
| 109 | + }, | ||
| 110 | + { | ||
| 111 | + "id": "U0005", | ||
| 112 | + "username": "scholar823", | ||
| 113 | + "name": "李霞", | ||
| 114 | + "avatar": "https://randomuser.me/api/portraits/women/24.jpg", | ||
| 115 | + "phone": "15765356756", | ||
| 116 | + "email": "scholar823@outlook.com", | ||
| 117 | + "gender": "女", | ||
| 118 | + "age_group": "41-50岁", | ||
| 119 | + "education": "高中", | ||
| 120 | + "registration_date": "2023-07-05 07:11:49", | ||
| 121 | + "location": "北京", | ||
| 122 | + "bio": "思考,兴趣,观点,兴趣,观点,经验,观点,观点,文化,智慧", | ||
| 123 | + "interests": [ | ||
| 124 | + "艺术", | ||
| 125 | + "旅行", | ||
| 126 | + "古典文学", | ||
| 127 | + "音乐", | ||
| 128 | + "外国文学" | ||
| 129 | + ], | ||
| 130 | + "is_organizer": false, | ||
| 131 | + "organization": null, | ||
| 132 | + "activity_count": 3, | ||
| 133 | + "follow_count": 2, | ||
| 134 | + "followers_count": 27, | ||
| 135 | + "is_new_user": false | ||
| 136 | + }, | ||
| 137 | + { | ||
| 138 | + "id": "U0006", | ||
| 139 | + "username": "thinker926", | ||
| 140 | + "name": "胡超", | ||
| 141 | + "avatar": "https://randomuser.me/api/portraits/men/40.jpg", | ||
| 142 | + "phone": "15926853615", | ||
| 143 | + "email": "thinker926@126.com", | ||
| 144 | + "gender": "女", | ||
| 145 | + "age_group": "36-40岁", | ||
| 146 | + "education": "博士", | ||
| 147 | + "registration_date": "2025-04-10 07:11:49", | ||
| 148 | + "location": "北京", | ||
| 149 | + "bio": "情感,未来,发现,创造,灵感,灵感,读书,灵感,灵感", | ||
| 150 | + "interests": [ | ||
| 151 | + "心理学", | ||
| 152 | + "哲学", | ||
| 153 | + "管理", | ||
| 154 | + "科技" | ||
| 155 | + ], | ||
| 156 | + "is_organizer": false, | ||
| 157 | + "organization": null, | ||
| 158 | + "activity_count": 15, | ||
| 159 | + "follow_count": 10, | ||
| 160 | + "followers_count": 21, | ||
| 161 | + "is_new_user": true | ||
| 162 | + }, | ||
| 163 | + { | ||
| 164 | + "id": "U0007", | ||
| 165 | + "username": "reader206", | ||
| 166 | + "name": "何秀英", | ||
| 167 | + "avatar": "https://randomuser.me/api/portraits/men/33.jpg", | ||
| 168 | + "phone": "13028502918", | ||
| 169 | + "email": "reader206@hotmail.com", | ||
| 170 | + "gender": "女", | ||
| 171 | + "age_group": "18-24岁", | ||
| 172 | + "education": "大专", | ||
| 173 | + "registration_date": "2024-05-18 07:11:49", | ||
| 174 | + "location": "深圳", | ||
| 175 | + "bio": "坚持,文化,教育,智慧,专注,情感,探索,成长,知识,沟通,生活,认知", | ||
| 176 | + "interests": [ | ||
| 177 | + "外国文学", | ||
| 178 | + "古典文学", | ||
| 179 | + "传记", | ||
| 180 | + "科技", | ||
| 181 | + "社会科学" | ||
| 182 | + ], | ||
| 183 | + "is_organizer": false, | ||
| 184 | + "organization": null, | ||
| 185 | + "activity_count": 13, | ||
| 186 | + "follow_count": 1, | ||
| 187 | + "followers_count": 25, | ||
| 188 | + "is_new_user": false | ||
| 189 | + }, | ||
| 190 | + { | ||
| 191 | + "id": "U0008", | ||
| 192 | + "username": "reader520", | ||
| 193 | + "name": "周霞", | ||
| 194 | + "avatar": "https://randomuser.me/api/portraits/women/77.jpg", | ||
| 195 | + "phone": "13954151629", | ||
| 196 | + "email": "reader520@126.com", | ||
| 197 | + "gender": "男", | ||
| 198 | + "age_group": "31-35岁", | ||
| 199 | + "education": "本科", | ||
| 200 | + "registration_date": "2024-08-24 07:11:49", | ||
| 201 | + "location": "北京", | ||
| 202 | + "bio": "读书,专注,观点,兴趣,知识,探索,智慧,情感,理解,创造,心灵,思想,观点,创造,视野,认知,学习,文化,探索,情感,知识,视野,工作", | ||
| 203 | + "interests": [ | ||
| 204 | + "健康", | ||
| 205 | + "推理" | ||
| 206 | + ], | ||
| 207 | + "is_organizer": false, | ||
| 208 | + "organization": null, | ||
| 209 | + "activity_count": 15, | ||
| 210 | + "follow_count": 43, | ||
| 211 | + "followers_count": 16, | ||
| 212 | + "is_new_user": false | ||
| 213 | + }, | ||
| 214 | + { | ||
| 215 | + "id": "U0009", | ||
| 216 | + "username": "literati391", | ||
| 217 | + "name": "何敏", | ||
| 218 | + "avatar": "https://randomuser.me/api/portraits/women/26.jpg", | ||
| 219 | + "phone": "18778721591", | ||
| 220 | + "email": "literati391@gmail.com", | ||
| 221 | + "gender": "女", | ||
| 222 | + "age_group": "41-50岁", | ||
| 223 | + "education": "博士", | ||
| 224 | + "registration_date": "2024-08-06 07:11:49", | ||
| 225 | + "location": "重庆", | ||
| 226 | + "bio": "成长,工作,启发,文化,认知,观点,创造,感悟,学习,情感,坚持,成长,视野,思考,生活,启发,热爱,热爱", | ||
| 227 | + "interests": [ | ||
| 228 | + "健康", | ||
| 229 | + "经济", | ||
| 230 | + "科幻", | ||
| 231 | + "外国文学", | ||
| 232 | + "社会科学" | ||
| 233 | + ], | ||
| 234 | + "is_organizer": false, | ||
| 235 | + "organization": null, | ||
| 236 | + "activity_count": 5, | ||
| 237 | + "follow_count": 14, | ||
| 238 | + "followers_count": 5, | ||
| 239 | + "is_new_user": false | ||
| 240 | + }, | ||
| 241 | + { | ||
| 242 | + "id": "U0010", | ||
| 243 | + "username": "scholar137", | ||
| 244 | + "name": "黄伟", | ||
| 245 | + "avatar": "https://randomuser.me/api/portraits/women/46.jpg", | ||
| 246 | + "phone": "15554784272", | ||
| 247 | + "email": "scholar137@qq.com", | ||
| 248 | + "gender": "女", | ||
| 249 | + "age_group": "50岁以上", | ||
| 250 | + "education": "博士", | ||
| 251 | + "registration_date": "2023-04-21 07:11:49", | ||
| 252 | + "location": "深圳", | ||
| 253 | + "bio": "未来,心灵,知识,沟通,交流,感悟,未来,情感,知识,表达,理解,沟通,表达,观点,价值,工作,交流,教育,知识,发现,发现,读书,学习,认知,启发,工作,价值,智慧,沟通,启发,表达,感悟,", | ||
| 254 | + "interests": [ | ||
| 255 | + "政治", | ||
| 256 | + "经济", | ||
| 257 | + "推理" | ||
| 258 | + ], | ||
| 259 | + "is_organizer": false, | ||
| 260 | + "organization": null, | ||
| 261 | + "activity_count": 5, | ||
| 262 | + "follow_count": 44, | ||
| 263 | + "followers_count": 10, | ||
| 264 | + "is_new_user": false | ||
| 265 | + }, | ||
| 266 | + { | ||
| 267 | + "id": "U0011", | ||
| 268 | + "username": "thinker327", | ||
| 269 | + "name": "陈洋", | ||
| 270 | + "avatar": "https://randomuser.me/api/portraits/men/44.jpg", | ||
| 271 | + "phone": "13252122058", | ||
| 272 | + "email": "thinker327@gmail.com", | ||
| 273 | + "gender": "女", | ||
| 274 | + "age_group": "41-50岁", | ||
| 275 | + "education": "大专", | ||
| 276 | + "registration_date": "2024-06-27 07:11:49", | ||
| 277 | + "location": "北京", | ||
| 278 | + "bio": "工作,启发,工作,表达,发现,观点,读书,经验,沟通,探索,智慧,理解,文化,探索,兴趣,兴趣,思考,灵感,", | ||
| 279 | + "interests": [ | ||
| 280 | + "健康", | ||
| 281 | + "历史", | ||
| 282 | + "文学", | ||
| 283 | + "经济", | ||
| 284 | + "心理学" | ||
| 285 | + ], | ||
| 286 | + "is_organizer": false, | ||
| 287 | + "organization": null, | ||
| 288 | + "activity_count": 3, | ||
| 289 | + "follow_count": 15, | ||
| 290 | + "followers_count": 11, | ||
| 291 | + "is_new_user": false | ||
| 292 | + }, | ||
| 293 | + { | ||
| 294 | + "id": "U0012", | ||
| 295 | + "username": "scholar730", | ||
| 296 | + "name": "陈超", | ||
| 297 | + "avatar": "https://randomuser.me/api/portraits/men/67.jpg", | ||
| 298 | + "phone": "13152364083", | ||
| 299 | + "email": "scholar730@126.com", | ||
| 300 | + "gender": "男", | ||
| 301 | + "age_group": "41-50岁", | ||
| 302 | + "education": "博士", | ||
| 303 | + "registration_date": "2023-10-07 07:11:49", | ||
| 304 | + "location": "北京", | ||
| 305 | + "bio": "交流,探索,灵感,发现,未来,分享,专注,读书,工作,未来,思考,观点", | ||
| 306 | + "interests": [ | ||
| 307 | + "传记" | ||
| 308 | + ], | ||
| 309 | + "is_organizer": false, | ||
| 310 | + "organization": null, | ||
| 311 | + "activity_count": 2, | ||
| 312 | + "follow_count": 34, | ||
| 313 | + "followers_count": 5, | ||
| 314 | + "is_new_user": false | ||
| 315 | + }, | ||
| 316 | + { | ||
| 317 | + "id": "U0013", | ||
| 318 | + "username": "booklover923", | ||
| 319 | + "name": "黄超", | ||
| 320 | + "avatar": "https://randomuser.me/api/portraits/men/48.jpg", | ||
| 321 | + "phone": "15670614516", | ||
| 322 | + "email": "booklover923@126.com", | ||
| 323 | + "gender": "女", | ||
| 324 | + "age_group": "36-40岁", | ||
| 325 | + "education": "硕士", | ||
| 326 | + "registration_date": "2024-10-25 07:11:49", | ||
| 327 | + "location": "重庆", | ||
| 328 | + "bio": "思考,精神,经验,价值,经验,精神,知识,启发,表达,学习,思考,生活,探索,经验,坚持,创造,思想,情感,专注,精神,知识,工作,探索,知识,思想", | ||
| 329 | + "interests": [ | ||
| 330 | + "社会科学", | ||
| 331 | + "科技", | ||
| 332 | + "哲学", | ||
| 333 | + "推理", | ||
| 334 | + "心理学" | ||
| 335 | + ], | ||
| 336 | + "is_organizer": false, | ||
| 337 | + "organization": null, | ||
| 338 | + "activity_count": 3, | ||
| 339 | + "follow_count": 15, | ||
| 340 | + "followers_count": 10, | ||
| 341 | + "is_new_user": false | ||
| 342 | + }, | ||
| 343 | + { | ||
| 344 | + "id": "U0014", | ||
| 345 | + "username": "reader948", | ||
| 346 | + "name": "李敏", | ||
| 347 | + "avatar": "https://randomuser.me/api/portraits/men/85.jpg", | ||
| 348 | + "phone": "18128797547", | ||
| 349 | + "email": "reader948@qq.com", | ||
| 350 | + "gender": "女", | ||
| 351 | + "age_group": "18-24岁", | ||
| 352 | + "education": "高中", | ||
| 353 | + "registration_date": "2023-07-12 07:11:49", | ||
| 354 | + "location": "广州", | ||
| 355 | + "bio": "价值,坚持,认知,读书,灵感,探索,知识,坚持,专注,灵感,未来,文化,探索,教育,未来,教育,认知,学习,探索,教育", | ||
| 356 | + "interests": [ | ||
| 357 | + "科技", | ||
| 358 | + "政治", | ||
| 359 | + "科幻" | ||
| 360 | + ], | ||
| 361 | + "is_organizer": false, | ||
| 362 | + "organization": null, | ||
| 363 | + "activity_count": 9, | ||
| 364 | + "follow_count": 50, | ||
| 365 | + "followers_count": 9, | ||
| 366 | + "is_new_user": false | ||
| 367 | + }, | ||
| 368 | + { | ||
| 369 | + "id": "U0015", | ||
| 370 | + "username": "literati987", | ||
| 371 | + "name": "徐磊", | ||
| 372 | + "avatar": "https://randomuser.me/api/portraits/women/29.jpg", | ||
| 373 | + "phone": "15585365059", | ||
| 374 | + "email": "literati987@yahoo.com", | ||
| 375 | + "gender": "女", | ||
| 376 | + "age_group": "25-30岁", | ||
| 377 | + "education": "博士", | ||
| 378 | + "registration_date": "2024-06-18 07:11:49", | ||
| 379 | + "location": "上海", | ||
| 380 | + "bio": "理解,心灵,表达,感悟,启发,读书,文化,交流,兴趣,思想,文化,未来,分享,兴趣,启发,交流,生活,知识,专注,文化,情感,兴趣", | ||
| 381 | + "interests": [ | ||
| 382 | + "教育", | ||
| 383 | + "社会科学", | ||
| 384 | + "哲学", | ||
| 385 | + "管理", | ||
| 386 | + "古典文学" | ||
| 387 | + ], | ||
| 388 | + "is_organizer": false, | ||
| 389 | + "organization": null, | ||
| 390 | + "activity_count": 4, | ||
| 391 | + "follow_count": 40, | ||
| 392 | + "followers_count": 18, | ||
| 393 | + "is_new_user": false | ||
| 394 | + }, | ||
| 395 | + { | ||
| 396 | + "id": "U0016", | ||
| 397 | + "username": "literati913", | ||
| 398 | + "name": "刘磊", | ||
| 399 | + "avatar": "https://randomuser.me/api/portraits/men/41.jpg", | ||
| 400 | + "phone": "15126570482", | ||
| 401 | + "email": "literati913@qq.com", | ||
| 402 | + "gender": "女", | ||
| 403 | + "age_group": "36-40岁", | ||
| 404 | + "education": "本科", | ||
| 405 | + "registration_date": "2023-09-06 07:11:49", | ||
| 406 | + "location": "南京", | ||
| 407 | + "bio": "思考,未来,感悟,探索,坚持,发现,感悟,思想,学习,沟通,坚持,文化,探索,未来", | ||
| 408 | + "interests": [ | ||
| 409 | + "经济", | ||
| 410 | + "管理" | ||
| 411 | + ], | ||
| 412 | + "is_organizer": false, | ||
| 413 | + "organization": null, | ||
| 414 | + "activity_count": 10, | ||
| 415 | + "follow_count": 19, | ||
| 416 | + "followers_count": 26, | ||
| 417 | + "is_new_user": false | ||
| 418 | + }, | ||
| 419 | + { | ||
| 420 | + "id": "U0017", | ||
| 421 | + "username": "bibliophile286", | ||
| 422 | + "name": "林杰", | ||
| 423 | + "avatar": "https://randomuser.me/api/portraits/men/12.jpg", | ||
| 424 | + "phone": "18598074151", | ||
| 425 | + "email": "bibliophile286@foxmail.com", | ||
| 426 | + "gender": "男", | ||
| 427 | + "age_group": "36-40岁", | ||
| 428 | + "education": "大专", | ||
| 429 | + "registration_date": "2023-09-02 07:11:49", | ||
| 430 | + "location": "杭州", | ||
| 431 | + "bio": "兴趣,启发,坚持,观点,情感,沟通,生活,学习,交流,发现,精神", | ||
| 432 | + "interests": [ | ||
| 433 | + "文学", | ||
| 434 | + "音乐" | ||
| 435 | + ], | ||
| 436 | + "is_organizer": false, | ||
| 437 | + "organization": null, | ||
| 438 | + "activity_count": 4, | ||
| 439 | + "follow_count": 32, | ||
| 440 | + "followers_count": 12, | ||
| 441 | + "is_new_user": false | ||
| 442 | + }, | ||
| 443 | + { | ||
| 444 | + "id": "U0018", | ||
| 445 | + "username": "sage162", | ||
| 446 | + "name": "高明", | ||
| 447 | + "avatar": "https://randomuser.me/api/portraits/women/73.jpg", | ||
| 448 | + "phone": "18339690960", | ||
| 449 | + "email": "sage162@126.com", | ||
| 450 | + "gender": "女", | ||
| 451 | + "age_group": "25-30岁", | ||
| 452 | + "education": "本科", | ||
| 453 | + "registration_date": "2024-06-14 07:11:49", | ||
| 454 | + "location": "北京", | ||
| 455 | + "bio": "热爱,思想,教育,学习,启发,教育,启发,生活,专注,知识,成长,热爱,热爱,学习,思想,视野,启发,思考,认知,精神,专注,坚持,读书,教育,思想,学习,读书,价值,理解,工作", | ||
| 456 | + "interests": [ | ||
| 457 | + "社会科学", | ||
| 458 | + "历史", | ||
| 459 | + "音乐", | ||
| 460 | + "心理学" | ||
| 461 | + ], | ||
| 462 | + "is_organizer": false, | ||
| 463 | + "organization": null, | ||
| 464 | + "activity_count": 5, | ||
| 465 | + "follow_count": 37, | ||
| 466 | + "followers_count": 1, | ||
| 467 | + "is_new_user": false | ||
| 468 | + }, | ||
| 469 | + { | ||
| 470 | + "id": "U0019", | ||
| 471 | + "username": "thinker676", | ||
| 472 | + "name": "张芳", | ||
| 473 | + "avatar": "https://randomuser.me/api/portraits/men/31.jpg", | ||
| 474 | + "phone": "15710859650", | ||
| 475 | + "email": "thinker676@qq.com", | ||
| 476 | + "gender": "男", | ||
| 477 | + "age_group": "36-40岁", | ||
| 478 | + "education": "本科", | ||
| 479 | + "registration_date": "2025-03-20 07:11:49", | ||
| 480 | + "location": "上海", | ||
| 481 | + "bio": "坚持,成长,思想,情感,工作,心灵,经验,探索,分享,知识,创造,兴趣,表达,思考,分享,发现,情感,视野,思考,创造,文化,思想,", | ||
| 482 | + "interests": [ | ||
| 483 | + "教育", | ||
| 484 | + "旅行" | ||
| 485 | + ], | ||
| 486 | + "is_organizer": false, | ||
| 487 | + "organization": null, | ||
| 488 | + "activity_count": 3, | ||
| 489 | + "follow_count": 12, | ||
| 490 | + "followers_count": 8, | ||
| 491 | + "is_new_user": true | ||
| 492 | + }, | ||
| 493 | + { | ||
| 494 | + "id": "U0020", | ||
| 495 | + "username": "bibliophile942", | ||
| 496 | + "name": "杨勇", | ||
| 497 | + "avatar": "https://randomuser.me/api/portraits/men/9.jpg", | ||
| 498 | + "phone": "13970324817", | ||
| 499 | + "email": "bibliophile942@foxmail.com", | ||
| 500 | + "gender": "男", | ||
| 501 | + "age_group": "41-50岁", | ||
| 502 | + "education": "硕士", | ||
| 503 | + "registration_date": "2025-02-25 07:11:49", | ||
| 504 | + "location": "西安", | ||
| 505 | + "bio": "发现,成长,知识,智慧,理解,观点,坚持,创造,学习", | ||
| 506 | + "interests": [ | ||
| 507 | + "推理", | ||
| 508 | + "科幻", | ||
| 509 | + "诗歌", | ||
| 510 | + "管理", | ||
| 511 | + "外国文学" | ||
| 512 | + ], | ||
| 513 | + "is_organizer": false, | ||
| 514 | + "organization": null, | ||
| 515 | + "activity_count": 9, | ||
| 516 | + "follow_count": 49, | ||
| 517 | + "followers_count": 29, | ||
| 518 | + "is_new_user": false | ||
| 519 | + }, | ||
| 520 | + { | ||
| 521 | + "id": "U0021", | ||
| 522 | + "username": "bibliophile998", | ||
| 523 | + "name": "刘秀英", | ||
| 524 | + "avatar": "https://randomuser.me/api/portraits/women/17.jpg", | ||
| 525 | + "phone": "15844639209", | ||
| 526 | + "email": "bibliophile998@126.com", | ||
| 527 | + "gender": "女", | ||
| 528 | + "age_group": "31-35岁", | ||
| 529 | + "education": "硕士", | ||
| 530 | + "registration_date": "2023-12-06 07:11:49", | ||
| 531 | + "location": "武汉", | ||
| 532 | + "bio": "精神,发现,心灵,交流,视野,情感,思考,情感,坚持,发现,心灵,教育,感悟,", | ||
| 533 | + "interests": [ | ||
| 534 | + "外国文学", | ||
| 535 | + "艺术", | ||
| 536 | + "健康", | ||
| 537 | + "政治", | ||
| 538 | + "心理学" | ||
| 539 | + ], | ||
| 540 | + "is_organizer": false, | ||
| 541 | + "organization": null, | ||
| 542 | + "activity_count": 6, | ||
| 543 | + "follow_count": 17, | ||
| 544 | + "followers_count": 25, | ||
| 545 | + "is_new_user": false | ||
| 546 | + }, | ||
| 547 | + { | ||
| 548 | + "id": "U0022", | ||
| 549 | + "username": "bibliophile730", | ||
| 550 | + "name": "徐娜", | ||
| 551 | + "avatar": "https://randomuser.me/api/portraits/women/5.jpg", | ||
| 552 | + "phone": "18820345218", | ||
| 553 | + "email": "bibliophile730@foxmail.com", | ||
| 554 | + "gender": "男", | ||
| 555 | + "age_group": "36-40岁", | ||
| 556 | + "education": "硕士", | ||
| 557 | + "registration_date": "2024-09-23 07:11:49", | ||
| 558 | + "location": "北京", | ||
| 559 | + "bio": "思考,创造,感悟,思想,学习,成长,情感,生活,启发,创造,学习,理解,感悟,生活,分享,沟通,智慧,探索,学习,智慧,交流,成长,", | ||
| 560 | + "interests": [ | ||
| 561 | + "健康", | ||
| 562 | + "诗歌", | ||
| 563 | + "科幻", | ||
| 564 | + "心理学" | ||
| 565 | + ], | ||
| 566 | + "is_organizer": false, | ||
| 567 | + "organization": null, | ||
| 568 | + "activity_count": 3, | ||
| 569 | + "follow_count": 11, | ||
| 570 | + "followers_count": 3, | ||
| 571 | + "is_new_user": false | ||
| 572 | + }, | ||
| 573 | + { | ||
| 574 | + "id": "U0023", | ||
| 575 | + "username": "booklover552", | ||
| 576 | + "name": "徐娜", | ||
| 577 | + "avatar": "https://randomuser.me/api/portraits/women/54.jpg", | ||
| 578 | + "phone": "18161956034", | ||
| 579 | + "email": "booklover552@foxmail.com", | ||
| 580 | + "gender": "女", | ||
| 581 | + "age_group": "31-35岁", | ||
| 582 | + "education": "高中", | ||
| 583 | + "registration_date": "2023-12-19 07:11:49", | ||
| 584 | + "location": "成都", | ||
| 585 | + "bio": "沟通,思考,价值,教育,分享,心灵,交流,生活,经验,启发,专注,情感", | ||
| 586 | + "interests": [ | ||
| 587 | + "社会科学", | ||
| 588 | + "音乐", | ||
| 589 | + "古典文学" | ||
| 590 | + ], | ||
| 591 | + "is_organizer": false, | ||
| 592 | + "organization": null, | ||
| 593 | + "activity_count": 5, | ||
| 594 | + "follow_count": 39, | ||
| 595 | + "followers_count": 14, | ||
| 596 | + "is_new_user": false | ||
| 597 | + }, | ||
| 598 | + { | ||
| 599 | + "id": "U0024", | ||
| 600 | + "username": "bookworm707", | ||
| 601 | + "name": "胡敏", | ||
| 602 | + "avatar": "https://randomuser.me/api/portraits/men/80.jpg", | ||
| 603 | + "phone": "13799073465", | ||
| 604 | + "email": "bookworm707@yahoo.com", | ||
| 605 | + "gender": "女", | ||
| 606 | + "age_group": "31-35岁", | ||
| 607 | + "education": "博士", | ||
| 608 | + "registration_date": "2024-03-23 07:11:49", | ||
| 609 | + "location": "武汉", | ||
| 610 | + "bio": "沟通,情感,思考,未来,知识,生活,知识,工作,经验,教育,文化,专注,专注,情感,认知,未来,经验,精神,教育,认知,坚持,视野,精神,情感,交流,观点,表达,专注,分享,经验,视野,知识,认知", | ||
| 611 | + "interests": [ | ||
| 612 | + "外国文学", | ||
| 613 | + "音乐", | ||
| 614 | + "管理", | ||
| 615 | + "艺术" | ||
| 616 | + ], | ||
| 617 | + "is_organizer": false, | ||
| 618 | + "organization": null, | ||
| 619 | + "activity_count": 4, | ||
| 620 | + "follow_count": 17, | ||
| 621 | + "followers_count": 6, | ||
| 622 | + "is_new_user": false | ||
| 623 | + }, | ||
| 624 | + { | ||
| 625 | + "id": "U0025", | ||
| 626 | + "username": "philosopher564", | ||
| 627 | + "name": "朱洋", | ||
| 628 | + "avatar": "https://randomuser.me/api/portraits/women/71.jpg", | ||
| 629 | + "phone": "18654998138", | ||
| 630 | + "email": "philosopher564@foxmail.com", | ||
| 631 | + "gender": "男", | ||
| 632 | + "age_group": "50岁以上", | ||
| 633 | + "education": "硕士", | ||
| 634 | + "registration_date": "2023-05-23 07:11:49", | ||
| 635 | + "location": "深圳", | ||
| 636 | + "bio": "思考,经验,观点,学习,理解,智慧,交流,表达,专注,", | ||
| 637 | + "interests": [ | ||
| 638 | + "传记", | ||
| 639 | + "社会科学", | ||
| 640 | + "经济", | ||
| 641 | + "音乐" | ||
| 642 | + ], | ||
| 643 | + "is_organizer": false, | ||
| 644 | + "organization": null, | ||
| 645 | + "activity_count": 3, | ||
| 646 | + "follow_count": 20, | ||
| 647 | + "followers_count": 27, | ||
| 648 | + "is_new_user": false | ||
| 649 | + }, | ||
| 650 | + { | ||
| 651 | + "id": "U0026", | ||
| 652 | + "username": "sage490", | ||
| 653 | + "name": "吴洋", | ||
| 654 | + "avatar": "https://randomuser.me/api/portraits/men/71.jpg", | ||
| 655 | + "phone": "13415330923", | ||
| 656 | + "email": "sage490@163.com", | ||
| 657 | + "gender": "女", | ||
| 658 | + "age_group": "36-40岁", | ||
| 659 | + "education": "大专", | ||
| 660 | + "registration_date": "2025-01-10 07:11:49", | ||
| 661 | + "location": "广州", | ||
| 662 | + "bio": "成长,心灵,精神,交流,分享,观点,认知,坚持,交流,创造,思考,经验,兴趣", | ||
| 663 | + "interests": [ | ||
| 664 | + "音乐", | ||
| 665 | + "健康" | ||
| 666 | + ], | ||
| 667 | + "is_organizer": false, | ||
| 668 | + "organization": null, | ||
| 669 | + "activity_count": 13, | ||
| 670 | + "follow_count": 49, | ||
| 671 | + "followers_count": 20, | ||
| 672 | + "is_new_user": false | ||
| 673 | + }, | ||
| 674 | + { | ||
| 675 | + "id": "U0027", | ||
| 676 | + "username": "bookworm606", | ||
| 677 | + "name": "王勇", | ||
| 678 | + "avatar": "https://randomuser.me/api/portraits/women/55.jpg", | ||
| 679 | + "phone": "18785082868", | ||
| 680 | + "email": "bookworm606@126.com", | ||
| 681 | + "gender": "女", | ||
| 682 | + "age_group": "41-50岁", | ||
| 683 | + "education": "高中", | ||
| 684 | + "registration_date": "2024-12-05 07:11:49", | ||
| 685 | + "location": "武汉", | ||
| 686 | + "bio": "坚持,价值,思考,视野,观点,精神,感悟,分享,理解,启发,思考,文化,精神,思想,思考,热爱,", | ||
| 687 | + "interests": [ | ||
| 688 | + "历史", | ||
| 689 | + "健康", | ||
| 690 | + "管理", | ||
| 691 | + "古典文学" | ||
| 692 | + ], | ||
| 693 | + "is_organizer": false, | ||
| 694 | + "organization": null, | ||
| 695 | + "activity_count": 3, | ||
| 696 | + "follow_count": 29, | ||
| 697 | + "followers_count": 24, | ||
| 698 | + "is_new_user": false | ||
| 699 | + }, | ||
| 700 | + { | ||
| 701 | + "id": "U0028", | ||
| 702 | + "username": "sage811", | ||
| 703 | + "name": "罗强", | ||
| 704 | + "avatar": "https://randomuser.me/api/portraits/men/30.jpg", | ||
| 705 | + "phone": "15294749899", | ||
| 706 | + "email": "sage811@hotmail.com", | ||
| 707 | + "gender": "男", | ||
| 708 | + "age_group": "25-30岁", | ||
| 709 | + "education": "大专", | ||
| 710 | + "registration_date": "2024-08-05 07:11:49", | ||
| 711 | + "location": "北京", | ||
| 712 | + "bio": "成长,视野,视野,读书,思想,思想,沟通,知识,启发,精神,成长,感悟,认知,探索,表达,感悟,启发,热爱,文化,专注,思想,感悟,专注,情感,思想,发现,兴趣", | ||
| 713 | + "interests": [ | ||
| 714 | + "艺术", | ||
| 715 | + "文学", | ||
| 716 | + "管理" | ||
| 717 | + ], | ||
| 718 | + "is_organizer": false, | ||
| 719 | + "organization": null, | ||
| 720 | + "activity_count": 15, | ||
| 721 | + "follow_count": 13, | ||
| 722 | + "followers_count": 17, | ||
| 723 | + "is_new_user": false | ||
| 724 | + }, | ||
| 725 | + { | ||
| 726 | + "id": "U0029", | ||
| 727 | + "username": "scholar879", | ||
| 728 | + "name": "朱强", | ||
| 729 | + "avatar": "https://randomuser.me/api/portraits/men/24.jpg", | ||
| 730 | + "phone": "15552442116", | ||
| 731 | + "email": "scholar879@yahoo.com", | ||
| 732 | + "gender": "女", | ||
| 733 | + "age_group": "31-35岁", | ||
| 734 | + "education": "本科", | ||
| 735 | + "registration_date": "2024-04-26 07:11:49", | ||
| 736 | + "location": "西安", | ||
| 737 | + "bio": "生活,发现,沟通,感悟,情感,探索,生活,精神,教育,知识,思考,交流,成长,心灵,价值,教育,工作,心灵,发现,思想,发现,观点,经验,经验,成长,表达,表达,视野,知识,生活,教育", | ||
| 738 | + "interests": [ | ||
| 739 | + "推理", | ||
| 740 | + "管理" | ||
| 741 | + ], | ||
| 742 | + "is_organizer": false, | ||
| 743 | + "organization": null, | ||
| 744 | + "activity_count": 3, | ||
| 745 | + "follow_count": 4, | ||
| 746 | + "followers_count": 14, | ||
| 747 | + "is_new_user": false | ||
| 748 | + }, | ||
| 749 | + { | ||
| 750 | + "id": "U0030", | ||
| 751 | + "username": "booklover385", | ||
| 752 | + "name": "张涛", | ||
| 753 | + "avatar": "https://randomuser.me/api/portraits/women/38.jpg", | ||
| 754 | + "phone": "15189425224", | ||
| 755 | + "email": "booklover385@gmail.com", | ||
| 756 | + "gender": "女", | ||
| 757 | + "age_group": "41-50岁", | ||
| 758 | + "education": "高中", | ||
| 759 | + "registration_date": "2024-05-14 07:11:49", | ||
| 760 | + "location": "成都", | ||
| 761 | + "bio": "认知,经验,心灵,经验,观点,读书,热爱,思考,思考", | ||
| 762 | + "interests": [ | ||
| 763 | + "哲学", | ||
| 764 | + "文学", | ||
| 765 | + "科幻", | ||
| 766 | + "社会科学", | ||
| 767 | + "外国文学" | ||
| 768 | + ], | ||
| 769 | + "is_organizer": false, | ||
| 770 | + "organization": null, | ||
| 771 | + "activity_count": 8, | ||
| 772 | + "follow_count": 16, | ||
| 773 | + "followers_count": 19, | ||
| 774 | + "is_new_user": false | ||
| 775 | + }, | ||
| 776 | + { | ||
| 777 | + "id": "U0031", | ||
| 778 | + "username": "bibliophile693", | ||
| 779 | + "name": "李芳", | ||
| 780 | + "avatar": "https://randomuser.me/api/portraits/women/21.jpg", | ||
| 781 | + "phone": "18658709476", | ||
| 782 | + "email": "bibliophile693@hotmail.com", | ||
| 783 | + "gender": "男", | ||
| 784 | + "age_group": "36-40岁", | ||
| 785 | + "education": "高中", | ||
| 786 | + "registration_date": "2023-05-29 07:11:49", | ||
| 787 | + "location": "杭州", | ||
| 788 | + "bio": "观点,交流,启发,思想,兴趣,生活,精神,思想,交流", | ||
| 789 | + "interests": [ | ||
| 790 | + "外国文学", | ||
| 791 | + "哲学", | ||
| 792 | + "经济", | ||
| 793 | + "科技", | ||
| 794 | + "历史" | ||
| 795 | + ], | ||
| 796 | + "is_organizer": false, | ||
| 797 | + "organization": null, | ||
| 798 | + "activity_count": 7, | ||
| 799 | + "follow_count": 21, | ||
| 800 | + "followers_count": 9, | ||
| 801 | + "is_new_user": false | ||
| 802 | + }, | ||
| 803 | + { | ||
| 804 | + "id": "U0032", | ||
| 805 | + "username": "scholar444", | ||
| 806 | + "name": "王敏", | ||
| 807 | + "avatar": "https://randomuser.me/api/portraits/men/69.jpg", | ||
| 808 | + "phone": "18353657373", | ||
| 809 | + "email": "scholar444@163.com", | ||
| 810 | + "gender": "女", | ||
| 811 | + "age_group": "25-30岁", | ||
| 812 | + "education": "高中", | ||
| 813 | + "registration_date": "2024-01-10 07:11:49", | ||
| 814 | + "location": "重庆", | ||
| 815 | + "bio": "读书,创造,价值,发现,工作,探索,未来,理解,视野,经验,成长,思考,思想,价值,文化,思想,观点,教育,沟通,坚持,表达,生活,经验,分享,心灵,探索,智慧,智慧,知识,", | ||
| 816 | + "interests": [ | ||
| 817 | + "推理", | ||
| 818 | + "健康", | ||
| 819 | + "社会科学" | ||
| 820 | + ], | ||
| 821 | + "is_organizer": false, | ||
| 822 | + "organization": null, | ||
| 823 | + "activity_count": 9, | ||
| 824 | + "follow_count": 18, | ||
| 825 | + "followers_count": 28, | ||
| 826 | + "is_new_user": false | ||
| 827 | + }, | ||
| 828 | + { | ||
| 829 | + "id": "U0033", | ||
| 830 | + "username": "bibliophile775", | ||
| 831 | + "name": "林秀英", | ||
| 832 | + "avatar": "https://randomuser.me/api/portraits/men/39.jpg", | ||
| 833 | + "phone": "13786169274", | ||
| 834 | + "email": "bibliophile775@outlook.com", | ||
| 835 | + "gender": "女", | ||
| 836 | + "age_group": "25-30岁", | ||
| 837 | + "education": "高中", | ||
| 838 | + "registration_date": "2025-03-20 07:11:49", | ||
| 839 | + "location": "西安", | ||
| 840 | + "bio": "知识,认知,坚持,精神,文化,读书,未来,分享,智慧,专注,分享,经验,热爱,专注,未来,兴趣,探索,智慧", | ||
| 841 | + "interests": [ | ||
| 842 | + "科幻" | ||
| 843 | + ], | ||
| 844 | + "is_organizer": false, | ||
| 845 | + "organization": null, | ||
| 846 | + "activity_count": 14, | ||
| 847 | + "follow_count": 27, | ||
| 848 | + "followers_count": 1, | ||
| 849 | + "is_new_user": true | ||
| 850 | + }, | ||
| 851 | + { | ||
| 852 | + "id": "U0034", | ||
| 853 | + "username": "philosopher472", | ||
| 854 | + "name": "何平", | ||
| 855 | + "avatar": "https://randomuser.me/api/portraits/women/22.jpg", | ||
| 856 | + "phone": "13967679665", | ||
| 857 | + "email": "philosopher472@gmail.com", | ||
| 858 | + "gender": "女", | ||
| 859 | + "age_group": "25-30岁", | ||
| 860 | + "education": "本科", | ||
| 861 | + "registration_date": "2023-11-02 07:11:49", | ||
| 862 | + "location": "广州", | ||
| 863 | + "bio": "知识,思考,坚持,学习,专注,学习,发现,分享,智慧,经验,心灵,工作,专注,生活,未来,成长,价值,精神,热爱,精神,工作,专注,智慧,心灵,智慧,感悟", | ||
| 864 | + "interests": [ | ||
| 865 | + "心理学", | ||
| 866 | + "哲学", | ||
| 867 | + "古典文学", | ||
| 868 | + "音乐" | ||
| 869 | + ], | ||
| 870 | + "is_organizer": false, | ||
| 871 | + "organization": null, | ||
| 872 | + "activity_count": 10, | ||
| 873 | + "follow_count": 4, | ||
| 874 | + "followers_count": 27, | ||
| 875 | + "is_new_user": false | ||
| 876 | + }, | ||
| 877 | + { | ||
| 878 | + "id": "U0035", | ||
| 879 | + "username": "thinker448", | ||
| 880 | + "name": "罗芳", | ||
| 881 | + "avatar": "https://randomuser.me/api/portraits/men/51.jpg", | ||
| 882 | + "phone": "18474979217", | ||
| 883 | + "email": "thinker448@hotmail.com", | ||
| 884 | + "gender": "女", | ||
| 885 | + "age_group": "36-40岁", | ||
| 886 | + "education": "本科", | ||
| 887 | + "registration_date": "2024-03-12 07:11:49", | ||
| 888 | + "location": "武汉", | ||
| 889 | + "bio": "沟通,发现,表达,表达,读书,热爱,热爱,观点,理解,创造,观点,感悟,观点,交流,探索,心灵,表达,思想,专注,思想,探索,学习,理解,坚持,理解,坚持,热爱,探索,价值,感悟,文化,探索,经验,成", | ||
| 890 | + "interests": [ | ||
| 891 | + "科幻" | ||
| 892 | + ], | ||
| 893 | + "is_organizer": false, | ||
| 894 | + "organization": null, | ||
| 895 | + "activity_count": 15, | ||
| 896 | + "follow_count": 16, | ||
| 897 | + "followers_count": 29, | ||
| 898 | + "is_new_user": false | ||
| 899 | + }, | ||
| 900 | + { | ||
| 901 | + "id": "U0036", | ||
| 902 | + "username": "scholar345", | ||
| 903 | + "name": "刘杰", | ||
| 904 | + "avatar": "https://randomuser.me/api/portraits/women/49.jpg", | ||
| 905 | + "phone": "18492551516", | ||
| 906 | + "email": "scholar345@qq.com", | ||
| 907 | + "gender": "女", | ||
| 908 | + "age_group": "36-40岁", | ||
| 909 | + "education": "博士", | ||
| 910 | + "registration_date": "2024-10-14 07:11:49", | ||
| 911 | + "location": "上海", | ||
| 912 | + "bio": "文化,工作,表达,理解,未来,沟通,启发,坚持,工作,认知,学习,未来,热爱,专注,价值,兴趣,工作", | ||
| 913 | + "interests": [ | ||
| 914 | + "历史", | ||
| 915 | + "心理学" | ||
| 916 | + ], | ||
| 917 | + "is_organizer": false, | ||
| 918 | + "organization": null, | ||
| 919 | + "activity_count": 3, | ||
| 920 | + "follow_count": 0, | ||
| 921 | + "followers_count": 20, | ||
| 922 | + "is_new_user": false | ||
| 923 | + }, | ||
| 924 | + { | ||
| 925 | + "id": "U0037", | ||
| 926 | + "username": "bookworm118", | ||
| 927 | + "name": "黄静", | ||
| 928 | + "avatar": "https://randomuser.me/api/portraits/women/25.jpg", | ||
| 929 | + "phone": "18027065768", | ||
| 930 | + "email": "bookworm118@126.com", | ||
| 931 | + "gender": "女", | ||
| 932 | + "age_group": "41-50岁", | ||
| 933 | + "education": "硕士", | ||
| 934 | + "registration_date": "2024-06-03 07:11:49", | ||
| 935 | + "location": "深圳", | ||
| 936 | + "bio": "启发,学习,分享,探索,工作,思想,经验,创造,认知,理解,理解,专注,智慧,兴趣,思想,灵感", | ||
| 937 | + "interests": [ | ||
| 938 | + "诗歌", | ||
| 939 | + "社会科学", | ||
| 940 | + "哲学", | ||
| 941 | + "艺术", | ||
| 942 | + "政治" | ||
| 943 | + ], | ||
| 944 | + "is_organizer": false, | ||
| 945 | + "organization": null, | ||
| 946 | + "activity_count": 15, | ||
| 947 | + "follow_count": 33, | ||
| 948 | + "followers_count": 21, | ||
| 949 | + "is_new_user": false | ||
| 950 | + }, | ||
| 951 | + { | ||
| 952 | + "id": "U0038", | ||
| 953 | + "username": "sage197", | ||
| 954 | + "name": "杨伟", | ||
| 955 | + "avatar": "https://randomuser.me/api/portraits/men/33.jpg", | ||
| 956 | + "phone": "15524305177", | ||
| 957 | + "email": "sage197@outlook.com", | ||
| 958 | + "gender": "女", | ||
| 959 | + "age_group": "50岁以上", | ||
| 960 | + "education": "高中", | ||
| 961 | + "registration_date": "2024-12-24 07:11:49", | ||
| 962 | + "location": "深圳", | ||
| 963 | + "bio": "心灵,学习,文化,读书,思考,文化,表达,教育,灵感,价值,表达,启发,创造,专注,表达,感悟,文化,兴趣,探索,价值,灵感,价值,探索,精神,价值,经验,坚持,表达,", | ||
| 964 | + "interests": [ | ||
| 965 | + "外国文学" | ||
| 966 | + ], | ||
| 967 | + "is_organizer": false, | ||
| 968 | + "organization": null, | ||
| 969 | + "activity_count": 15, | ||
| 970 | + "follow_count": 13, | ||
| 971 | + "followers_count": 1, | ||
| 972 | + "is_new_user": false | ||
| 973 | + }, | ||
| 974 | + { | ||
| 975 | + "id": "U0039", | ||
| 976 | + "username": "reader235", | ||
| 977 | + "name": "罗芳", | ||
| 978 | + "avatar": "https://randomuser.me/api/portraits/men/35.jpg", | ||
| 979 | + "phone": "13189382815", | ||
| 980 | + "email": "reader235@126.com", | ||
| 981 | + "gender": "女", | ||
| 982 | + "age_group": "25-30岁", | ||
| 983 | + "education": "大专", | ||
| 984 | + "registration_date": "2024-06-30 07:11:49", | ||
| 985 | + "location": "南京", | ||
| 986 | + "bio": "视野,兴趣,知识,认知,思考,学习,灵感,教育,读书,专注,智慧,文化,发现,成长,学习,灵感,生活,思想,工作,读书,热爱,价值,感悟,视野,智慧,精神,教育,交流,学习,坚持", | ||
| 987 | + "interests": [ | ||
| 988 | + "科幻", | ||
| 989 | + "经济" | ||
| 990 | + ], | ||
| 991 | + "is_organizer": false, | ||
| 992 | + "organization": null, | ||
| 993 | + "activity_count": 13, | ||
| 994 | + "follow_count": 39, | ||
| 995 | + "followers_count": 12, | ||
| 996 | + "is_new_user": false | ||
| 997 | + }, | ||
| 998 | + { | ||
| 999 | + "id": "U0040", | ||
| 1000 | + "username": "scholar946", | ||
| 1001 | + "name": "孙敏", | ||
| 1002 | + "avatar": "https://randomuser.me/api/portraits/men/96.jpg", | ||
| 1003 | + "phone": "13191009314", | ||
| 1004 | + "email": "scholar946@gmail.com", | ||
| 1005 | + "gender": "女", | ||
| 1006 | + "age_group": "18-24岁", | ||
| 1007 | + "education": "博士", | ||
| 1008 | + "registration_date": "2024-10-30 07:11:49", | ||
| 1009 | + "location": "深圳", | ||
| 1010 | + "bio": "认知,坚持,启发,情感,情感,生活,思想,感悟,坚持,发现,读书,工作,成长,视野,灵感,经验,探索,启发,表达,发现,观点,成长", | ||
| 1011 | + "interests": [ | ||
| 1012 | + "古典文学", | ||
| 1013 | + "历史" | ||
| 1014 | + ], | ||
| 1015 | + "is_organizer": false, | ||
| 1016 | + "organization": null, | ||
| 1017 | + "activity_count": 14, | ||
| 1018 | + "follow_count": 13, | ||
| 1019 | + "followers_count": 12, | ||
| 1020 | + "is_new_user": false | ||
| 1021 | + }, | ||
| 1022 | + { | ||
| 1023 | + "id": "O0001", | ||
| 1024 | + "username": "sage841", | ||
| 1025 | + "name": "王超", | ||
| 1026 | + "avatar": "https://randomuser.me/api/portraits/men/49.jpg", | ||
| 1027 | + "phone": "13039676712", | ||
| 1028 | + "email": "sage841@hotmail.com", | ||
| 1029 | + "gender": "女", | ||
| 1030 | + "age_group": "31-35岁", | ||
| 1031 | + "education": "博士", | ||
| 1032 | + "registration_date": "2022-11-07 07:11:49", | ||
| 1033 | + "location": "南京", | ||
| 1034 | + "bio": "学习,认知,理解,成长,兴趣,视野,兴趣,情感,交流,智慧,交流,智慧,交流,启发,生活,启发,知识,启发,智慧,学习,理解,创造,价值,生活,思想,学习,生活,读书,坚持,热爱,思考,感悟,读书,交流,思想,成长,学习,工作,视野,专注,认知,心灵,心灵,探索,文化", | ||
| 1035 | + "interests": [ | ||
| 1036 | + "艺术", | ||
| 1037 | + "科幻", | ||
| 1038 | + "推理", | ||
| 1039 | + "历史" | ||
| 1040 | + ], | ||
| 1041 | + "is_organizer": true, | ||
| 1042 | + "organization": "光合作用文化空间", | ||
| 1043 | + "activity_count": 31, | ||
| 1044 | + "follow_count": 40, | ||
| 1045 | + "followers_count": 50, | ||
| 1046 | + "is_new_user": false | ||
| 1047 | + }, | ||
| 1048 | + { | ||
| 1049 | + "id": "O0002", | ||
| 1050 | + "username": "bibliophile236", | ||
| 1051 | + "name": "罗芳", | ||
| 1052 | + "avatar": "https://randomuser.me/api/portraits/women/83.jpg", | ||
| 1053 | + "phone": "15760214355", | ||
| 1054 | + "email": "bibliophile236@163.com", | ||
| 1055 | + "gender": "女", | ||
| 1056 | + "age_group": "41-50岁", | ||
| 1057 | + "education": "本科", | ||
| 1058 | + "registration_date": "2023-01-08 07:11:49", | ||
| 1059 | + "location": "北京", | ||
| 1060 | + "bio": "学习,观点,经验,观点,创造,精神,沟通,心灵,启发,兴趣,创造,理解,思考,经验,文化,坚持,热爱,沟通,教育,认知,成长,分享,理解,思想,智慧,探索,表达,教育,观点,观点,教育,思想,发现,生活,视野,思想,情感,探索,成长,交流,观点,成长,文化,探索,感悟,文化,智慧,学习,思考", | ||
| 1061 | + "interests": [ | ||
| 1062 | + "文学", | ||
| 1063 | + "古典文学", | ||
| 1064 | + "诗歌" | ||
| 1065 | + ], | ||
| 1066 | + "is_organizer": true, | ||
| 1067 | + "organization": "四季阅读空间", | ||
| 1068 | + "activity_count": 16, | ||
| 1069 | + "follow_count": 161, | ||
| 1070 | + "followers_count": 235, | ||
| 1071 | + "is_new_user": false | ||
| 1072 | + }, | ||
| 1073 | + { | ||
| 1074 | + "id": "O0003", | ||
| 1075 | + "username": "booklover483", | ||
| 1076 | + "name": "李秀英", | ||
| 1077 | + "avatar": "https://randomuser.me/api/portraits/women/77.jpg", | ||
| 1078 | + "phone": "15043716500", | ||
| 1079 | + "email": "booklover483@hotmail.com", | ||
| 1080 | + "gender": "女", | ||
| 1081 | + "age_group": "31-35岁", | ||
| 1082 | + "education": "硕士", | ||
| 1083 | + "registration_date": "2023-05-17 07:11:49", | ||
| 1084 | + "location": "深圳", | ||
| 1085 | + "bio": "精神,教育,视野,心灵,交流,未来,认知,文化,热爱,学习,经验,工作,启发,价值,学习,成长,交流,成长,工作,生活,分享,创造,文化,工作,表达,视野,工作", | ||
| 1086 | + "interests": [ | ||
| 1087 | + "古典文学", | ||
| 1088 | + "健康", | ||
| 1089 | + "历史", | ||
| 1090 | + "诗歌", | ||
| 1091 | + "艺术", | ||
| 1092 | + "教育" | ||
| 1093 | + ], | ||
| 1094 | + "is_organizer": true, | ||
| 1095 | + "organization": "知行合一读书社", | ||
| 1096 | + "activity_count": 31, | ||
| 1097 | + "follow_count": 37, | ||
| 1098 | + "followers_count": 490, | ||
| 1099 | + "is_new_user": false | ||
| 1100 | + }, | ||
| 1101 | + { | ||
| 1102 | + "id": "O0004", | ||
| 1103 | + "username": "sage327", | ||
| 1104 | + "name": "赵磊", | ||
| 1105 | + "avatar": "https://randomuser.me/api/portraits/women/32.jpg", | ||
| 1106 | + "phone": "18591156244", | ||
| 1107 | + "email": "sage327@163.com", | ||
| 1108 | + "gender": "女", | ||
| 1109 | + "age_group": "41-50岁", | ||
| 1110 | + "education": "硕士", | ||
| 1111 | + "registration_date": "2023-03-12 07:11:49", | ||
| 1112 | + "location": "武汉", | ||
| 1113 | + "bio": "经验,读书,创造,思考,工作,价值,视野,交流,表达,教育,分享,价值,分享,创造,知识,热爱,经验,工作", | ||
| 1114 | + "interests": [ | ||
| 1115 | + "经济", | ||
| 1116 | + "古典文学", | ||
| 1117 | + "哲学", | ||
| 1118 | + "教育", | ||
| 1119 | + "艺术", | ||
| 1120 | + "音乐", | ||
| 1121 | + "社会科学", | ||
| 1122 | + "旅行" | ||
| 1123 | + ], | ||
| 1124 | + "is_organizer": true, | ||
| 1125 | + "organization": "百草园读书会", | ||
| 1126 | + "activity_count": 44, | ||
| 1127 | + "follow_count": 21, | ||
| 1128 | + "followers_count": 150, | ||
| 1129 | + "is_new_user": false | ||
| 1130 | + }, | ||
| 1131 | + { | ||
| 1132 | + "id": "O0005", | ||
| 1133 | + "username": "bookworm479", | ||
| 1134 | + "name": "朱明", | ||
| 1135 | + "avatar": "https://randomuser.me/api/portraits/men/45.jpg", | ||
| 1136 | + "phone": "13581054570", | ||
| 1137 | + "email": "bookworm479@163.com", | ||
| 1138 | + "gender": "男", | ||
| 1139 | + "age_group": "50岁以上", | ||
| 1140 | + "education": "硕士", | ||
| 1141 | + "registration_date": "2022-09-04 07:11:49", | ||
| 1142 | + "location": "西安", | ||
| 1143 | + "bio": "智慧,认知,心灵,价值,经验,智慧,视野,认知,专注,启发,智慧,心灵,沟通,经验,交流,智慧,交流,坚持,精神,智慧,教育,发现,探索,精神,坚持,经验,知识,探索,经验,认知,专注,", | ||
| 1144 | + "interests": [ | ||
| 1145 | + "哲学", | ||
| 1146 | + "心理学", | ||
| 1147 | + "科幻", | ||
| 1148 | + "传记", | ||
| 1149 | + "经济", | ||
| 1150 | + "政治", | ||
| 1151 | + "科技" | ||
| 1152 | + ], | ||
| 1153 | + "is_organizer": true, | ||
| 1154 | + "organization": "鹿鸣书店", | ||
| 1155 | + "activity_count": 26, | ||
| 1156 | + "follow_count": 96, | ||
| 1157 | + "followers_count": 454, | ||
| 1158 | + "is_new_user": false | ||
| 1159 | + }, | ||
| 1160 | + { | ||
| 1161 | + "id": "O0006", | ||
| 1162 | + "username": "booklover785", | ||
| 1163 | + "name": "李敏", | ||
| 1164 | + "avatar": "https://randomuser.me/api/portraits/women/51.jpg", | ||
| 1165 | + "phone": "15828129990", | ||
| 1166 | + "email": "booklover785@foxmail.com", | ||
| 1167 | + "gender": "女", | ||
| 1168 | + "age_group": "50岁以上", | ||
| 1169 | + "education": "硕士", | ||
| 1170 | + "registration_date": "2024-07-16 07:11:49", | ||
| 1171 | + "location": "成都", | ||
| 1172 | + "bio": "分享,灵感,分享,视野,心灵,分享,视野,创造,认知,读书,专注,理解,视野,探索,视野,感悟,发现,精神,工作,精神,情感,表达,交流,生活,沟通,观点,启发,热爱", | ||
| 1173 | + "interests": [ | ||
| 1174 | + "文学", | ||
| 1175 | + "心理学", | ||
| 1176 | + "科技", | ||
| 1177 | + "历史" | ||
| 1178 | + ], | ||
| 1179 | + "is_organizer": true, | ||
| 1180 | + "organization": "百草园读书会", | ||
| 1181 | + "activity_count": 37, | ||
| 1182 | + "follow_count": 133, | ||
| 1183 | + "followers_count": 425, | ||
| 1184 | + "is_new_user": false | ||
| 1185 | + }, | ||
| 1186 | + { | ||
| 1187 | + "id": "O0007", | ||
| 1188 | + "username": "bookworm995", | ||
| 1189 | + "name": "刘明", | ||
| 1190 | + "avatar": "https://randomuser.me/api/portraits/men/35.jpg", | ||
| 1191 | + "phone": "18484363974", | ||
| 1192 | + "email": "bookworm995@163.com", | ||
| 1193 | + "gender": "女", | ||
| 1194 | + "age_group": "31-35岁", | ||
| 1195 | + "education": "博士", | ||
| 1196 | + "registration_date": "2024-03-02 07:11:49", | ||
| 1197 | + "location": "南京", | ||
| 1198 | + "bio": "专注,情感,未来,专注,文化,思考,生活,心灵,精神,启发,分享,工作,感悟,思想,创造,理解,思想,工作,思考,热爱,认知,启发,精神,交流,启发,知识,坚持,认知,知识,读书,认知,学习,坚持,精神,兴趣,智慧,理解,发现", | ||
| 1199 | + "interests": [ | ||
| 1200 | + "教育", | ||
| 1201 | + "经济", | ||
| 1202 | + "文学", | ||
| 1203 | + "健康", | ||
| 1204 | + "传记", | ||
| 1205 | + "科技", | ||
| 1206 | + "心理学", | ||
| 1207 | + "政治" | ||
| 1208 | + ], | ||
| 1209 | + "is_organizer": true, | ||
| 1210 | + "organization": "百草园读书会", | ||
| 1211 | + "activity_count": 28, | ||
| 1212 | + "follow_count": 73, | ||
| 1213 | + "followers_count": 319, | ||
| 1214 | + "is_new_user": false | ||
| 1215 | + }, | ||
| 1216 | + { | ||
| 1217 | + "id": "O0008", | ||
| 1218 | + "username": "literati792", | ||
| 1219 | + "name": "吴军", | ||
| 1220 | + "avatar": "https://randomuser.me/api/portraits/women/25.jpg", | ||
| 1221 | + "phone": "18764703997", | ||
| 1222 | + "email": "literati792@hotmail.com", | ||
| 1223 | + "gender": "女", | ||
| 1224 | + "age_group": "31-35岁", | ||
| 1225 | + "education": "本科", | ||
| 1226 | + "registration_date": "2023-09-21 07:11:49", | ||
| 1227 | + "location": "西安", | ||
| 1228 | + "bio": "认知,未来,沟通,灵感,思想,坚持,启发,思想,思考,生活,思考,未来,成长,学习,表达,精神,理解,未来,认知,坚持,表达,价值,沟通,精神,思想,分享,观点,视野,知识,灵感,生活,文化,学习,思想,观点,智慧,创造,兴趣,学习,坚持,精神,成长", | ||
| 1229 | + "interests": [ | ||
| 1230 | + "哲学", | ||
| 1231 | + "经济", | ||
| 1232 | + "古典文学" | ||
| 1233 | + ], | ||
| 1234 | + "is_organizer": true, | ||
| 1235 | + "organization": "墨香文化传媒", | ||
| 1236 | + "activity_count": 41, | ||
| 1237 | + "follow_count": 175, | ||
| 1238 | + "followers_count": 306, | ||
| 1239 | + "is_new_user": false | ||
| 1240 | + }, | ||
| 1241 | + { | ||
| 1242 | + "id": "O0009", | ||
| 1243 | + "username": "reader617", | ||
| 1244 | + "name": "陈艳", | ||
| 1245 | + "avatar": "https://randomuser.me/api/portraits/women/25.jpg", | ||
| 1246 | + "phone": "15658916066", | ||
| 1247 | + "email": "reader617@foxmail.com", | ||
| 1248 | + "gender": "女", | ||
| 1249 | + "age_group": "41-50岁", | ||
| 1250 | + "education": "本科", | ||
| 1251 | + "registration_date": "2024-06-26 07:11:49", | ||
| 1252 | + "location": "西安", | ||
| 1253 | + "bio": "思考,读书,精神,创造,热爱,情感,读书,创造,工作,灵感,热爱,创造,认知,沟通,读书,精神,生活,心灵,学习,热爱,交流,发现,知识,经验,感悟,创造,读书,学习,探索,文化,沟通,发现", | ||
| 1254 | + "interests": [ | ||
| 1255 | + "科技", | ||
| 1256 | + "诗歌", | ||
| 1257 | + "教育" | ||
| 1258 | + ], | ||
| 1259 | + "is_organizer": true, | ||
| 1260 | + "organization": "四季阅读空间", | ||
| 1261 | + "activity_count": 24, | ||
| 1262 | + "follow_count": 35, | ||
| 1263 | + "followers_count": 84, | ||
| 1264 | + "is_new_user": false | ||
| 1265 | + }, | ||
| 1266 | + { | ||
| 1267 | + "id": "O0010", | ||
| 1268 | + "username": "bibliophile948", | ||
| 1269 | + "name": "李伟", | ||
| 1270 | + "avatar": "https://randomuser.me/api/portraits/women/58.jpg", | ||
| 1271 | + "phone": "18696049013", | ||
| 1272 | + "email": "bibliophile948@hotmail.com", | ||
| 1273 | + "gender": "男", | ||
| 1274 | + "age_group": "50岁以上", | ||
| 1275 | + "education": "硕士", | ||
| 1276 | + "registration_date": "2024-02-21 07:11:49", | ||
| 1277 | + "location": "南京", | ||
| 1278 | + "bio": "工作,教育,视野,教育,认知,创造,生活,价值,学习,教育,专注,情感,价值,沟通,热爱,未来,知识,知识,思想,表达,知识,创造,专注,交流,视野,思考,感悟,", | ||
| 1279 | + "interests": [ | ||
| 1280 | + "社会科学", | ||
| 1281 | + "音乐", | ||
| 1282 | + "教育", | ||
| 1283 | + "旅行" | ||
| 1284 | + ], | ||
| 1285 | + "is_organizer": true, | ||
| 1286 | + "organization": "青禾读书会", | ||
| 1287 | + "activity_count": 17, | ||
| 1288 | + "follow_count": 135, | ||
| 1289 | + "followers_count": 269, | ||
| 1290 | + "is_new_user": false | ||
| 1291 | + } | ||
| 1292 | +] | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/App.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-04-17 08:14:12 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 13:15:27 | ||
| 5 | + * @FilePath: /reading-club-app/src/App.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +/* | ||
| 9 | + * @Date: 2025-04-17 08:14:12 | ||
| 10 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 11 | + * @LastEditTime: 2025-04-17 13:15:05 | ||
| 12 | + * @FilePath: /reading-club-app/src/App.jsx | ||
| 13 | + * @Description: 文件描述 | ||
| 14 | + */ | ||
| 15 | +<template> | ||
| 16 | + <div class="flex flex-col min-h-screen"> | ||
| 17 | + <Header /> | ||
| 18 | + <main class="flex-grow"> | ||
| 19 | + <router-view></router-view> | ||
| 20 | + </main> | ||
| 21 | + <Footer /> | ||
| 22 | + </div> | ||
| 23 | +</template> | ||
| 24 | + | ||
| 25 | +<script setup> | ||
| 26 | +import { onMounted } from 'vue' | ||
| 27 | +import Header from './components/layout/Header.vue' | ||
| 28 | +import Footer from './components/layout/Footer.vue' | ||
| 29 | + | ||
| 30 | +// 更新文档标题 | ||
| 31 | +onMounted(() => { | ||
| 32 | + document.title = '读书会 - 连接爱读书的人' | ||
| 33 | +}) | ||
| 34 | +</script> |
src/components/layout/Footer.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-04-17 13:22:07 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 13:22:09 | ||
| 5 | + * @FilePath: /reading-club-app/src/components/layout/Footer.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <footer class="mt-8 py-6 bg-gradient-to-r from-green-50 to-blue-50"> | ||
| 10 | + <div class="container mx-auto px-4"> | ||
| 11 | + <div class="flex flex-col md:flex-row justify-between items-center"> | ||
| 12 | + <div class="mb-4 md:mb-0"> | ||
| 13 | + <h3 class="text-xl font-bold bg-gradient-to-r from-green-500 to-blue-400 bg-clip-text text-transparent">读书会</h3> | ||
| 14 | + <p class="text-gray-600 mt-2">连接爱读书的人,共享知识的力量</p> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <div class="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-8"> | ||
| 18 | + <div> | ||
| 19 | + <h4 class="font-semibold text-gray-800 mb-3">关于我们</h4> | ||
| 20 | + <ul class="space-y-2"> | ||
| 21 | + <li><a href="#" class="text-gray-600 hover:text-green-500">平台介绍</a></li> | ||
| 22 | + <li><a href="#" class="text-gray-600 hover:text-green-500">使用指南</a></li> | ||
| 23 | + <li><a href="#" class="text-gray-600 hover:text-green-500">联系我们</a></li> | ||
| 24 | + </ul> | ||
| 25 | + </div> | ||
| 26 | + | ||
| 27 | + <div> | ||
| 28 | + <h4 class="font-semibold text-gray-800 mb-3">热门分类</h4> | ||
| 29 | + <ul class="space-y-2"> | ||
| 30 | + <li><a href="#" class="text-gray-600 hover:text-green-500">文学小说</a></li> | ||
| 31 | + <li><a href="#" class="text-gray-600 hover:text-green-500">社科人文</a></li> | ||
| 32 | + <li><a href="#" class="text-gray-600 hover:text-green-500">商业财经</a></li> | ||
| 33 | + </ul> | ||
| 34 | + </div> | ||
| 35 | + | ||
| 36 | + <div> | ||
| 37 | + <h4 class="font-semibold text-gray-800 mb-3">关注我们</h4> | ||
| 38 | + <div class="flex space-x-4"> | ||
| 39 | + <a href="#" class="text-gray-600 hover:text-green-500"> | ||
| 40 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 41 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 8l-8 8m0-8l8 8" /> | ||
| 42 | + </svg> | ||
| 43 | + </a> | ||
| 44 | + <a href="#" class="text-gray-600 hover:text-green-500"> | ||
| 45 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 46 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 47 | + </svg> | ||
| 48 | + </a> | ||
| 49 | + <a href="#" class="text-gray-600 hover:text-green-500"> | ||
| 50 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 51 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /> | ||
| 52 | + </svg> | ||
| 53 | + </a> | ||
| 54 | + </div> | ||
| 55 | + </div> | ||
| 56 | + </div> | ||
| 57 | + </div> | ||
| 58 | + | ||
| 59 | + <div class="border-t border-gray-200 mt-8 pt-6 text-center"> | ||
| 60 | + <p class="text-gray-500 text-sm">© 2024 读书会平台 All Rights Reserved</p> | ||
| 61 | + </div> | ||
| 62 | + </div> | ||
| 63 | + </footer> | ||
| 64 | +</template> | ||
| 65 | + | ||
| 66 | +<script setup> | ||
| 67 | +// Footer组件不需要任何响应式数据或方法 | ||
| 68 | +</script> |
src/components/layout/Header.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <header class="sticky top-0 z-50"> | ||
| 3 | + <!-- Frosted glass effect background --> | ||
| 4 | + <div class="backdrop-blur-xl bg-white/70 shadow-sm"> | ||
| 5 | + <div class="container mx-auto px-4"> | ||
| 6 | + <div class="flex items-center justify-between h-16"> | ||
| 7 | + <!-- Logo and Title --> | ||
| 8 | + <div class="flex items-center"> | ||
| 9 | + <router-link to="/" class="flex items-center"> | ||
| 10 | + <span class="text-2xl font-bold bg-gradient-to-r from-green-500 to-blue-400 bg-clip-text text-transparent"> | ||
| 11 | + 读书会 | ||
| 12 | + </span> | ||
| 13 | + </router-link> | ||
| 14 | + </div> | ||
| 15 | + | ||
| 16 | + <!-- Navigation - Desktop --> | ||
| 17 | + <nav class="hidden md:flex items-center space-x-6"> | ||
| 18 | + <router-link to="/" class="text-gray-600 hover:text-green-500 font-medium"> | ||
| 19 | + 首页 | ||
| 20 | + </router-link> | ||
| 21 | + <router-link to="/activities" class="text-gray-600 hover:text-green-500 font-medium"> | ||
| 22 | + 全部活动 | ||
| 23 | + </router-link> | ||
| 24 | + <router-link to="/create-activity" class="text-gray-600 hover:text-green-500 font-medium"> | ||
| 25 | + 创建活动 | ||
| 26 | + </router-link> | ||
| 27 | + </nav> | ||
| 28 | + | ||
| 29 | + <!-- User Profile and Actions --> | ||
| 30 | + <div class="flex items-center"> | ||
| 31 | + <!-- Messages Icon --> | ||
| 32 | + <router-link to="/messages" class="relative p-2 mr-4 text-gray-600 hover:text-green-500"> | ||
| 33 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 34 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" /> | ||
| 35 | + </svg> | ||
| 36 | + <span class="absolute top-1 right-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-500 rounded-full"> | ||
| 37 | + 2 | ||
| 38 | + </span> | ||
| 39 | + </router-link> | ||
| 40 | + | ||
| 41 | + <!-- User Profile --> | ||
| 42 | + <div class="relative"> | ||
| 43 | + <button @click="toggleProfileDropdown" class="flex items-center space-x-2"> | ||
| 44 | + <div class="h-8 w-8 rounded-full overflow-hidden border-2 border-green-500"> | ||
| 45 | + <img :src="currentUser?.avatar || '/assets/images/avatars/default_avatar.png'" alt="User Avatar" class="h-full w-full object-cover" /> | ||
| 46 | + </div> | ||
| 47 | + <span class="hidden lg:block text-sm font-medium text-gray-700">{{ currentUser?.name || 'User' }}</span> | ||
| 48 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 49 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /> | ||
| 50 | + </svg> | ||
| 51 | + </button> | ||
| 52 | + | ||
| 53 | + <!-- Profile Dropdown --> | ||
| 54 | + <div v-if="isProfileDropdownOpen" class="absolute right-0 mt-2 w-48 py-2 bg-white rounded-md shadow-lg backdrop-blur-xl bg-white/90 z-20"> | ||
| 55 | + <router-link to="/profile" class="block px-4 py-2 text-sm text-gray-700 hover:bg-green-50 hover:text-green-500"> | ||
| 56 | + 个人资料 | ||
| 57 | + </router-link> | ||
| 58 | + <router-link to="/my-activities" class="block px-4 py-2 text-sm text-gray-700 hover:bg-green-50 hover:text-green-500"> | ||
| 59 | + 我的活动 | ||
| 60 | + </router-link> | ||
| 61 | + <router-link to="/settings" class="block px-4 py-2 text-sm text-gray-700 hover:bg-green-50 hover:text-green-500"> | ||
| 62 | + 设置 | ||
| 63 | + </router-link> | ||
| 64 | + <button class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-green-50 hover:text-green-500"> | ||
| 65 | + 退出登录 | ||
| 66 | + </button> | ||
| 67 | + </div> | ||
| 68 | + </div> | ||
| 69 | + | ||
| 70 | + <!-- Mobile Menu Button --> | ||
| 71 | + <div class="ml-4 md:hidden"> | ||
| 72 | + <button @click="toggleMenu" type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-green-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-green-500"> | ||
| 73 | + <span class="sr-only">Open main menu</span> | ||
| 74 | + <svg :class="{ 'hidden': isMenuOpen, 'block': !isMenuOpen }" class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 75 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /> | ||
| 76 | + </svg> | ||
| 77 | + <svg :class="{ 'block': isMenuOpen, 'hidden': !isMenuOpen }" class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 78 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | ||
| 79 | + </svg> | ||
| 80 | + </button> | ||
| 81 | + </div> | ||
| 82 | + </div> | ||
| 83 | + </div> | ||
| 84 | + | ||
| 85 | + <!-- Mobile Menu --> | ||
| 86 | + <div :class="{ 'block': isMenuOpen, 'hidden': !isMenuOpen }" class="md:hidden"> | ||
| 87 | + <div class="px-2 pt-2 pb-3 space-y-1 sm:px-3"> | ||
| 88 | + <router-link to="/" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-green-500 hover:bg-green-50"> | ||
| 89 | + 首页 | ||
| 90 | + </router-link> | ||
| 91 | + <router-link to="/activities" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-green-500 hover:bg-green-50"> | ||
| 92 | + 全部活动 | ||
| 93 | + </router-link> | ||
| 94 | + <router-link to="/create-activity" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-green-500 hover:bg-green-50"> | ||
| 95 | + 创建活动 | ||
| 96 | + </router-link> | ||
| 97 | + <router-link to="/profile" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-green-500 hover:bg-green-50"> | ||
| 98 | + 个人资料 | ||
| 99 | + </router-link> | ||
| 100 | + <router-link to="/messages" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-green-500 hover:bg-green-50"> | ||
| 101 | + 消息通知 | ||
| 102 | + </router-link> | ||
| 103 | + </div> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 106 | + </div> | ||
| 107 | + </header> | ||
| 108 | +</template> | ||
| 109 | + | ||
| 110 | +<script setup> | ||
| 111 | +import { ref } from 'vue' | ||
| 112 | +import { useAppStore } from '../../stores/app' | ||
| 113 | + | ||
| 114 | +const appStore = useAppStore() | ||
| 115 | +const currentUser = appStore.currentUser | ||
| 116 | + | ||
| 117 | +const isMenuOpen = ref(false) | ||
| 118 | +const isProfileDropdownOpen = ref(false) | ||
| 119 | + | ||
| 120 | +const toggleMenu = () => { | ||
| 121 | + isMenuOpen.value = !isMenuOpen.value | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | +const toggleProfileDropdown = () => { | ||
| 125 | + isProfileDropdownOpen.value = !isProfileDropdownOpen.value | ||
| 126 | +} | ||
| 127 | +</script> |
src/components/shared/ActivityCard.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-04-17 13:16:20 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 13:16:22 | ||
| 5 | + * @FilePath: /reading-club-app/src/components/shared/ActivityCard.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <router-link | ||
| 10 | + :to="`/activity/${activity.id}`" | ||
| 11 | + class="block bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition duration-200" | ||
| 12 | + > | ||
| 13 | + <div class="relative pb-48 overflow-hidden"> | ||
| 14 | + <img | ||
| 15 | + :src="activity.cover_image" | ||
| 16 | + :alt="activity.title" | ||
| 17 | + class="absolute inset-0 h-full w-full object-cover" | ||
| 18 | + /> | ||
| 19 | + <div | ||
| 20 | + v-if="activity.tags && activity.tags.length" | ||
| 21 | + class="absolute top-0 left-0 p-4 flex flex-wrap gap-2" | ||
| 22 | + > | ||
| 23 | + <span | ||
| 24 | + v-for="tag in activity.tags" | ||
| 25 | + :key="tag" | ||
| 26 | + class="px-3 py-1 text-sm bg-green-500 text-white rounded-full" | ||
| 27 | + > | ||
| 28 | + {{ tag }} | ||
| 29 | + </span> | ||
| 30 | + </div> | ||
| 31 | + </div> | ||
| 32 | + | ||
| 33 | + <div class="p-6"> | ||
| 34 | + <h3 class="text-xl font-semibold text-gray-800 mb-2">{{ activity.title }}</h3> | ||
| 35 | + <p class="text-gray-600 text-sm mb-4 line-clamp-2">{{ activity.description }}</p> | ||
| 36 | + | ||
| 37 | + <div class="flex items-center text-sm text-gray-500 mb-4"> | ||
| 38 | + <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| 39 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> | ||
| 40 | + </svg> | ||
| 41 | + <span>{{ formatDateTime(activity.start_time) }}</span> | ||
| 42 | + </div> | ||
| 43 | + | ||
| 44 | + <div class="flex items-center text-sm text-gray-500 mb-4"> | ||
| 45 | + <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| 46 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /> | ||
| 47 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /> | ||
| 48 | + </svg> | ||
| 49 | + <span>{{ activity.location }}</span> | ||
| 50 | + </div> | ||
| 51 | + | ||
| 52 | + <div class="flex items-center justify-between"> | ||
| 53 | + <div class="flex items-center"> | ||
| 54 | + <img | ||
| 55 | + :src="activity.organizer_avatar" | ||
| 56 | + :alt="activity.organizer_name" | ||
| 57 | + class="w-8 h-8 rounded-full mr-2" | ||
| 58 | + /> | ||
| 59 | + <span class="text-sm text-gray-600">{{ activity.organizer_name }}</span> | ||
| 60 | + </div> | ||
| 61 | + <span class="text-sm font-medium text-green-500"> | ||
| 62 | + {{ activity.participant_count }}人参与 | ||
| 63 | + </span> | ||
| 64 | + </div> | ||
| 65 | + </div> | ||
| 66 | + </router-link> | ||
| 67 | +</template> | ||
| 68 | + | ||
| 69 | +<script setup> | ||
| 70 | +import { defineProps } from 'vue' | ||
| 71 | + | ||
| 72 | +const props = defineProps({ | ||
| 73 | + activity: { | ||
| 74 | + type: Object, | ||
| 75 | + required: true | ||
| 76 | + } | ||
| 77 | +}) | ||
| 78 | + | ||
| 79 | +// 格式化日期时间 | ||
| 80 | +const formatDateTime = (dateTimeStr) => { | ||
| 81 | + const date = new Date(dateTimeStr.replace(' ', 'T')) | ||
| 82 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 83 | + year: 'numeric', | ||
| 84 | + month: 'long', | ||
| 85 | + day: 'numeric', | ||
| 86 | + hour: '2-digit', | ||
| 87 | + minute: '2-digit' | ||
| 88 | + }).format(date) | ||
| 89 | +} | ||
| 90 | +</script> |
src/components/shared/Button.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <button | ||
| 3 | + :type="type" | ||
| 4 | + :class="[baseClasses, variantClass, sizeClass, roundedClass, block ? buttonBlock : '', className]" | ||
| 5 | + :disabled="disabled" | ||
| 6 | + @click="$emit('click', $event)" | ||
| 7 | + > | ||
| 8 | + <span v-if="leftIcon" class="mr-2"> | ||
| 9 | + <slot name="leftIcon"> | ||
| 10 | + {{ leftIcon }} | ||
| 11 | + </slot> | ||
| 12 | + </span> | ||
| 13 | + <slot></slot> | ||
| 14 | + <span v-if="rightIcon" class="ml-2"> | ||
| 15 | + <slot name="rightIcon"> | ||
| 16 | + {{ rightIcon }} | ||
| 17 | + </slot> | ||
| 18 | + </span> | ||
| 19 | + </button> | ||
| 20 | +</template> | ||
| 21 | + | ||
| 22 | +<script setup> | ||
| 23 | +import { computed } from 'vue' | ||
| 24 | + | ||
| 25 | +const buttonVariants = { | ||
| 26 | + primary: 'bg-gradient-to-r from-green-500 to-blue-500 hover:from-green-600 hover:to-blue-600 text-white border-transparent', | ||
| 27 | + secondary: 'bg-white hover:bg-gray-50 text-gray-700 border-gray-300', | ||
| 28 | + success: 'bg-green-600 hover:bg-green-700 text-white border-transparent', | ||
| 29 | + danger: 'bg-red-600 hover:bg-red-700 text-white border-transparent', | ||
| 30 | + warning: 'bg-yellow-500 hover:bg-yellow-600 text-white border-transparent', | ||
| 31 | + info: 'bg-blue-500 hover:bg-blue-600 text-white border-transparent', | ||
| 32 | + ghost: 'bg-transparent hover:bg-gray-100 text-gray-700 hover:text-gray-900 border-transparent' | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +const buttonSizes = { | ||
| 36 | + xs: 'px-2 py-1 text-xs', | ||
| 37 | + sm: 'px-2 py-1 text-sm', | ||
| 38 | + md: 'px-4 py-2', | ||
| 39 | + lg: 'px-6 py-3 text-lg', | ||
| 40 | + xl: 'px-8 py-4 text-xl' | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +const buttonRounded = { | ||
| 44 | + none: 'rounded-none', | ||
| 45 | + sm: 'rounded-sm', | ||
| 46 | + md: 'rounded-md', | ||
| 47 | + lg: 'rounded-lg', | ||
| 48 | + full: 'rounded-full' | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +const buttonBlock = 'w-full flex justify-center' | ||
| 52 | + | ||
| 53 | +const props = defineProps({ | ||
| 54 | + variant: { | ||
| 55 | + type: String, | ||
| 56 | + default: 'primary', | ||
| 57 | + validator: (value) => Object.keys(buttonVariants).includes(value) | ||
| 58 | + }, | ||
| 59 | + size: { | ||
| 60 | + type: String, | ||
| 61 | + default: 'md', | ||
| 62 | + validator: (value) => Object.keys(buttonSizes).includes(value) | ||
| 63 | + }, | ||
| 64 | + rounded: { | ||
| 65 | + type: String, | ||
| 66 | + default: 'md', | ||
| 67 | + validator: (value) => Object.keys(buttonRounded).includes(value) | ||
| 68 | + }, | ||
| 69 | + block: { | ||
| 70 | + type: Boolean, | ||
| 71 | + default: false | ||
| 72 | + }, | ||
| 73 | + disabled: { | ||
| 74 | + type: Boolean, | ||
| 75 | + default: false | ||
| 76 | + }, | ||
| 77 | + className: { | ||
| 78 | + type: String, | ||
| 79 | + default: '' | ||
| 80 | + }, | ||
| 81 | + leftIcon: { | ||
| 82 | + type: [String, Object], | ||
| 83 | + default: null | ||
| 84 | + }, | ||
| 85 | + rightIcon: { | ||
| 86 | + type: [String, Object], | ||
| 87 | + default: null | ||
| 88 | + }, | ||
| 89 | + type: { | ||
| 90 | + type: String, | ||
| 91 | + default: 'button' | ||
| 92 | + } | ||
| 93 | +}) | ||
| 94 | + | ||
| 95 | +defineEmits(['click']) | ||
| 96 | + | ||
| 97 | +const baseClasses = 'flex items-center justify-center font-medium border shadow-sm transition duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 disabled:opacity-50 disabled:cursor-not-allowed' | ||
| 98 | + | ||
| 99 | +const variantClass = computed(() => buttonVariants[props.variant] || buttonVariants.primary) | ||
| 100 | +const sizeClass = computed(() => buttonSizes[props.size] || buttonSizes.md) | ||
| 101 | +const roundedClass = computed(() => buttonRounded[props.rounded] || buttonRounded.md) | ||
| 102 | +</script> |
src/components/shared/Input.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div :class="['w-full', className]"> | ||
| 3 | + <label v-if="label" :for="inputId" class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 4 | + {{ label }} | ||
| 5 | + <span v-if="required" class="text-red-500 ml-1">*</span> | ||
| 6 | + </label> | ||
| 7 | + | ||
| 8 | + <div class="relative rounded-md shadow-sm"> | ||
| 9 | + <div v-if="leftIcon" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> | ||
| 10 | + <span class="text-gray-500 sm:text-sm"> | ||
| 11 | + <slot name="leftIcon"> | ||
| 12 | + {{ leftIcon }} | ||
| 13 | + </slot> | ||
| 14 | + </span> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <input | ||
| 18 | + :id="inputId" | ||
| 19 | + :type="type" | ||
| 20 | + :name="name" | ||
| 21 | + :placeholder="placeholder" | ||
| 22 | + :value="modelValue" | ||
| 23 | + :required="required" | ||
| 24 | + :disabled="disabled" | ||
| 25 | + @input="$emit('update:modelValue', $event.target.value)" | ||
| 26 | + @blur="$emit('blur', $event)" | ||
| 27 | + :class="[ | ||
| 28 | + 'block w-full border-gray-300 rounded-md shadow-sm', | ||
| 29 | + 'focus:ring-green-500 focus:border-green-500 sm:text-sm', | ||
| 30 | + 'disabled:bg-gray-100 disabled:text-gray-500 disabled:cursor-not-allowed', | ||
| 31 | + sizeClass, | ||
| 32 | + error ? 'border-red-300 text-red-900 placeholder-red-300 focus:ring-red-500 focus:border-red-500' : '', | ||
| 33 | + leftIcon ? 'pl-10' : '', | ||
| 34 | + rightIcon ? 'pr-10' : '' | ||
| 35 | + ]" | ||
| 36 | + v-bind="$attrs" | ||
| 37 | + /> | ||
| 38 | + | ||
| 39 | + <div v-if="rightIcon" class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"> | ||
| 40 | + <span class="text-gray-500 sm:text-sm"> | ||
| 41 | + <slot name="rightIcon"> | ||
| 42 | + {{ rightIcon }} | ||
| 43 | + </slot> | ||
| 44 | + </span> | ||
| 45 | + </div> | ||
| 46 | + </div> | ||
| 47 | + | ||
| 48 | + <p v-if="error || helperText" :class="['mt-1 text-sm', error ? 'text-red-600' : 'text-gray-500']"> | ||
| 49 | + {{ error || helperText }} | ||
| 50 | + </p> | ||
| 51 | + </div> | ||
| 52 | +</template> | ||
| 53 | + | ||
| 54 | +<script setup> | ||
| 55 | +import { computed } from 'vue' | ||
| 56 | + | ||
| 57 | +const inputSizes = { | ||
| 58 | + sm: 'px-2 py-1 text-sm', | ||
| 59 | + md: 'px-3 py-2', | ||
| 60 | + lg: 'px-4 py-3 text-lg' | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +const props = defineProps({ | ||
| 64 | + modelValue: { | ||
| 65 | + type: [String, Number], | ||
| 66 | + default: '' | ||
| 67 | + }, | ||
| 68 | + label: { | ||
| 69 | + type: String, | ||
| 70 | + default: '' | ||
| 71 | + }, | ||
| 72 | + name: { | ||
| 73 | + type: String, | ||
| 74 | + required: true | ||
| 75 | + }, | ||
| 76 | + type: { | ||
| 77 | + type: String, | ||
| 78 | + default: 'text' | ||
| 79 | + }, | ||
| 80 | + placeholder: { | ||
| 81 | + type: String, | ||
| 82 | + default: '' | ||
| 83 | + }, | ||
| 84 | + error: { | ||
| 85 | + type: String, | ||
| 86 | + default: '' | ||
| 87 | + }, | ||
| 88 | + size: { | ||
| 89 | + type: String, | ||
| 90 | + default: 'md', | ||
| 91 | + validator: (value) => Object.keys(inputSizes).includes(value) | ||
| 92 | + }, | ||
| 93 | + required: { | ||
| 94 | + type: Boolean, | ||
| 95 | + default: false | ||
| 96 | + }, | ||
| 97 | + disabled: { | ||
| 98 | + type: Boolean, | ||
| 99 | + default: false | ||
| 100 | + }, | ||
| 101 | + className: { | ||
| 102 | + type: String, | ||
| 103 | + default: '' | ||
| 104 | + }, | ||
| 105 | + helperText: { | ||
| 106 | + type: String, | ||
| 107 | + default: '' | ||
| 108 | + }, | ||
| 109 | + leftIcon: { | ||
| 110 | + type: [String, Object], | ||
| 111 | + default: null | ||
| 112 | + }, | ||
| 113 | + rightIcon: { | ||
| 114 | + type: [String, Object], | ||
| 115 | + default: null | ||
| 116 | + } | ||
| 117 | +}) | ||
| 118 | + | ||
| 119 | +defineEmits(['update:modelValue', 'blur']) | ||
| 120 | + | ||
| 121 | +const inputId = computed(() => `input-${props.name}`) | ||
| 122 | +const sizeClass = computed(() => inputSizes[props.size] || inputSizes.md) | ||
| 123 | +</script> |
src/components/shared/Modal.vue
0 → 100644
| 1 | +<script setup> | ||
| 2 | +import { ref, onMounted, onUnmounted, watch } from 'vue'; | ||
| 3 | + | ||
| 4 | +const props = defineProps({ | ||
| 5 | + isOpen: { | ||
| 6 | + type: Boolean, | ||
| 7 | + required: true | ||
| 8 | + }, | ||
| 9 | + title: { | ||
| 10 | + type: String, | ||
| 11 | + required: true | ||
| 12 | + }, | ||
| 13 | + size: { | ||
| 14 | + type: String, | ||
| 15 | + default: 'md' | ||
| 16 | + }, | ||
| 17 | + closeOnClickOutside: { | ||
| 18 | + type: Boolean, | ||
| 19 | + default: true | ||
| 20 | + }, | ||
| 21 | + showCloseButton: { | ||
| 22 | + type: Boolean, | ||
| 23 | + default: true | ||
| 24 | + }, | ||
| 25 | + contentClassName: { | ||
| 26 | + type: String, | ||
| 27 | + default: '' | ||
| 28 | + } | ||
| 29 | +}); | ||
| 30 | + | ||
| 31 | +const emit = defineEmits(['close']); | ||
| 32 | + | ||
| 33 | +const modalRef = ref(null); | ||
| 34 | +const isMounted = ref(false); | ||
| 35 | + | ||
| 36 | +// Set sizes based on the size prop | ||
| 37 | +const sizeClasses = { | ||
| 38 | + sm: 'max-w-md', | ||
| 39 | + md: 'max-w-lg', | ||
| 40 | + lg: 'max-w-2xl', | ||
| 41 | + xl: 'max-w-4xl', | ||
| 42 | + full: 'max-w-full mx-4' | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +const modalSize = computed(() => sizeClasses[props.size] || sizeClasses.md); | ||
| 46 | + | ||
| 47 | +// Handle ESC key press | ||
| 48 | +const handleKeyDown = (event) => { | ||
| 49 | + if (event.key === 'Escape' && props.isOpen) { | ||
| 50 | + emit('close'); | ||
| 51 | + } | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +// Handle click outside | ||
| 55 | +const handleClickOutside = (event) => { | ||
| 56 | + if (modalRef.value && !modalRef.value.contains(event.target) && props.closeOnClickOutside) { | ||
| 57 | + emit('close'); | ||
| 58 | + } | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +// Handle mounting/unmounting and event listeners | ||
| 62 | +onMounted(() => { | ||
| 63 | + isMounted.value = true; | ||
| 64 | + document.addEventListener('keydown', handleKeyDown); | ||
| 65 | +}); | ||
| 66 | + | ||
| 67 | +onUnmounted(() => { | ||
| 68 | + document.removeEventListener('keydown', handleKeyDown); | ||
| 69 | + document.removeEventListener('mousedown', handleClickOutside); | ||
| 70 | + document.body.style.overflow = 'auto'; | ||
| 71 | +}); | ||
| 72 | + | ||
| 73 | +// Watch isOpen changes | ||
| 74 | +watch(() => props.isOpen, (newValue) => { | ||
| 75 | + if (newValue) { | ||
| 76 | + document.body.style.overflow = 'hidden'; | ||
| 77 | + document.addEventListener('mousedown', handleClickOutside); | ||
| 78 | + } else { | ||
| 79 | + document.body.style.overflow = 'auto'; | ||
| 80 | + document.removeEventListener('mousedown', handleClickOutside); | ||
| 81 | + } | ||
| 82 | +}); | ||
| 83 | +</script> | ||
| 84 | + | ||
| 85 | +<template> | ||
| 86 | + <Teleport to="body"> | ||
| 87 | + <div v-if="isOpen && isMounted" class="fixed inset-0 z-50 overflow-y-auto"> | ||
| 88 | + <!-- Backdrop with semi-transparent background --> | ||
| 89 | + <div class="fixed inset-0 bg-black bg-opacity-50 backdrop-blur-sm transition-opacity"></div> | ||
| 90 | + | ||
| 91 | + <!-- Modal container --> | ||
| 92 | + <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center"> | ||
| 93 | + <div | ||
| 94 | + :class="['relative inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle w-full', modalSize]" | ||
| 95 | + ref="modalRef" | ||
| 96 | + > | ||
| 97 | + <!-- Modal header --> | ||
| 98 | + <div class="bg-white px-4 py-4 border-b border-gray-200 sm:px-6"> | ||
| 99 | + <div class="flex items-center justify-between"> | ||
| 100 | + <h3 class="text-lg leading-6 font-medium text-gray-900"> | ||
| 101 | + {{ title }} | ||
| 102 | + </h3> | ||
| 103 | + <button | ||
| 104 | + v-if="showCloseButton" | ||
| 105 | + type="button" | ||
| 106 | + class="rounded-md text-gray-400 hover:text-gray-500 focus:outline-none" | ||
| 107 | + @click="emit('close')" | ||
| 108 | + > | ||
| 109 | + <span class="sr-only">关闭</span> | ||
| 110 | + <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 111 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> | ||
| 112 | + </svg> | ||
| 113 | + </button> | ||
| 114 | + </div> | ||
| 115 | + </div> | ||
| 116 | + | ||
| 117 | + <!-- Modal content --> | ||
| 118 | + <div :class="['bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4', contentClassName]"> | ||
| 119 | + <slot></slot> | ||
| 120 | + </div> | ||
| 121 | + | ||
| 122 | + <!-- Modal footer --> | ||
| 123 | + <div v-if="$slots.footer" class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | ||
| 124 | + <slot name="footer"></slot> | ||
| 125 | + </div> | ||
| 126 | + </div> | ||
| 127 | + </div> | ||
| 128 | + </div> | ||
| 129 | + </Teleport> | ||
| 130 | +</template> |
src/components/shared/Tabs.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div :class="className"> | ||
| 3 | + <!-- Tab headers --> | ||
| 4 | + <div :class="getContainerClasses()"> | ||
| 5 | + <button | ||
| 6 | + v-for="(tab, index) in tabs" | ||
| 7 | + :key="index" | ||
| 8 | + :class="getTabHeaderClasses(index)" | ||
| 9 | + @click="handleTabChange(index)" | ||
| 10 | + role="tab" | ||
| 11 | + :aria-selected="currentTab === index" | ||
| 12 | + > | ||
| 13 | + {{ tab.label }} | ||
| 14 | + </button> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <!-- Tab content --> | ||
| 18 | + <div class="pt-4"> | ||
| 19 | + <component :is="tabs[currentTab]?.content" /> | ||
| 20 | + </div> | ||
| 21 | + </div> | ||
| 22 | +</template> | ||
| 23 | + | ||
| 24 | +<script setup> | ||
| 25 | +import { ref, computed } from 'vue'; | ||
| 26 | + | ||
| 27 | +const props = defineProps({ | ||
| 28 | + tabs: { | ||
| 29 | + type: Array, | ||
| 30 | + required: true | ||
| 31 | + }, | ||
| 32 | + activeTab: { | ||
| 33 | + type: Number, | ||
| 34 | + default: 0 | ||
| 35 | + }, | ||
| 36 | + className: { | ||
| 37 | + type: String, | ||
| 38 | + default: '' | ||
| 39 | + }, | ||
| 40 | + variant: { | ||
| 41 | + type: String, | ||
| 42 | + default: 'underline', // 'underline', 'pills', 'bordered' | ||
| 43 | + validator: (value) => ['underline', 'pills', 'bordered'].includes(value) | ||
| 44 | + }, | ||
| 45 | + size: { | ||
| 46 | + type: String, | ||
| 47 | + default: 'md', // 'sm', 'md', 'lg' | ||
| 48 | + validator: (value) => ['sm', 'md', 'lg'].includes(value) | ||
| 49 | + } | ||
| 50 | +}); | ||
| 51 | + | ||
| 52 | +const emit = defineEmits(['change']); | ||
| 53 | + | ||
| 54 | +const currentTab = ref(props.activeTab); | ||
| 55 | + | ||
| 56 | +const handleTabChange = (index) => { | ||
| 57 | + currentTab.value = index; | ||
| 58 | + emit('change', index); | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +const getSizeClasses = () => { | ||
| 62 | + switch (props.size) { | ||
| 63 | + case 'sm': return 'text-sm py-1 px-2'; | ||
| 64 | + case 'lg': return 'text-lg py-3 px-5'; | ||
| 65 | + case 'md': | ||
| 66 | + default: return 'text-base py-2 px-4'; | ||
| 67 | + } | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | +const getTabHeaderClasses = (index) => { | ||
| 71 | + const isActive = index === currentTab.value; | ||
| 72 | + const sizeClasses = getSizeClasses(); | ||
| 73 | + | ||
| 74 | + const baseClasses = 'font-medium transition-all duration-200 focus:outline-none'; | ||
| 75 | + | ||
| 76 | + switch (props.variant) { | ||
| 77 | + case 'pills': | ||
| 78 | + return `${baseClasses} ${sizeClasses} rounded-md ${ | ||
| 79 | + isActive | ||
| 80 | + ? 'bg-green-500 text-white' | ||
| 81 | + : 'text-gray-700 hover:text-green-500 hover:bg-green-50' | ||
| 82 | + }`; | ||
| 83 | + | ||
| 84 | + case 'bordered': | ||
| 85 | + return `${baseClasses} ${sizeClasses} border-b-2 ${ | ||
| 86 | + isActive | ||
| 87 | + ? 'border-green-500 text-green-600' | ||
| 88 | + : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' | ||
| 89 | + }`; | ||
| 90 | + | ||
| 91 | + case 'underline': | ||
| 92 | + default: | ||
| 93 | + return `${baseClasses} ${sizeClasses} border-b-2 ${ | ||
| 94 | + isActive | ||
| 95 | + ? 'border-green-500 text-green-600' | ||
| 96 | + : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' | ||
| 97 | + }`; | ||
| 98 | + } | ||
| 99 | +}; | ||
| 100 | + | ||
| 101 | +const getContainerClasses = () => { | ||
| 102 | + switch (props.variant) { | ||
| 103 | + case 'pills': | ||
| 104 | + return 'flex p-1 space-x-1 bg-gray-100 rounded-lg'; | ||
| 105 | + case 'bordered': | ||
| 106 | + return 'flex border-b border-gray-200'; | ||
| 107 | + case 'underline': | ||
| 108 | + default: | ||
| 109 | + return 'flex border-b border-gray-200'; | ||
| 110 | + } | ||
| 111 | +}; | ||
| 112 | +</script> |
src/context/AppContext.jsx
0 → 100644
| 1 | +import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; | ||
| 2 | + | ||
| 3 | +const AppContext = createContext(); | ||
| 4 | + | ||
| 5 | +export const AppProvider = ({ children }) => { | ||
| 6 | + const [currentUser, setCurrentUser] = useState(null); | ||
| 7 | + const [activities, setActivities] = useState([]); | ||
| 8 | + const [loading, setLoading] = useState(true); | ||
| 9 | + const [error, setError] = useState(null); | ||
| 10 | + const [registrations, setRegistrations] = useState([]); | ||
| 11 | + const [userMessages, setUserMessages] = useState([]); | ||
| 12 | + | ||
| 13 | + // Initialize app data | ||
| 14 | + useEffect(() => { | ||
| 15 | + const fetchInitialData = async () => { | ||
| 16 | + try { | ||
| 17 | + setLoading(true); | ||
| 18 | + | ||
| 19 | + // Fetch users data - In a real app, this would be a real API call | ||
| 20 | + const usersResponse = await fetch('/data/users.json'); | ||
| 21 | + const usersData = await usersResponse.json(); | ||
| 22 | + | ||
| 23 | + // For demo purposes, set the first user as current user | ||
| 24 | + setCurrentUser(usersData[0]); | ||
| 25 | + | ||
| 26 | + // Fetch activities | ||
| 27 | + const activitiesResponse = await fetch('/data/activities.json'); | ||
| 28 | + const activitiesData = await activitiesResponse.json(); | ||
| 29 | + setActivities(activitiesData); | ||
| 30 | + | ||
| 31 | + // Fetch registrations | ||
| 32 | + const registrationsResponse = await fetch('/data/registrations.json'); | ||
| 33 | + const registrationsData = await registrationsResponse.json(); | ||
| 34 | + setRegistrations(registrationsData); | ||
| 35 | + | ||
| 36 | + // Fetch messages | ||
| 37 | + const messagesResponse = await fetch('/data/messages.json'); | ||
| 38 | + const messagesData = await messagesResponse.json(); | ||
| 39 | + setUserMessages(messagesData); | ||
| 40 | + | ||
| 41 | + setLoading(false); | ||
| 42 | + } catch (err) { | ||
| 43 | + console.error('Failed to fetch initial data:', err); | ||
| 44 | + setError('Failed to load application data. Please try again later.'); | ||
| 45 | + setLoading(false); | ||
| 46 | + } | ||
| 47 | + }; | ||
| 48 | + | ||
| 49 | + fetchInitialData(); | ||
| 50 | + }, []); | ||
| 51 | + | ||
| 52 | + // Get activity by ID | ||
| 53 | + const getActivityById = useCallback((activityId) => { | ||
| 54 | + return activities.find(activity => activity.id === activityId) || null; | ||
| 55 | + }, [activities]); | ||
| 56 | + | ||
| 57 | + // Get user's registrations | ||
| 58 | + const getUserRegistrations = useCallback(() => { | ||
| 59 | + if (!currentUser) return []; | ||
| 60 | + return registrations.filter(reg => reg.user_id === currentUser.id); | ||
| 61 | + }, [currentUser, registrations]); | ||
| 62 | + | ||
| 63 | + // Register for an activity | ||
| 64 | + const registerForActivity = useCallback((activityId, formData) => { | ||
| 65 | + if (!currentUser) return { success: false, error: 'User not logged in' }; | ||
| 66 | + | ||
| 67 | + // In a real app, this would make an API call | ||
| 68 | + const newRegistration = { | ||
| 69 | + id: `R${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 70 | + activity_id: activityId, | ||
| 71 | + user_id: currentUser.id, | ||
| 72 | + registration_time: new Date().toISOString().replace('T', ' ').substring(0, 19), | ||
| 73 | + status: 'pending', | ||
| 74 | + custom_fields: formData.fields, | ||
| 75 | + custom_answers: formData.answers | ||
| 76 | + }; | ||
| 77 | + | ||
| 78 | + setRegistrations(prev => [...prev, newRegistration]); | ||
| 79 | + return { success: true, registrationId: newRegistration.id }; | ||
| 80 | + }, [currentUser]); | ||
| 81 | + | ||
| 82 | + // Create a new activity | ||
| 83 | + const createActivity = useCallback((activityData) => { | ||
| 84 | + if (!currentUser) return { success: false, error: 'User not logged in' }; | ||
| 85 | + | ||
| 86 | + // In a real app, this would make an API call | ||
| 87 | + const newActivity = { | ||
| 88 | + id: `A${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 89 | + organizer_id: currentUser.id, | ||
| 90 | + organizer_name: currentUser.name, | ||
| 91 | + ...activityData, | ||
| 92 | + participant_count: 0, | ||
| 93 | + is_published: activityData.is_published || true, | ||
| 94 | + is_public: activityData.is_public || true, | ||
| 95 | + }; | ||
| 96 | + | ||
| 97 | + setActivities(prev => [...prev, newActivity]); | ||
| 98 | + return { success: true, activityId: newActivity.id }; | ||
| 99 | + }, [currentUser]); | ||
| 100 | + | ||
| 101 | + // Check in for an activity | ||
| 102 | + const checkInForActivity = useCallback((activityId, registrationId, method = 'manual') => { | ||
| 103 | + if (!currentUser) return { success: false, error: 'User not logged in' }; | ||
| 104 | + | ||
| 105 | + // In a real app, this would make an API call | ||
| 106 | + const checkinData = { | ||
| 107 | + id: `C${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 108 | + activity_id: activityId, | ||
| 109 | + user_id: currentUser.id, | ||
| 110 | + registration_id: registrationId, | ||
| 111 | + checkin_time: new Date().toISOString().replace('T', ' ').substring(0, 19), | ||
| 112 | + checkin_type: method, | ||
| 113 | + status: 'successful', | ||
| 114 | + is_late: false | ||
| 115 | + }; | ||
| 116 | + | ||
| 117 | + // In a real app, we would update the backend | ||
| 118 | + return { success: true, checkin: checkinData }; | ||
| 119 | + }, [currentUser]); | ||
| 120 | + | ||
| 121 | + // Get user messages | ||
| 122 | + const getUserMessages = useCallback(() => { | ||
| 123 | + if (!currentUser) return []; | ||
| 124 | + return userMessages.filter(msg => msg.recipient_id === currentUser.id); | ||
| 125 | + }, [currentUser, userMessages]); | ||
| 126 | + | ||
| 127 | + // Toggle read status of a message | ||
| 128 | + const toggleMessageReadStatus = useCallback((messageId) => { | ||
| 129 | + setUserMessages(prev => | ||
| 130 | + prev.map(msg => | ||
| 131 | + msg.id === messageId | ||
| 132 | + ? { ...msg, read_status: !msg.read_status } | ||
| 133 | + : msg | ||
| 134 | + ) | ||
| 135 | + ); | ||
| 136 | + }, []); | ||
| 137 | + | ||
| 138 | + const contextValue = { | ||
| 139 | + currentUser, | ||
| 140 | + activities, | ||
| 141 | + loading, | ||
| 142 | + error, | ||
| 143 | + registrations, | ||
| 144 | + userMessages, | ||
| 145 | + getActivityById, | ||
| 146 | + getUserRegistrations, | ||
| 147 | + registerForActivity, | ||
| 148 | + createActivity, | ||
| 149 | + checkInForActivity, | ||
| 150 | + getUserMessages, | ||
| 151 | + toggleMessageReadStatus | ||
| 152 | + }; | ||
| 153 | + | ||
| 154 | + return ( | ||
| 155 | + <AppContext.Provider value={contextValue}> | ||
| 156 | + {children} | ||
| 157 | + </AppContext.Provider> | ||
| 158 | + ); | ||
| 159 | +}; | ||
| 160 | + | ||
| 161 | +export const useApp = () => { | ||
| 162 | + const context = useContext(AppContext); | ||
| 163 | + if (!context) { | ||
| 164 | + throw new Error('useApp must be used within an AppProvider'); | ||
| 165 | + } | ||
| 166 | + return context; | ||
| 167 | +}; | ||
| 168 | + | ||
| 169 | +export default AppContext; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/hooks/useAuth.js
0 → 100644
| 1 | +import { useState, useEffect } from 'react'; | ||
| 2 | +import { fetchUsers } from '../utils/api'; | ||
| 3 | + | ||
| 4 | +// A custom hook to manage authentication state | ||
| 5 | +const useAuth = () => { | ||
| 6 | + const [user, setUser] = useState(null); | ||
| 7 | + const [loading, setLoading] = useState(true); | ||
| 8 | + const [error, setError] = useState(null); | ||
| 9 | + | ||
| 10 | + useEffect(() => { | ||
| 11 | + // In a real app, this would check if the user is logged in via JWT, cookies, etc. | ||
| 12 | + // For this demo, we'll just load the first user from the mock data | ||
| 13 | + const checkAuth = async () => { | ||
| 14 | + try { | ||
| 15 | + const users = await fetchUsers(); | ||
| 16 | + // For demo purposes, use the first user as the logged-in user | ||
| 17 | + if (users && users.length > 0) { | ||
| 18 | + // Check if there's a stored user ID in local storage (for persistence) | ||
| 19 | + const storedUserId = localStorage.getItem('currentUserId'); | ||
| 20 | + if (storedUserId) { | ||
| 21 | + const storedUser = users.find(u => u.id === storedUserId); | ||
| 22 | + if (storedUser) { | ||
| 23 | + setUser(storedUser); | ||
| 24 | + } else { | ||
| 25 | + setUser(users[0]); // Fallback to first user | ||
| 26 | + } | ||
| 27 | + } else { | ||
| 28 | + setUser(users[0]); | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + setLoading(false); | ||
| 32 | + } catch (err) { | ||
| 33 | + console.error('Authentication error:', err); | ||
| 34 | + setError('Failed to authenticate. Please try again.'); | ||
| 35 | + setLoading(false); | ||
| 36 | + } | ||
| 37 | + }; | ||
| 38 | + | ||
| 39 | + checkAuth(); | ||
| 40 | + }, []); | ||
| 41 | + | ||
| 42 | + // Login function - in a real app, this would validate credentials | ||
| 43 | + const login = async (userId) => { | ||
| 44 | + try { | ||
| 45 | + setLoading(true); | ||
| 46 | + const users = await fetchUsers(); | ||
| 47 | + const foundUser = users.find(u => u.id === userId); | ||
| 48 | + | ||
| 49 | + if (foundUser) { | ||
| 50 | + setUser(foundUser); | ||
| 51 | + localStorage.setItem('currentUserId', userId); | ||
| 52 | + setLoading(false); | ||
| 53 | + return { success: true }; | ||
| 54 | + } else { | ||
| 55 | + setError('User not found'); | ||
| 56 | + setLoading(false); | ||
| 57 | + return { success: false, error: 'User not found' }; | ||
| 58 | + } | ||
| 59 | + } catch (err) { | ||
| 60 | + console.error('Login error:', err); | ||
| 61 | + setError('Failed to log in. Please try again.'); | ||
| 62 | + setLoading(false); | ||
| 63 | + return { success: false, error: err.message }; | ||
| 64 | + } | ||
| 65 | + }; | ||
| 66 | + | ||
| 67 | + // Logout function | ||
| 68 | + const logout = () => { | ||
| 69 | + setUser(null); | ||
| 70 | + localStorage.removeItem('currentUserId'); | ||
| 71 | + }; | ||
| 72 | + | ||
| 73 | + // Switch user (for demo purposes) | ||
| 74 | + const switchUser = async (userId) => { | ||
| 75 | + return await login(userId); | ||
| 76 | + }; | ||
| 77 | + | ||
| 78 | + return { | ||
| 79 | + user, | ||
| 80 | + loading, | ||
| 81 | + error, | ||
| 82 | + login, | ||
| 83 | + logout, | ||
| 84 | + switchUser, | ||
| 85 | + isAuthenticated: !!user | ||
| 86 | + }; | ||
| 87 | +}; | ||
| 88 | + | ||
| 89 | +export default useAuth; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/index.css
0 → 100644
| 1 | +@tailwind base; | ||
| 2 | +@tailwind components; | ||
| 3 | +@tailwind utilities; | ||
| 4 | + | ||
| 5 | +::-webkit-scrollbar { | ||
| 6 | + width: 5px; | ||
| 7 | + height: 5px; | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +::-webkit-scrollbar-track { | ||
| 11 | + background-color: transparent; | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +::-webkit-scrollbar-thumb { | ||
| 15 | + border-radius: 25px; | ||
| 16 | + transition: all 0.3s; | ||
| 17 | + background-color: rgba(106, 115, 125, 0.2); | ||
| 18 | + &:hover { | ||
| 19 | + background-color: rgba(106, 115, 125, 0.27); | ||
| 20 | + } | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +::-webkit-scrollbar-corner { | ||
| 24 | + display: none; | ||
| 25 | +} |
src/main.js
0 → 100644
| 1 | +import { createApp } from 'vue' | ||
| 2 | +import { createPinia } from 'pinia' | ||
| 3 | +import { createRouter, createWebHistory } from 'vue-router' | ||
| 4 | +import App from './App.vue' | ||
| 5 | +import './index.css' | ||
| 6 | + | ||
| 7 | +// 创建Vue应用实例 | ||
| 8 | +const app = createApp(App) | ||
| 9 | + | ||
| 10 | +// 创建Pinia状态管理实例 | ||
| 11 | +const pinia = createPinia() | ||
| 12 | +app.use(pinia) | ||
| 13 | + | ||
| 14 | +// 创建路由实例 | ||
| 15 | +const router = createRouter({ | ||
| 16 | + history: createWebHistory(), | ||
| 17 | + routes: [ | ||
| 18 | + { path: '/', component: () => import('./pages/HomePage.vue') }, | ||
| 19 | + { path: '/activity/:activityId', component: () => import('./pages/ActivityDetail.vue') }, | ||
| 20 | + { path: '/create-activity', component: () => import('./pages/CreateActivity.vue') }, | ||
| 21 | + { path: '/profile', component: () => import('./pages/UserProfile.vue') }, | ||
| 22 | + { path: '/registration/:activityId', component: () => import('./pages/Registration.vue') }, | ||
| 23 | + { path: '/check-in/:activityId', component: () => import('./pages/CheckIn.vue') }, | ||
| 24 | + { path: '/messages/:activityId', component: () => import('./pages/Messages.vue') }, | ||
| 25 | + { path: '/:pathMatch(.*)*', redirect: '/' } | ||
| 26 | + ] | ||
| 27 | +}) | ||
| 28 | +app.use(router) | ||
| 29 | + | ||
| 30 | +// 挂载应用 | ||
| 31 | +app.mount('#root') |
src/pages/ActivityDetail.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50"> | ||
| 3 | + <!-- Activity Header --> | ||
| 4 | + <div class="bg-white shadow-sm"> | ||
| 5 | + <div class="container mx-auto px-4 py-4"> | ||
| 6 | + <button @click="goBack" class="flex items-center text-gray-600 hover:text-green-500"> | ||
| 7 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" | ||
| 8 | + fill="currentColor"> | ||
| 9 | + <path fill-rule="evenodd" | ||
| 10 | + d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" | ||
| 11 | + clip-rule="evenodd" /> | ||
| 12 | + </svg> | ||
| 13 | + 返回 | ||
| 14 | + </button> | ||
| 15 | + </div> | ||
| 16 | + </div> | ||
| 17 | + | ||
| 18 | + <!-- Loading State --> | ||
| 19 | + <div v-if="loading" class="min-h-screen flex justify-center items-center"> | ||
| 20 | + <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-green-500"></div> | ||
| 21 | + </div> | ||
| 22 | + | ||
| 23 | + <!-- Error State --> | ||
| 24 | + <div v-else-if="error || !activity" | ||
| 25 | + class="min-h-screen flex flex-col justify-center items-center bg-gray-50 px-4"> | ||
| 26 | + <div class="text-red-500 text-6xl mb-4"> | ||
| 27 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-24 w-24" fill="none" viewBox="0 0 24 24" | ||
| 28 | + stroke="currentColor"> | ||
| 29 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 30 | + d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 31 | + </svg> | ||
| 32 | + </div> | ||
| 33 | + <h1 class="text-2xl font-bold mb-2">活动不存在</h1> | ||
| 34 | + <p class="text-gray-600 mb-6">{{ error || '该活动可能已被删除或不存在' }}</p> | ||
| 35 | + <Button @click="goBack" variant="primary">返回上一页</Button> | ||
| 36 | + </div> | ||
| 37 | + | ||
| 38 | + <!-- Activity Content --> | ||
| 39 | + <template v-else> | ||
| 40 | + <!-- Activity Cover --> | ||
| 41 | + <div class="relative h-64 md:h-80 bg-gray-300 overflow-hidden"> | ||
| 42 | + <img :src="getActivityImage(activity.id)" :alt="activity.title" class="w-full h-full object-cover" /> | ||
| 43 | + <div class="absolute inset-0 bg-black bg-opacity-40"></div> | ||
| 44 | + <div class="absolute bottom-0 left-0 right-0 p-6"> | ||
| 45 | + <div class="container mx-auto"> | ||
| 46 | + <span | ||
| 47 | + :class="['inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium mb-2', activityStatus.class]"> | ||
| 48 | + {{ activityStatus.text }} | ||
| 49 | + </span> | ||
| 50 | + <h1 class="text-2xl md:text-3xl font-bold text-white">{{ activity.title }}</h1> | ||
| 51 | + </div> | ||
| 52 | + </div> | ||
| 53 | + </div> | ||
| 54 | + | ||
| 55 | + <!-- Activity Content --> | ||
| 56 | + <div class="container mx-auto px-4 py-8"> | ||
| 57 | + <div class="flex flex-col md:flex-row gap-8"> | ||
| 58 | + <!-- Main content --> | ||
| 59 | + <div class="w-full md:w-2/3"> | ||
| 60 | + <!-- Organizer --> | ||
| 61 | + <div class="mb-8 flex items-center"> | ||
| 62 | + <div class="flex items-center"> | ||
| 63 | + <div class="h-12 w-12 rounded-full overflow-hidden bg-gray-200 mr-3"> | ||
| 64 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-full w-full text-gray-400" | ||
| 65 | + fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 66 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" | ||
| 67 | + d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> | ||
| 68 | + </svg> | ||
| 69 | + </div> | ||
| 70 | + <div> | ||
| 71 | + <div class="font-medium">主办方:{{ activity.organizer_name }}</div> | ||
| 72 | + <div class="text-sm text-gray-500">活动组织者</div> | ||
| 73 | + </div> | ||
| 74 | + </div> | ||
| 75 | + </div> | ||
| 76 | + | ||
| 77 | + <!-- Activity Tabs --> | ||
| 78 | + <Tabs :tabs="tabs" /> | ||
| 79 | + </div> | ||
| 80 | + | ||
| 81 | + <!-- Sidebar --> | ||
| 82 | + <div class="w-full md:w-1/3 mt-8 md:mt-0"> | ||
| 83 | + <div class="bg-white rounded-lg shadow-sm p-6 mb-6"> | ||
| 84 | + <h3 class="text-lg font-medium text-gray-900 mb-4">活动信息</h3> | ||
| 85 | + | ||
| 86 | + <div class="space-y-4"> | ||
| 87 | + <!-- Date and Time --> | ||
| 88 | + <div class="flex"> | ||
| 89 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mt-0.5 mr-3" | ||
| 90 | + fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 91 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 92 | + d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> | ||
| 93 | + </svg> | ||
| 94 | + <div> | ||
| 95 | + <div class="font-medium">活动时间</div> | ||
| 96 | + <div class="text-gray-600">{{ formatDate(activity.start_time) }}</div> | ||
| 97 | + </div> | ||
| 98 | + </div> | ||
| 99 | + | ||
| 100 | + <!-- Location --> | ||
| 101 | + <div class="flex"> | ||
| 102 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mt-0.5 mr-3" | ||
| 103 | + fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 104 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 105 | + d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /> | ||
| 106 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 107 | + d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /> | ||
| 108 | + </svg> | ||
| 109 | + <div> | ||
| 110 | + <div class="font-medium">活动地点</div> | ||
| 111 | + <div class="text-gray-600"> | ||
| 112 | + {{ activity.activity_type === 'online' | ||
| 113 | + ? '线上活动' + (activity.online_link ? `(${activity.online_link})` : '') | ||
| 114 | + : (activity.location ? (typeof activity.location === 'object' ? | ||
| 115 | + activity.location.name : activity.location) : '地点未设置') | ||
| 116 | + }} | ||
| 117 | + </div> | ||
| 118 | + </div> | ||
| 119 | + </div> | ||
| 120 | + | ||
| 121 | + <!-- Registration --> | ||
| 122 | + <div class="flex"> | ||
| 123 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mt-0.5 mr-3" | ||
| 124 | + fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 125 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 126 | + d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" /> | ||
| 127 | + </svg> | ||
| 128 | + <div> | ||
| 129 | + <div class="font-medium">报名时间</div> | ||
| 130 | + <div class="text-gray-600">{{ formatDate(activity.registration_start) }} - {{ | ||
| 131 | + formatDate(activity.registration_end) }}</div> | ||
| 132 | + </div> | ||
| 133 | + </div> | ||
| 134 | + | ||
| 135 | + <!-- Participants --> | ||
| 136 | + <div class="flex"> | ||
| 137 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mt-0.5 mr-3" | ||
| 138 | + fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 139 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 140 | + d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /> | ||
| 141 | + </svg> | ||
| 142 | + <div> | ||
| 143 | + <div class="font-medium">参与人数</div> | ||
| 144 | + <div class="text-gray-600">{{ activity.participant_count }}/{{ | ||
| 145 | + activity.max_participants }}</div> | ||
| 146 | + </div> | ||
| 147 | + </div> | ||
| 148 | + | ||
| 149 | + <!-- Registration progress --> | ||
| 150 | + <div class="mt-2"> | ||
| 151 | + <div class="flex items-center justify-between text-sm mb-1"> | ||
| 152 | + <span>报名进度</span> | ||
| 153 | + <span>{{ Math.round((activity.participant_count / activity.max_participants) * | ||
| 154 | + 100) }}%</span> | ||
| 155 | + </div> | ||
| 156 | + <div class="w-full bg-gray-200 rounded-full h-2"> | ||
| 157 | + <div class="bg-gradient-to-r from-green-400 to-blue-500 h-2 rounded-full" | ||
| 158 | + :style="{ width: `${Math.min((activity.participant_count / activity.max_participants) * 100, 100)}%` }"> | ||
| 159 | + </div> | ||
| 160 | + </div> | ||
| 161 | + </div> | ||
| 162 | + | ||
| 163 | + <!-- Registration Status --> | ||
| 164 | + <div v-if="hasRegistered" | ||
| 165 | + class="mt-2 bg-green-50 border border-green-100 rounded-md p-4"> | ||
| 166 | + <div class="flex items-center"> | ||
| 167 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" | ||
| 168 | + viewBox="0 0 20 20" fill="currentColor"> | ||
| 169 | + <path fill-rule="evenodd" | ||
| 170 | + d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" | ||
| 171 | + clip-rule="evenodd" /> | ||
| 172 | + </svg> | ||
| 173 | + <span class="font-medium text-green-800">您已报名此活动</span> | ||
| 174 | + </div> | ||
| 175 | + <div class="mt-2 flex items-center"> | ||
| 176 | + <span class="text-sm text-green-700 mr-2">报名状态:</span> | ||
| 177 | + <span :class="registrationStatusBadge.class">{{ registrationStatusBadge.text | ||
| 178 | + }}</span> | ||
| 179 | + </div> | ||
| 180 | + </div> | ||
| 181 | + | ||
| 182 | + <!-- Registration button or message --> | ||
| 183 | + <template v-if="!hasRegistered"> | ||
| 184 | + <Button variant="primary" size="lg" block | ||
| 185 | + :disabled="!isRegistrationOpen || activity.participant_count >= activity.max_participants" | ||
| 186 | + @click="handleRegistration" class="mt-4"> | ||
| 187 | + {{ isRegistrationOpen | ||
| 188 | + ? activity.participant_count >= activity.max_participants | ||
| 189 | + ? '名额已满' | ||
| 190 | + : '立即报名' | ||
| 191 | + : '报名已截止' }} | ||
| 192 | + </Button> | ||
| 193 | + </template> | ||
| 194 | + | ||
| 195 | + <RouterLink v-if="hasRegistered" :to="`/check-in/${activity.id}`"> | ||
| 196 | + <Button variant="secondary" size="md" block class="mt-2"> | ||
| 197 | + 活动签到 | ||
| 198 | + </Button> | ||
| 199 | + </RouterLink> | ||
| 200 | + </div> | ||
| 201 | + </div> | ||
| 202 | + | ||
| 203 | + <!-- Similar Activities --> | ||
| 204 | + <div v-if="similarActivities.length > 0" class="bg-white rounded-lg shadow-sm p-6"> | ||
| 205 | + <h3 class="text-lg font-medium text-gray-900 mb-4">相似活动推荐</h3> | ||
| 206 | + <div class="space-y-4"> | ||
| 207 | + <ActivityCard v-for="activity in similarActivities" :key="activity.id" | ||
| 208 | + :activity="activity" variant="compact" /> | ||
| 209 | + </div> | ||
| 210 | + </div> | ||
| 211 | + </div> | ||
| 212 | + </div> | ||
| 213 | + </div> | ||
| 214 | + </template> | ||
| 215 | + | ||
| 216 | + <!-- Register Modal --> | ||
| 217 | + <Modal v-if="showRegisterModal" @close="showRegisterModal = false"> | ||
| 218 | + <template #title>活动报名</template> | ||
| 219 | + <template #content> | ||
| 220 | + <form @submit.prevent="submitRegistration"> | ||
| 221 | + <!-- Registration form fields --> | ||
| 222 | + </form> | ||
| 223 | + </template> | ||
| 224 | + </Modal> | ||
| 225 | + </div> | ||
| 226 | +</template> | ||
| 227 | + | ||
| 228 | +<script setup> | ||
| 229 | +import { ref, computed, onMounted } from 'vue' | ||
| 230 | +import { useRoute, useRouter } from 'vue-router' | ||
| 231 | +import { useAppStore } from '../stores/app' | ||
| 232 | +import Button from '../components/shared/Button.vue' | ||
| 233 | +import Modal from '../components/shared/Modal.vue' | ||
| 234 | +import Tabs from '../components/shared/Tabs.vue' | ||
| 235 | +import ActivityCard from '../components/shared/ActivityCard.vue' | ||
| 236 | + | ||
| 237 | +const route = useRoute() | ||
| 238 | +const router = useRouter() | ||
| 239 | +const store = useAppStore() | ||
| 240 | + | ||
| 241 | +// State | ||
| 242 | +const activity = ref(null) | ||
| 243 | +const loading = ref(true) | ||
| 244 | +const error = ref(null) | ||
| 245 | +const showRegisterModal = ref(false) | ||
| 246 | +const similarActivities = ref([]) | ||
| 247 | +const hasRegistered = ref(false) | ||
| 248 | +const registrationStatus = ref(null) | ||
| 249 | + | ||
| 250 | +// Computed | ||
| 251 | +const activityStatus = computed(() => { | ||
| 252 | + if (!activity.value) return {} | ||
| 253 | + | ||
| 254 | + const now = new Date() | ||
| 255 | + const startTime = new Date(activity.value.start_time.replace(' ', 'T')) | ||
| 256 | + const endTime = new Date(activity.value.end_time.replace(' ', 'T')) | ||
| 257 | + const registrationEnd = new Date(activity.value.registration_end.replace(' ', 'T')) | ||
| 258 | + | ||
| 259 | + if (now > endTime) { | ||
| 260 | + return { | ||
| 261 | + text: '已结束', | ||
| 262 | + class: 'bg-gray-100 text-gray-800' | ||
| 263 | + } | ||
| 264 | + } else if (now >= startTime && now <= endTime) { | ||
| 265 | + return { | ||
| 266 | + text: '进行中', | ||
| 267 | + class: 'bg-green-100 text-green-800' | ||
| 268 | + } | ||
| 269 | + } else if (now <= registrationEnd) { | ||
| 270 | + return { | ||
| 271 | + text: '报名中', | ||
| 272 | + class: 'bg-blue-100 text-blue-800' | ||
| 273 | + } | ||
| 274 | + } else { | ||
| 275 | + return { | ||
| 276 | + text: '即将开始', | ||
| 277 | + class: 'bg-yellow-100 text-yellow-800' | ||
| 278 | + } | ||
| 279 | + } | ||
| 280 | +}) | ||
| 281 | + | ||
| 282 | +const isRegistrationOpen = computed(() => { | ||
| 283 | + if (!activity.value) return false | ||
| 284 | + const now = new Date() | ||
| 285 | + return now >= new Date(activity.value.registration_start.replace(' ', 'T')) && | ||
| 286 | + now <= new Date(activity.value.registration_end.replace(' ', 'T')) | ||
| 287 | +}) | ||
| 288 | + | ||
| 289 | +const registrationStatusBadge = computed(() => { | ||
| 290 | + if (!registrationStatus.value) return null | ||
| 291 | + | ||
| 292 | + const statusMap = { | ||
| 293 | + pending: { text: '审核中', class: 'bg-yellow-100 text-yellow-800' }, | ||
| 294 | + approved: { text: '已通过', class: 'bg-green-100 text-green-800' }, | ||
| 295 | + rejected: { text: '已拒绝', class: 'bg-red-100 text-red-800' }, | ||
| 296 | + waitlist: { text: '候补', class: 'bg-purple-100 text-purple-800' } | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + return statusMap[registrationStatus.value] || { | ||
| 300 | + text: registrationStatus.value, | ||
| 301 | + class: 'bg-gray-100 text-gray-800' | ||
| 302 | + } | ||
| 303 | +}) | ||
| 304 | + | ||
| 305 | +const tabs = computed(() => [ | ||
| 306 | + { | ||
| 307 | + label: '活动详情', | ||
| 308 | + content: activity.value?.description.split('\n').map((paragraph, idx) => ( | ||
| 309 | + `<p key="${idx}" class="mb-4">${paragraph}</p>` | ||
| 310 | + )).join('') | ||
| 311 | + }, | ||
| 312 | + { | ||
| 313 | + label: '参与须知', | ||
| 314 | + content: ` | ||
| 315 | + <h3 class="font-medium text-lg mb-4">参与须知</h3> | ||
| 316 | + <ul class="list-disc pl-5 space-y-2"> | ||
| 317 | + <li>请准时到达活动地点或登录线上会议</li> | ||
| 318 | + <li>请提前阅读相关书籍或材料</li> | ||
| 319 | + <li>活动开始后,请将手机调至静音模式</li> | ||
| 320 | + <li>尊重他人发言,不打断他人</li> | ||
| 321 | + <li>可携带笔记本进行记录</li> | ||
| 322 | + <li>如需取消参与,请提前24小时通知主办方</li> | ||
| 323 | + </ul> | ||
| 324 | + ` | ||
| 325 | + }, | ||
| 326 | + { | ||
| 327 | + label: '常见问题', | ||
| 328 | + content: ` | ||
| 329 | + <div className="py-4"> | ||
| 330 | + <div className="space-y-6"> | ||
| 331 | + <div> | ||
| 332 | + <h4 className="font-medium text-gray-900">如何取消报名?</h4> | ||
| 333 | + <p className="mt-2 text-gray-600">您可以在"我的活动"页面找到已报名的活动,点击"取消报名"按钮即可。请注意,活动开始前24小时内取消将无法获得退款。</p> | ||
| 334 | + </div> | ||
| 335 | + <div> | ||
| 336 | + <h4 className="font-medium text-gray-900">活动材料如何获取?</h4> | ||
| 337 | + <p className="mt-2 text-gray-600">报名成功后,您将在"我的活动"页面看到活动详情,相关材料可在页面底部下载或通过邮件接收。</p> | ||
| 338 | + </div> | ||
| 339 | + <div> | ||
| 340 | + <h4 className="font-medium text-gray-900">线上活动如何参加?</h4> | ||
| 341 | + <p className="mt-2 text-gray-600">线上活动将在活动开始前30分钟发送会议链接到您的邮箱和手机短信,您也可以在"我的活动"页面找到入口链接。</p> | ||
| 342 | + </div> | ||
| 343 | + </div> | ||
| 344 | + </div> | ||
| 345 | + `} | ||
| 346 | +]) | ||
| 347 | + | ||
| 348 | +// Functions | ||
| 349 | +const goBack = () => { | ||
| 350 | + router.back() | ||
| 351 | +} | ||
| 352 | + | ||
| 353 | +const getActivityImage = (activityId) => { | ||
| 354 | + return `/ assets / images / activities / ${activityId}.jpg` | ||
| 355 | +} | ||
| 356 | + | ||
| 357 | +const formatDate = (dateString) => { | ||
| 358 | + if (!dateString) return '' | ||
| 359 | + const date = new Date(dateString.replace(' ', 'T')) | ||
| 360 | + return date.toLocaleString('zh-CN', { | ||
| 361 | + year: 'numeric', | ||
| 362 | + month: '2-digit', | ||
| 363 | + day: '2-digit', | ||
| 364 | + hour: '2-digit', | ||
| 365 | + minute: '2-digit' | ||
| 366 | + }) | ||
| 367 | +} | ||
| 368 | + | ||
| 369 | +const handleRegistration = () => { | ||
| 370 | + showRegisterModal.value = true | ||
| 371 | +} | ||
| 372 | + | ||
| 373 | +const submitRegistration = async () => { | ||
| 374 | + // TODO: Implement registration submission | ||
| 375 | + showRegisterModal.value = false | ||
| 376 | +} | ||
| 377 | + | ||
| 378 | +// Fetch activity data | ||
| 379 | +onMounted(async () => { | ||
| 380 | + try { | ||
| 381 | + const activityId = route.params.id | ||
| 382 | + const response = await store.fetchActivity(activityId) | ||
| 383 | + activity.value = response | ||
| 384 | + loading.value = false | ||
| 385 | + | ||
| 386 | + // Check registration status | ||
| 387 | + const registration = await store.checkRegistration(activityId) | ||
| 388 | + hasRegistered.value = registration !== null | ||
| 389 | + registrationStatus.value = registration?.status | ||
| 390 | + | ||
| 391 | + // Fetch similar activities | ||
| 392 | + similarActivities.value = await store.fetchSimilarActivities(activityId) | ||
| 393 | + } catch (err) { | ||
| 394 | + error.value = err.message | ||
| 395 | + loading.value = false | ||
| 396 | + } | ||
| 397 | +}) | ||
| 398 | +</script> |
src/pages/CheckIn.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50"> | ||
| 3 | + <!-- Loading State --> | ||
| 4 | + <div v-if="loading" class="min-h-screen flex justify-center items-center bg-gray-50"> | ||
| 5 | + <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-green-500"></div> | ||
| 6 | + </div> | ||
| 7 | + | ||
| 8 | + <!-- Error State --> | ||
| 9 | + <div v-else-if="error" class="min-h-screen flex flex-col justify-center items-center bg-gray-50 px-4"> | ||
| 10 | + <div class="text-red-500 text-6xl mb-4"> | ||
| 11 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-24 w-24" fill="none" viewBox="0 0 24 24" | ||
| 12 | + stroke="currentColor"> | ||
| 13 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 14 | + d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 15 | + </svg> | ||
| 16 | + </div> | ||
| 17 | + <h1 class="text-2xl font-bold mb-2">无法签到</h1> | ||
| 18 | + <p class="text-gray-600 mb-6">{{ error }}</p> | ||
| 19 | + <Button @click="goBack" variant="primary">返回上一页</Button> | ||
| 20 | + </div> | ||
| 21 | + | ||
| 22 | + <!-- Already Checked In --> | ||
| 23 | + <div v-else-if="userCheckIn" class="py-8"> | ||
| 24 | + <div class="container mx-auto px-4"> | ||
| 25 | + <div class="max-w-md mx-auto bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 26 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 px-6 py-4"> | ||
| 27 | + <h1 class="text-2xl font-bold text-white">签到成功</h1> | ||
| 28 | + </div> | ||
| 29 | + | ||
| 30 | + <div class="p-6 text-center"> | ||
| 31 | + <div class="flex justify-center"> | ||
| 32 | + <div class="rounded-full bg-green-100 p-4"> | ||
| 33 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-green-500" fill="none" | ||
| 34 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 35 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 36 | + d="M5 13l4 4L19 7" /> | ||
| 37 | + </svg> | ||
| 38 | + </div> | ||
| 39 | + </div> | ||
| 40 | + | ||
| 41 | + <h2 class="text-2xl font-bold text-gray-800 mt-6">您已完成签到</h2> | ||
| 42 | + <p class="text-gray-600 mt-2">签到时间:{{ formatDate(userCheckIn.check_in_time) }}</p> | ||
| 43 | + <p class="text-gray-600">祝您阅读愉快!</p> | ||
| 44 | + | ||
| 45 | + <div class="mt-8"> | ||
| 46 | + <h3 class="font-semibold text-gray-800 mb-2">活动信息</h3> | ||
| 47 | + <div class="bg-gray-50 rounded-lg p-4 text-left"> | ||
| 48 | + <p class="font-medium text-gray-900">{{ activity.title }}</p> | ||
| 49 | + <p class="text-gray-600 text-sm mt-1"> | ||
| 50 | + 时间:{{ formatDate(activity.start_time) }} - {{ formatDate(activity.end_time) }} | ||
| 51 | + </p> | ||
| 52 | + <p class="text-gray-600 text-sm mt-1"> | ||
| 53 | + 地点:{{ activity.activity_type === 'online' ? '线上活动' : (activity.location ? (typeof | ||
| 54 | + activity.location === 'object' ? activity.location.name : activity.location) : | ||
| 55 | + '地点未设置') }} | ||
| 56 | + </p> | ||
| 57 | + </div> | ||
| 58 | + </div> | ||
| 59 | + | ||
| 60 | + <Button @click="goToActivityDetail" variant="primary" class="mt-8"> | ||
| 61 | + 返回活动详情 | ||
| 62 | + </Button> | ||
| 63 | + </div> | ||
| 64 | + </div> | ||
| 65 | + </div> | ||
| 66 | + </div> | ||
| 67 | + | ||
| 68 | + <!-- Activity Not Now --> | ||
| 69 | + <div v-else-if="!isActivityNow()" class="py-8"> | ||
| 70 | + <div class="container mx-auto px-4"> | ||
| 71 | + <div class="max-w-md mx-auto bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 72 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 px-6 py-4"> | ||
| 73 | + <h1 class="text-2xl font-bold text-white">暂不可签到</h1> | ||
| 74 | + </div> | ||
| 75 | + | ||
| 76 | + <div class="p-6"> | ||
| 77 | + <div class="text-center"> | ||
| 78 | + <div class="inline-block rounded-full bg-blue-100 p-4"> | ||
| 79 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-blue-500" fill="none" | ||
| 80 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 81 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 82 | + d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 83 | + </svg> | ||
| 84 | + </div> | ||
| 85 | + | ||
| 86 | + <h2 class="text-xl font-bold text-gray-800 mt-6">签到尚未开始</h2> | ||
| 87 | + <p class="text-gray-600 mt-2"> | ||
| 88 | + {{ new Date() < new Date(activity.start_time.replace(' ', ' T')) ? '活动签到将于活动开始前30分钟开放' | ||
| 89 | + : '活动已结束,签到已关闭' }} </p> | ||
| 90 | + | ||
| 91 | + <div class="mt-8"> | ||
| 92 | + <h3 class="font-semibold text-gray-800 mb-2">活动信息</h3> | ||
| 93 | + <div class="bg-gray-50 rounded-lg p-4 text-left"> | ||
| 94 | + <p class="font-medium text-gray-900">{{ activity.title }}</p> | ||
| 95 | + <p class="text-gray-600 text-sm mt-1"> | ||
| 96 | + 时间:{{ formatDate(activity.start_time) }} - {{ | ||
| 97 | + formatDate(activity.end_time) }} | ||
| 98 | + </p> | ||
| 99 | + <p class="text-gray-600 text-sm mt-1"> | ||
| 100 | + 地点:{{ activity.activity_type === 'online' ? '线上活动' : (activity.location | ||
| 101 | + ? (typeof activity.location === 'object' ? activity.location.name : | ||
| 102 | + activity.location) : '地点未设置') }} | ||
| 103 | + </p> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 106 | + | ||
| 107 | + <Button @click="goToActivityDetail" variant="primary" class="mt-6"> | ||
| 108 | + 返回活动详情 | ||
| 109 | + </Button> | ||
| 110 | + </div> | ||
| 111 | + </div> | ||
| 112 | + </div> | ||
| 113 | + </div> | ||
| 114 | + </div> | ||
| 115 | + | ||
| 116 | + <!-- Main Check-in Flow --> | ||
| 117 | + <div v-else class="py-8"> | ||
| 118 | + <div class="container mx-auto px-4"> | ||
| 119 | + <div class="max-w-md mx-auto bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 120 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 px-6 py-4"> | ||
| 121 | + <h1 class="text-2xl font-bold text-white">活动签到</h1> | ||
| 122 | + </div> | ||
| 123 | + | ||
| 124 | + <div class="p-6"> | ||
| 125 | + <!-- Activity Info --> | ||
| 126 | + <div class="mb-6"> | ||
| 127 | + <h2 class="text-xl font-medium text-gray-900 mb-2">{{ activity.title }}</h2> | ||
| 128 | + <p class="text-gray-600 text-sm"> | ||
| 129 | + 时间:{{ formatDate(activity.start_time) }} - {{ formatDate(activity.end_time) }} | ||
| 130 | + </p> | ||
| 131 | + <p class="text-gray-600 text-sm mt-1"> | ||
| 132 | + 地点:{{ activity.activity_type === 'online' ? '线上活动' : (activity.location ? (typeof | ||
| 133 | + activity.location === 'object' ? activity.location.name : activity.location) : '地点未设置') | ||
| 134 | + }} | ||
| 135 | + </p> | ||
| 136 | + | ||
| 137 | + <div v-if="userRegistration.status === 'approved'" | ||
| 138 | + class="bg-green-50 border border-green-200 rounded-md p-3 mt-4"> | ||
| 139 | + <div class="flex"> | ||
| 140 | + <svg class="h-5 w-5 text-green-500 mr-2" xmlns="http://www.w3.org/2000/svg" | ||
| 141 | + viewBox="0 0 20 20" fill="currentColor"> | ||
| 142 | + <path fill-rule="evenodd" | ||
| 143 | + d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" | ||
| 144 | + clip-rule="evenodd" /> | ||
| 145 | + </svg> | ||
| 146 | + <span class="text-green-800 font-medium">您的报名已通过审核</span> | ||
| 147 | + </div> | ||
| 148 | + </div> | ||
| 149 | + </div> | ||
| 150 | + | ||
| 151 | + <!-- Check-in Steps --> | ||
| 152 | + <div v-if="checkInStep === 'initial'" class="text-center"> | ||
| 153 | + <div class="inline-block bg-blue-100 rounded-full p-4 mb-6"> | ||
| 154 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-blue-600" fill="none" | ||
| 155 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 156 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 157 | + d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" /> | ||
| 158 | + </svg> | ||
| 159 | + </div> | ||
| 160 | + | ||
| 161 | + <h3 class="text-lg font-medium text-gray-900 mb-2">活动签到</h3> | ||
| 162 | + <p class="text-gray-600 mb-6"> | ||
| 163 | + 点击下方按钮生成签到码,请向工作人员出示 | ||
| 164 | + </p> | ||
| 165 | + | ||
| 166 | + <Button @click="generateCheckInCode" variant="primary" size="lg" block> | ||
| 167 | + 生成签到码 | ||
| 168 | + </Button> | ||
| 169 | + </div> | ||
| 170 | + | ||
| 171 | + <div v-else-if="checkInStep === 'code'" class="text-center"> | ||
| 172 | + <h3 class="text-lg font-medium text-gray-900 mb-2">您的签到码</h3> | ||
| 173 | + <p class="text-gray-600 mb-4">请向工作人员出示以下签到码</p> | ||
| 174 | + | ||
| 175 | + <div class="border-2 border-gray-300 rounded-lg p-4 mb-6"> | ||
| 176 | + <div class="mb-4"> | ||
| 177 | + <div class="w-48 h-48 mx-auto bg-gray-100 flex items-center justify-center"> | ||
| 178 | + <div class="text-center"> | ||
| 179 | + <div class="text-xl font-bold mb-2">签到码</div> | ||
| 180 | + <div class="text-3xl font-bold">{{ checkInCode }}</div> | ||
| 181 | + </div> | ||
| 182 | + </div> | ||
| 183 | + </div> | ||
| 184 | + | ||
| 185 | + <div class="flex justify-center"> | ||
| 186 | + <div | ||
| 187 | + class="text-3xl font-bold tracking-wide text-gray-800 py-2 px-4 border-2 border-gray-300 rounded-lg"> | ||
| 188 | + {{ checkInCode }} | ||
| 189 | + </div> | ||
| 190 | + </div> | ||
| 191 | + </div> | ||
| 192 | + | ||
| 193 | + <p class="text-sm text-gray-600"> | ||
| 194 | + {{ countdown > 0 ? `签到码有效期: ${countdown} 秒` : '签到码已过期,请重新生成' }} | ||
| 195 | + </p> | ||
| 196 | + | ||
| 197 | + <div class="mt-6 text-sm"> | ||
| 198 | + <p class="text-gray-700">或输入工作人员提供的活动码</p> | ||
| 199 | + <div class="flex mt-2"> | ||
| 200 | + <input type="text" v-model="inputCode" placeholder="请输入6位签到码" | ||
| 201 | + class="flex-1 block border-gray-300 rounded-l-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm" /> | ||
| 202 | + <Button @click="handleSubmitCode" variant="primary" class="rounded-l-none" | ||
| 203 | + :disabled="isSubmitting || !inputCode"> | ||
| 204 | + 验证 | ||
| 205 | + </Button> | ||
| 206 | + </div> | ||
| 207 | + </div> | ||
| 208 | + | ||
| 209 | + <Button @click="setCheckInStep('initial')" variant="secondary" size="md" class="mt-6"> | ||
| 210 | + 返回 | ||
| 211 | + </Button> | ||
| 212 | + </div> | ||
| 213 | + | ||
| 214 | + <div v-else-if="checkInStep === 'success'" class="text-center"> | ||
| 215 | + <div class="flex justify-center"> | ||
| 216 | + <div class="rounded-full bg-green-100 p-4"> | ||
| 217 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-green-500" fill="none" | ||
| 218 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 219 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 220 | + d="M5 13l4 4L19 7" /> | ||
| 221 | + </svg> | ||
| 222 | + </div> | ||
| 223 | + </div> | ||
| 224 | + | ||
| 225 | + <h2 class="text-2xl font-bold text-gray-800 mt-6">签到成功</h2> | ||
| 226 | + <p class="text-gray-600 mt-2">祝您阅读愉快!</p> | ||
| 227 | + | ||
| 228 | + <Button @click="goToActivityDetail" variant="primary" class="mt-8"> | ||
| 229 | + 返回活动详情 | ||
| 230 | + </Button> | ||
| 231 | + </div> | ||
| 232 | + | ||
| 233 | + <div v-else-if="checkInStep === 'error'" class="text-center"> | ||
| 234 | + <div class="flex justify-center"> | ||
| 235 | + <div class="rounded-full bg-red-100 p-4"> | ||
| 236 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-red-500" fill="none" | ||
| 237 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 238 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 239 | + d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 240 | + </svg> | ||
| 241 | + </div> | ||
| 242 | + </div> | ||
| 243 | + | ||
| 244 | + <h2 class="text-xl font-bold text-gray-800 mt-6">签到失败</h2> | ||
| 245 | + <p class="text-red-500 mt-2">{{ error }}</p> | ||
| 246 | + | ||
| 247 | + <Button @click="setCheckInStep('initial')" variant="primary" class="mt-6"> | ||
| 248 | + 重新签到 | ||
| 249 | + </Button> | ||
| 250 | + </div> | ||
| 251 | + </div> | ||
| 252 | + </div> | ||
| 253 | + </div> | ||
| 254 | + </div> | ||
| 255 | + </div> | ||
| 256 | +</template> | ||
| 257 | + | ||
| 258 | +<script setup> | ||
| 259 | +import { ref, onMounted, watch } from 'vue' | ||
| 260 | +import { useRoute, useRouter } from 'vue-router' | ||
| 261 | +import { useAppStore } from '../stores/app' | ||
| 262 | +import Button from '../components/shared/Button.vue' | ||
| 263 | + | ||
| 264 | +const route = useRoute() | ||
| 265 | +const router = useRouter() | ||
| 266 | +const appStore = useAppStore() | ||
| 267 | + | ||
| 268 | +const activityId = route.params.activityId | ||
| 269 | +const activity = ref(null) | ||
| 270 | +const loading = ref(true) | ||
| 271 | +const error = ref(null) | ||
| 272 | +const userRegistration = ref(null) | ||
| 273 | +const userCheckIn = ref(null) | ||
| 274 | +const checkInStep = ref('initial') | ||
| 275 | +const checkInCode = ref('') | ||
| 276 | +const countdown = ref(0) | ||
| 277 | +const inputCode = ref('') | ||
| 278 | +const isSubmitting = ref(false) | ||
| 279 | + | ||
| 280 | +// Fetch activity details and user registration | ||
| 281 | +const fetchData = async () => { | ||
| 282 | + try { | ||
| 283 | + if (!appStore.currentUser) { | ||
| 284 | + error.value = '请先登录' | ||
| 285 | + loading.value = false | ||
| 286 | + return | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + if (appStore.activities.length > 0) { | ||
| 290 | + const foundActivity = appStore.getActivityById(activityId) | ||
| 291 | + | ||
| 292 | + if (foundActivity) { | ||
| 293 | + activity.value = foundActivity | ||
| 294 | + | ||
| 295 | + // Find user registration for this activity | ||
| 296 | + const registration = appStore.registrations.find( | ||
| 297 | + reg => reg.activity_id === activityId && reg.user_id === appStore.currentUser.id | ||
| 298 | + ) | ||
| 299 | + | ||
| 300 | + if (registration) { | ||
| 301 | + userRegistration.value = registration | ||
| 302 | + | ||
| 303 | + // Check if user already checked in | ||
| 304 | + const checkIn = appStore.checkIns.find( | ||
| 305 | + check => check.activity_id === activityId && check.user_id === appStore.currentUser.id | ||
| 306 | + ) | ||
| 307 | + | ||
| 308 | + if (checkIn) { | ||
| 309 | + userCheckIn.value = checkIn | ||
| 310 | + } | ||
| 311 | + } else { | ||
| 312 | + error.value = '您尚未报名该活动' | ||
| 313 | + } | ||
| 314 | + } else { | ||
| 315 | + error.value = '未找到活动信息' | ||
| 316 | + } | ||
| 317 | + } | ||
| 318 | + loading.value = false | ||
| 319 | + } catch (err) { | ||
| 320 | + console.error('Failed to fetch data:', err) | ||
| 321 | + error.value = '加载数据失败' | ||
| 322 | + loading.value = false | ||
| 323 | + } | ||
| 324 | +} | ||
| 325 | + | ||
| 326 | +// Generate a random check-in code | ||
| 327 | +const generateCheckInCode = () => { | ||
| 328 | + checkInCode.value = Math.floor(100000 + Math.random() * 900000).toString() | ||
| 329 | + checkInStep.value = 'code' | ||
| 330 | + countdown.value = 60 | ||
| 331 | +} | ||
| 332 | + | ||
| 333 | +// Handle check-in code submission | ||
| 334 | +const handleSubmitCode = async () => { | ||
| 335 | + if (!inputCode.value.trim()) return | ||
| 336 | + | ||
| 337 | + isSubmitting.value = true | ||
| 338 | + | ||
| 339 | + try { | ||
| 340 | + if (inputCode.value === checkInCode.value) { | ||
| 341 | + const now = new Date().toISOString().replace('T', ' ').substring(0, 19) | ||
| 342 | + const checkInResult = await appStore.addCheckIn({ | ||
| 343 | + user_id: appStore.currentUser.id, | ||
| 344 | + activity_id: activityId, | ||
| 345 | + check_in_time: now, | ||
| 346 | + status: 'checked_in' | ||
| 347 | + }) | ||
| 348 | + | ||
| 349 | + if (checkInResult.success) { | ||
| 350 | + userCheckIn.value = { | ||
| 351 | + user_id: appStore.currentUser.id, | ||
| 352 | + activity_id: activityId, | ||
| 353 | + check_in_time: now, | ||
| 354 | + status: 'checked_in' | ||
| 355 | + } | ||
| 356 | + checkInStep.value = 'success' | ||
| 357 | + } else { | ||
| 358 | + error.value = '签到失败,请稍后重试' | ||
| 359 | + checkInStep.value = 'error' | ||
| 360 | + } | ||
| 361 | + } else { | ||
| 362 | + error.value = '签到码不正确,请重试' | ||
| 363 | + checkInStep.value = 'error' | ||
| 364 | + } | ||
| 365 | + } catch (err) { | ||
| 366 | + console.error('Check-in error:', err) | ||
| 367 | + error.value = '签到失败,请稍后重试' | ||
| 368 | + checkInStep.value = 'error' | ||
| 369 | + } finally { | ||
| 370 | + isSubmitting.value = false | ||
| 371 | + } | ||
| 372 | +} | ||
| 373 | + | ||
| 374 | +// Format date for display | ||
| 375 | +const formatDate = (dateString) => { | ||
| 376 | + if (!dateString) return '' | ||
| 377 | + const date = new Date(dateString.replace(' ', 'T')) | ||
| 378 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 379 | + year: 'numeric', | ||
| 380 | + month: 'long', | ||
| 381 | + day: 'numeric', | ||
| 382 | + hour: '2-digit', | ||
| 383 | + minute: '2-digit', | ||
| 384 | + hour12: false | ||
| 385 | + }).format(date) | ||
| 386 | +} | ||
| 387 | + | ||
| 388 | +// Check if the activity is happening now | ||
| 389 | +const isActivityNow = () => { | ||
| 390 | + if (!activity.value) return false | ||
| 391 | + | ||
| 392 | + const now = new Date() | ||
| 393 | + const startTime = new Date(activity.value.start_time.replace(' ', 'T')) | ||
| 394 | + const endTime = new Date(activity.value.end_time.replace(' ', 'T')) | ||
| 395 | + | ||
| 396 | + // Allow check-in from 30 minutes before start until end time | ||
| 397 | + const checkInStartTime = new Date(startTime.getTime() - 30 * 60 * 1000) | ||
| 398 | + | ||
| 399 | + return now >= checkInStartTime && now <= endTime | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +// Navigation | ||
| 403 | +const goBack = () => router.back() | ||
| 404 | +const goToActivityDetail = () => router.push(`/activity/${activityId}`) | ||
| 405 | + | ||
| 406 | +// Watch countdown | ||
| 407 | +watch(countdown, (newValue) => { | ||
| 408 | + if (newValue > 0 && checkInStep.value === 'code') { | ||
| 409 | + setTimeout(() => { | ||
| 410 | + countdown.value-- | ||
| 411 | + }, 1000) | ||
| 412 | + } else if (newValue === 0 && checkInStep.value === 'code') { | ||
| 413 | + checkInStep.value = 'initial' | ||
| 414 | + } | ||
| 415 | +}) | ||
| 416 | + | ||
| 417 | +// Initial data fetch | ||
| 418 | +onMounted(fetchData) | ||
| 419 | +</script> |
src/pages/CreateActivity.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50 py-8"> | ||
| 3 | + <div class="container mx-auto px-4"> | ||
| 4 | + <div class="max-w-4xl mx-auto bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 5 | + <!-- Header --> | ||
| 6 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 px-6 py-4"> | ||
| 7 | + <h1 class="text-2xl font-bold text-white">创建读书会活动</h1> | ||
| 8 | + </div> | ||
| 9 | + | ||
| 10 | + <!-- Form --> | ||
| 11 | + <form class="p-6" @submit.prevent="handlePreview"> | ||
| 12 | + <div class="space-y-8"> | ||
| 13 | + <!-- Basic Information Section --> | ||
| 14 | + <div> | ||
| 15 | + <h2 class="text-xl font-medium text-gray-900 border-b pb-2">基本信息</h2> | ||
| 16 | + <div class="mt-4 space-y-6"> | ||
| 17 | + <!-- Title --> | ||
| 18 | + <Input id="title" label="活动标题" name="title" v-model="formState.title" | ||
| 19 | + placeholder="例如:《百年孤独》读书分享会" :error="formErrors.title" required /> | ||
| 20 | + | ||
| 21 | + <!-- Description --> | ||
| 22 | + <div> | ||
| 23 | + <label for="description" class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 24 | + 活动描述 <span class="text-red-500">*</span> | ||
| 25 | + </label> | ||
| 26 | + <textarea id="description" name="description" rows="8" | ||
| 27 | + v-model="formState.description" :class="[ | ||
| 28 | + 'block w-full border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm', | ||
| 29 | + formErrors.description ? 'border-red-300' : '' | ||
| 30 | + ]" placeholder="请描述活动内容、流程安排、参与须知等信息..."></textarea> | ||
| 31 | + <p v-if="formErrors.description" class="mt-1 text-sm text-red-600">{{ | ||
| 32 | + formErrors.description }}</p> | ||
| 33 | + </div> | ||
| 34 | + | ||
| 35 | + <!-- Cover Image --> | ||
| 36 | + <div> | ||
| 37 | + <label for="cover_image" class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 38 | + 封面图片 | ||
| 39 | + </label> | ||
| 40 | + <div class="mt-1 flex items-center space-x-4"> | ||
| 41 | + <div class="w-48 h-32 bg-gray-100 rounded-md overflow-hidden"> | ||
| 42 | + <img :src="formState.cover_image" alt="活动封面预览" | ||
| 43 | + class="w-full h-full object-cover" /> | ||
| 44 | + </div> | ||
| 45 | + <Input id="cover_image" name="cover_image" v-model="formState.cover_image" | ||
| 46 | + placeholder="输入图片URL或上传图片" /> | ||
| 47 | + </div> | ||
| 48 | + <p class="mt-1 text-sm text-gray-500"> | ||
| 49 | + 建议尺寸:1200 x 675 像素,格式:JPG、PNG | ||
| 50 | + </p> | ||
| 51 | + </div> | ||
| 52 | + | ||
| 53 | + <!-- Tags --> | ||
| 54 | + <div> | ||
| 55 | + <label for="tagInput" class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 56 | + 活动标签 | ||
| 57 | + </label> | ||
| 58 | + <div class="flex flex-wrap items-center gap-2 mb-2"> | ||
| 59 | + <div v-for="(tag, index) in formState.tags" :key="index" | ||
| 60 | + class="bg-green-50 text-green-700 rounded-full px-3 py-1 text-sm flex items-center"> | ||
| 61 | + <span>{{ tag }}</span> | ||
| 62 | + <button type="button" @click="removeTag(tag)" | ||
| 63 | + class="ml-1 text-green-500 hover:text-green-700 focus:outline-none"> | ||
| 64 | + × | ||
| 65 | + </button> | ||
| 66 | + </div> | ||
| 67 | + <Input id="tagInput" name="tagInput" v-model="formState.tagInput" | ||
| 68 | + @keydown="handleTagKeyDown" placeholder="输入标签并按回车" class="flex-1" /> | ||
| 69 | + </div> | ||
| 70 | + <p class="text-sm text-gray-500"> | ||
| 71 | + 添加相关标签,使活动更容易被发现,如:小说、科普、心理学等 | ||
| 72 | + </p> | ||
| 73 | + </div> | ||
| 74 | + </div> | ||
| 75 | + </div> | ||
| 76 | + | ||
| 77 | + <!-- Time and Location Section --> | ||
| 78 | + <div> | ||
| 79 | + <h2 class="text-xl font-medium text-gray-900 border-b pb-2">时间与地点</h2> | ||
| 80 | + <div class="mt-4 space-y-6"> | ||
| 81 | + <!-- Activity Time --> | ||
| 82 | + <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | ||
| 83 | + <Input id="start_time" type="datetime-local" label="活动开始时间" name="start_time" | ||
| 84 | + v-model="formState.start_time" :error="formErrors.start_time" required /> | ||
| 85 | + | ||
| 86 | + <Input id="end_time" type="datetime-local" label="活动结束时间" name="end_time" | ||
| 87 | + v-model="formState.end_time" :error="formErrors.end_time" required /> | ||
| 88 | + </div> | ||
| 89 | + | ||
| 90 | + <!-- Registration Time --> | ||
| 91 | + <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | ||
| 92 | + <Input id="registration_start" type="datetime-local" label="报名开始时间" | ||
| 93 | + name="registration_start" v-model="formState.registration_start" | ||
| 94 | + :error="formErrors.registration_start" required /> | ||
| 95 | + | ||
| 96 | + <Input id="registration_end" type="datetime-local" label="报名结束时间" | ||
| 97 | + name="registration_end" v-model="formState.registration_end" | ||
| 98 | + :error="formErrors.registration_end" required /> | ||
| 99 | + </div> | ||
| 100 | + | ||
| 101 | + <!-- Activity Type --> | ||
| 102 | + <div> | ||
| 103 | + <label class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 104 | + 活动形式 <span class="text-red-500">*</span> | ||
| 105 | + </label> | ||
| 106 | + <div class="flex space-x-4"> | ||
| 107 | + <label class="inline-flex items-center"> | ||
| 108 | + <input type="radio" name="activity_type" value="offline" | ||
| 109 | + v-model="formState.activity_type" | ||
| 110 | + class="h-4 w-4 text-green-600 border-gray-300 focus:ring-green-500" /> | ||
| 111 | + <span class="ml-2">线下活动</span> | ||
| 112 | + </label> | ||
| 113 | + <label class="inline-flex items-center"> | ||
| 114 | + <input type="radio" name="activity_type" value="online" | ||
| 115 | + v-model="formState.activity_type" | ||
| 116 | + class="h-4 w-4 text-green-600 border-gray-300 focus:ring-green-500" /> | ||
| 117 | + <span class="ml-2">线上活动</span> | ||
| 118 | + </label> | ||
| 119 | + </div> | ||
| 120 | + </div> | ||
| 121 | + | ||
| 122 | + <!-- Location or Online Link --> | ||
| 123 | + <Input v-if="formState.activity_type === 'offline'" id="location" label="活动地点" | ||
| 124 | + name="location" v-model="formState.location" placeholder="例如:北京市海淀区中关村图书馆三层读书区" | ||
| 125 | + :error="formErrors.location" required /> | ||
| 126 | + <Input v-else id="online_link" label="线上会议信息" name="online_link" | ||
| 127 | + v-model="formState.online_link" placeholder="例如:Zoom会议ID或飞书会议链接" | ||
| 128 | + :error="formErrors.online_link" required /> | ||
| 129 | + </div> | ||
| 130 | + </div> | ||
| 131 | + | ||
| 132 | + <!-- Settings Section --> | ||
| 133 | + <div> | ||
| 134 | + <h2 class="text-xl font-medium text-gray-900 border-b pb-2">活动设置</h2> | ||
| 135 | + <div class="mt-4 space-y-6"> | ||
| 136 | + <!-- Maximum Participants --> | ||
| 137 | + <div class="max-w-xs"> | ||
| 138 | + <Input id="max_participants" type="number" label="最大参与人数" name="max_participants" | ||
| 139 | + v-model="formState.max_participants" min="1" max="500" | ||
| 140 | + :error="formErrors.max_participants" /> | ||
| 141 | + </div> | ||
| 142 | + | ||
| 143 | + <!-- Visibility --> | ||
| 144 | + <div> | ||
| 145 | + <label class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 146 | + 活动可见性 | ||
| 147 | + </label> | ||
| 148 | + <label class="inline-flex items-center"> | ||
| 149 | + <input type="checkbox" name="is_public" v-model="formState.is_public" | ||
| 150 | + class="h-4 w-4 text-green-600 border-gray-300 rounded focus:ring-green-500" /> | ||
| 151 | + <span class="ml-2">公开活动(所有人可见)</span> | ||
| 152 | + </label> | ||
| 153 | + <p class="mt-1 text-sm text-gray-500"> | ||
| 154 | + {{ formState.is_public ? '活动将在首页和搜索结果中显示' : '活动仅对邀请的用户可见' }} | ||
| 155 | + </p> | ||
| 156 | + </div> | ||
| 157 | + </div> | ||
| 158 | + </div> | ||
| 159 | + | ||
| 160 | + <!-- Submit Buttons --> | ||
| 161 | + <div class="flex justify-end space-x-4 pt-6"> | ||
| 162 | + <Button type="button" variant="secondary" @click="goBack"> | ||
| 163 | + 取消 | ||
| 164 | + </Button> | ||
| 165 | + <Button type="submit" variant="primary" :disabled="isLoading"> | ||
| 166 | + 预览活动 | ||
| 167 | + </Button> | ||
| 168 | + </div> | ||
| 169 | + </div> | ||
| 170 | + </form> | ||
| 171 | + </div> | ||
| 172 | + </div> | ||
| 173 | + | ||
| 174 | + <!-- Preview Modal --> | ||
| 175 | + <Modal v-model:isOpen="showPreviewModal" title="活动预览" size="lg"> | ||
| 176 | + <template #default> | ||
| 177 | + <div class="py-4"> | ||
| 178 | + <div class="space-y-6"> | ||
| 179 | + <!-- Preview Cover --> | ||
| 180 | + <div class="relative h-48 rounded-lg overflow-hidden bg-gray-200"> | ||
| 181 | + <img :src="formState.cover_image" :alt="formState.title" | ||
| 182 | + class="w-full h-full object-cover" /> | ||
| 183 | + </div> | ||
| 184 | + | ||
| 185 | + <!-- Preview Title --> | ||
| 186 | + <h2 class="text-2xl font-bold text-gray-900">{{ formState.title }}</h2> | ||
| 187 | + | ||
| 188 | + <!-- Preview Tags --> | ||
| 189 | + <div v-if="formState.tags.length > 0" class="flex flex-wrap gap-2"> | ||
| 190 | + <span v-for="(tag, index) in formState.tags" :key="index" | ||
| 191 | + class="bg-green-50 text-green-700 rounded-full px-3 py-1 text-sm"> | ||
| 192 | + {{ tag }} | ||
| 193 | + </span> | ||
| 194 | + </div> | ||
| 195 | + | ||
| 196 | + <!-- Preview Description --> | ||
| 197 | + <div class="prose max-w-none text-gray-700"> | ||
| 198 | + <p v-for="(paragraph, idx) in formState.description.split('\n')" :key="idx" class="mb-2"> | ||
| 199 | + {{ paragraph }} | ||
| 200 | + </p> | ||
| 201 | + </div> | ||
| 202 | + </div> | ||
| 203 | + </div> | ||
| 204 | + </template> | ||
| 205 | + <template #footer> | ||
| 206 | + <Button @click="showPreviewModal = false" variant="secondary" class="mr-3"> | ||
| 207 | + 返回编辑 | ||
| 208 | + </Button> | ||
| 209 | + <Button @click="handleSubmit" variant="primary" :disabled="isLoading"> | ||
| 210 | + {{ isLoading ? '创建中...' : '创建活动' }} | ||
| 211 | + </Button> | ||
| 212 | + </template> | ||
| 213 | + </Modal> | ||
| 214 | + </div> | ||
| 215 | +</template> | ||
| 216 | + | ||
| 217 | +<script setup> | ||
| 218 | +import { ref, reactive, onMounted } from 'vue' | ||
| 219 | +import { useRouter } from 'vue-router' | ||
| 220 | +import { useAppStore } from '../stores/app' | ||
| 221 | +import Button from '../components/shared/Button.vue' | ||
| 222 | +import Input from '../components/shared/Input.vue' | ||
| 223 | +import Modal from '../components/shared/Modal.vue' | ||
| 224 | + | ||
| 225 | +const router = useRouter() | ||
| 226 | +const appStore = useAppStore() | ||
| 227 | +const { currentUser } = appStore | ||
| 228 | + | ||
| 229 | +const isLoading = ref(false) | ||
| 230 | +const showPreviewModal = ref(false) | ||
| 231 | +const formErrors = reactive({}) | ||
| 232 | + | ||
| 233 | +// Form state | ||
| 234 | +const formState = reactive({ | ||
| 235 | + title: '', | ||
| 236 | + description: '', | ||
| 237 | + cover_image: '/assets/images/LEVRaos2Ero.jpg', | ||
| 238 | + start_time: '', | ||
| 239 | + end_time: '', | ||
| 240 | + registration_start: '', | ||
| 241 | + registration_end: '', | ||
| 242 | + activity_type: 'offline', // 'online' or 'offline' | ||
| 243 | + location: '', | ||
| 244 | + online_link: '', | ||
| 245 | + max_participants: 20, | ||
| 246 | + is_public: true, | ||
| 247 | + tags: [], | ||
| 248 | + tagInput: '' // For managing tag input | ||
| 249 | +}) | ||
| 250 | + | ||
| 251 | +// Check if user is logged in | ||
| 252 | +onMounted(() => { | ||
| 253 | + if (!currentUser) { | ||
| 254 | + // In a real app, redirect to login | ||
| 255 | + alert('请先登录再创建活动') | ||
| 256 | + router.push('/') | ||
| 257 | + } | ||
| 258 | +}) | ||
| 259 | + | ||
| 260 | +// Handle tag input | ||
| 261 | +const handleTagKeyDown = (e) => { | ||
| 262 | + if (e.key === 'Enter') { | ||
| 263 | + e.preventDefault() | ||
| 264 | + addTag() | ||
| 265 | + } | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +// Add tag to the list | ||
| 269 | +const addTag = () => { | ||
| 270 | + const tag = formState.tagInput.trim() | ||
| 271 | + if (tag && !formState.tags.includes(tag)) { | ||
| 272 | + formState.tags.push(tag) | ||
| 273 | + formState.tagInput = '' | ||
| 274 | + } | ||
| 275 | +} | ||
| 276 | + | ||
| 277 | +// Remove tag from the list | ||
| 278 | +const removeTag = (tagToRemove) => { | ||
| 279 | + formState.tags = formState.tags.filter(tag => tag !== tagToRemove) | ||
| 280 | +} | ||
| 281 | + | ||
| 282 | +// Validate form before submission | ||
| 283 | +const validateForm = () => { | ||
| 284 | + const errors = {} | ||
| 285 | + | ||
| 286 | + if (!formState.title.trim()) { | ||
| 287 | + errors.title = '请输入活动标题' | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + if (!formState.description.trim()) { | ||
| 291 | + errors.description = '请输入活动描述' | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + if (!formState.start_time) { | ||
| 295 | + errors.start_time = '请选择活动开始时间' | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + if (!formState.end_time) { | ||
| 299 | + errors.end_time = '请选择活动结束时间' | ||
| 300 | + } else if (new Date(formState.end_time) <= new Date(formState.start_time)) { | ||
| 301 | + errors.end_time = '结束时间必须晚于开始时间' | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + if (!formState.registration_start) { | ||
| 305 | + errors.registration_start = '请选择报名开始时间' | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + if (!formState.registration_end) { | ||
| 309 | + errors.registration_end = '请选择报名结束时间' | ||
| 310 | + } else if (new Date(formState.registration_end) <= new Date(formState.registration_start)) { | ||
| 311 | + errors.registration_end = '报名结束时间必须晚于开始时间' | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + if (formState.activity_type === 'offline' && !formState.location.trim()) { | ||
| 315 | + errors.location = '请输入活动地点' | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + if (formState.activity_type === 'online' && !formState.online_link.trim()) { | ||
| 319 | + errors.online_link = '请输入线上会议链接' | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + if (formState.max_participants <= 0) { | ||
| 323 | + errors.max_participants = '参与人数必须大于0' | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + Object.assign(formErrors, errors) | ||
| 327 | + return Object.keys(errors).length === 0 | ||
| 328 | +} | ||
| 329 | + | ||
| 330 | +// Preview activity before submission | ||
| 331 | +const handlePreview = (e) => { | ||
| 332 | + e.preventDefault() | ||
| 333 | + if (validateForm()) { | ||
| 334 | + showPreviewModal.value = true | ||
| 335 | + } else { | ||
| 336 | + // Scroll to the first error | ||
| 337 | + const firstErrorField = Object.keys(formErrors)[0] | ||
| 338 | + const element = document.getElementById(firstErrorField) | ||
| 339 | + if (element) { | ||
| 340 | + element.scrollIntoView({ behavior: 'smooth', block: 'center' }) | ||
| 341 | + } | ||
| 342 | + } | ||
| 343 | +} | ||
| 344 | + | ||
| 345 | +// Submit form to create activity | ||
| 346 | +const handleSubmit = async () => { | ||
| 347 | + if (validateForm()) { | ||
| 348 | + isLoading.value = true | ||
| 349 | + try { | ||
| 350 | + // Create form data for submission | ||
| 351 | + const activityData = { ...formState } | ||
| 352 | + delete activityData.tagInput | ||
| 353 | + activityData.participant_count = 0 | ||
| 354 | + activityData.is_published = true | ||
| 355 | + | ||
| 356 | + const result = await appStore.createActivity(activityData) | ||
| 357 | + | ||
| 358 | + if (result.success) { | ||
| 359 | + alert('活动创建成功!') | ||
| 360 | + router.push(`/activity/${result.activityId}`) | ||
| 361 | + } else { | ||
| 362 | + alert(`创建失败: ${result.error || '未知错误'}`) | ||
| 363 | + isLoading.value = false | ||
| 364 | + } | ||
| 365 | + } catch (error) { | ||
| 366 | + console.error('Failed to create activity:', error) | ||
| 367 | + alert('创建活动失败,请稍后再试') | ||
| 368 | + isLoading.value = false | ||
| 369 | + } | ||
| 370 | + } | ||
| 371 | +} | ||
| 372 | + | ||
| 373 | +// Format datetime for preview | ||
| 374 | +const formatDatetime = (datetimeStr) => { | ||
| 375 | + if (!datetimeStr) return '' | ||
| 376 | + const date = new Date(datetimeStr) | ||
| 377 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 378 | + year: 'numeric', | ||
| 379 | + month: 'long', | ||
| 380 | + day: 'numeric', | ||
| 381 | + hour: '2-digit', | ||
| 382 | + minute: '2-digit', | ||
| 383 | + hour12: false | ||
| 384 | + }).format(date) | ||
| 385 | +} | ||
| 386 | + | ||
| 387 | +// Navigation | ||
| 388 | +const goBack = () => { | ||
| 389 | + router.back() | ||
| 390 | +} | ||
| 391 | +</script> |
src/pages/HomePage.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen"> | ||
| 3 | + <!-- 加载状态 --> | ||
| 4 | + <div v-if="loading" class="min-h-screen flex justify-center items-center"> | ||
| 5 | + <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-green-500"></div> | ||
| 6 | + </div> | ||
| 7 | + | ||
| 8 | + <template v-else> | ||
| 9 | + <!-- Hero Section --> | ||
| 10 | + <section class="relative bg-gradient-to-br from-green-50 to-blue-50 py-16"> | ||
| 11 | + <div class="container mx-auto px-4"> | ||
| 12 | + <div class="max-w-3xl mx-auto text-center"> | ||
| 13 | + <h1 class="text-4xl md:text-5xl font-bold mb-6 text-gray-800"> | ||
| 14 | + 连接爱读书的人,<span | ||
| 15 | + class="bg-gradient-to-r from-green-500 to-blue-400 bg-clip-text text-transparent">共享知识的力量</span> | ||
| 16 | + </h1> | ||
| 17 | + <p class="text-xl text-gray-600 mb-8"> | ||
| 18 | + 发现丰富的读书活动,结识志同道合的朋友,让阅读成为一种享受 | ||
| 19 | + </p> | ||
| 20 | + | ||
| 21 | + <!-- 搜索表单 --> | ||
| 22 | + <form @submit.prevent="handleSearch" class="relative max-w-xl mx-auto mb-8"> | ||
| 23 | + <div class="flex rounded-full overflow-hidden shadow-lg"> | ||
| 24 | + <input type="text" v-model="searchTerm" class="flex-grow px-6 py-4 focus:outline-none" | ||
| 25 | + placeholder="搜索读书会活动、主题或城市..." /> | ||
| 26 | + <button type="submit" | ||
| 27 | + class="px-8 py-4 bg-green-500 text-white font-semibold hover:bg-green-600 transition duration-200"> | ||
| 28 | + 搜索 | ||
| 29 | + </button> | ||
| 30 | + </div> | ||
| 31 | + </form> | ||
| 32 | + </div> | ||
| 33 | + </div> | ||
| 34 | + </section> | ||
| 35 | + | ||
| 36 | + <!-- 搜索结果 --> | ||
| 37 | + <section v-if="isSearching" class="container mx-auto px-4 py-12"> | ||
| 38 | + <div class="flex justify-between items-center mb-8"> | ||
| 39 | + <h2 class="text-2xl font-bold text-gray-800">搜索结果</h2> | ||
| 40 | + <button @click="clearSearch" class="text-gray-600 hover:text-gray-800 transition duration-200"> | ||
| 41 | + 清除搜索 | ||
| 42 | + </button> | ||
| 43 | + </div> | ||
| 44 | + <div v-if="searchResults.length > 0" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | ||
| 45 | + <ActivityCard v-for="activity in searchResults" :key="activity.id" :activity="activity" /> | ||
| 46 | + </div> | ||
| 47 | + <div v-else class="text-center py-12 text-gray-600"> | ||
| 48 | + 未找到相关活动 | ||
| 49 | + </div> | ||
| 50 | + </section> | ||
| 51 | + | ||
| 52 | + <!-- 活动列表 --> | ||
| 53 | + <template v-else> | ||
| 54 | + <!-- 进行中的活动 --> | ||
| 55 | + <section v-if="ongoingActivities.length > 0" class="container mx-auto px-4 py-12"> | ||
| 56 | + <h2 class="text-2xl font-bold text-gray-800 mb-8">正在进行的活动</h2> | ||
| 57 | + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | ||
| 58 | + <ActivityCard v-for="activity in ongoingActivities" :key="activity.id" :activity="activity" /> | ||
| 59 | + </div> | ||
| 60 | + </section> | ||
| 61 | + | ||
| 62 | + <!-- 即将开始的活动 --> | ||
| 63 | + <section class="container mx-auto px-4 py-12"> | ||
| 64 | + <div class="flex justify-between items-center mb-8"> | ||
| 65 | + <h2 class="text-2xl font-bold text-gray-800">即将开始的活动</h2> | ||
| 66 | + <router-link to="/create-activity" | ||
| 67 | + class="px-6 py-2 bg-green-500 text-white rounded-full font-semibold hover:bg-green-600 transition duration-200"> | ||
| 68 | + 创建活动 | ||
| 69 | + </router-link> | ||
| 70 | + </div> | ||
| 71 | + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | ||
| 72 | + <ActivityCard v-for="activity in upcomingActivities" :key="activity.id" :activity="activity" /> | ||
| 73 | + </div> | ||
| 74 | + </section> | ||
| 75 | + | ||
| 76 | + <!-- 往期活动 --> | ||
| 77 | + <section class="container mx-auto px-4 py-12"> | ||
| 78 | + <h2 class="text-2xl font-bold text-gray-800 mb-8">往期活动</h2> | ||
| 79 | + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | ||
| 80 | + <ActivityCard v-for="activity in pastActivities" :key="activity.id" :activity="activity" /> | ||
| 81 | + </div> | ||
| 82 | + </section> | ||
| 83 | + </template> | ||
| 84 | + </template> | ||
| 85 | + </div> | ||
| 86 | +</template> | ||
| 87 | + | ||
| 88 | +<script setup> | ||
| 89 | +import { ref, computed, watchEffect } from 'vue' | ||
| 90 | +import { useAppStore } from '../stores/app' | ||
| 91 | +import ActivityCard from '../components/shared/ActivityCard.vue' | ||
| 92 | + | ||
| 93 | +const store = useAppStore() | ||
| 94 | +const { activities, loading } = store | ||
| 95 | + | ||
| 96 | +const upcomingActivities = ref([]) | ||
| 97 | +const ongoingActivities = ref([]) | ||
| 98 | +const pastActivities = ref([]) | ||
| 99 | +const searchTerm = ref('') | ||
| 100 | +const searchResults = ref([]) | ||
| 101 | +const isSearching = ref(false) | ||
| 102 | + | ||
| 103 | +// 监听活动数据变化并分类 | ||
| 104 | +watchEffect(() => { | ||
| 105 | + if (activities.value.length > 0) { | ||
| 106 | + const now = new Date() | ||
| 107 | + | ||
| 108 | + // 筛选即将开始的活动 | ||
| 109 | + upcomingActivities.value = activities.value | ||
| 110 | + .filter(activity => { | ||
| 111 | + const startTime = new Date(activity.start_time.replace(' ', 'T')) | ||
| 112 | + return startTime > now | ||
| 113 | + }) | ||
| 114 | + .sort((a, b) => { | ||
| 115 | + return new Date(a.start_time.replace(' ', 'T')) - new Date(b.start_time.replace(' ', 'T')) | ||
| 116 | + }) | ||
| 117 | + .slice(0, 6) | ||
| 118 | + | ||
| 119 | + // 筛选进行中的活动 | ||
| 120 | + ongoingActivities.value = activities.value | ||
| 121 | + .filter(activity => { | ||
| 122 | + const startTime = new Date(activity.start_time.replace(' ', 'T')) | ||
| 123 | + const endTime = new Date(activity.end_time.replace(' ', 'T')) | ||
| 124 | + return startTime <= now && endTime >= now | ||
| 125 | + }) | ||
| 126 | + | ||
| 127 | + // 筛选往期活动 | ||
| 128 | + pastActivities.value = activities.value | ||
| 129 | + .filter(activity => { | ||
| 130 | + const endTime = new Date(activity.end_time.replace(' ', 'T')) | ||
| 131 | + return endTime < now | ||
| 132 | + }) | ||
| 133 | + .sort((a, b) => { | ||
| 134 | + return new Date(b.end_time.replace(' ', 'T')) - new Date(a.end_time.replace(' ', 'T')) | ||
| 135 | + }) | ||
| 136 | + .slice(0, 6) | ||
| 137 | + } | ||
| 138 | +}) | ||
| 139 | + | ||
| 140 | +// 搜索处理 | ||
| 141 | +const handleSearch = () => { | ||
| 142 | + if (!searchTerm.value.trim()) return | ||
| 143 | + | ||
| 144 | + isSearching.value = true | ||
| 145 | + searchResults.value = activities.value.filter(activity => | ||
| 146 | + activity.title.toLowerCase().includes(searchTerm.value.toLowerCase()) || | ||
| 147 | + activity.description.toLowerCase().includes(searchTerm.value.toLowerCase()) || | ||
| 148 | + (activity.tags && activity.tags.some(tag => tag.toLowerCase().includes(searchTerm.value.toLowerCase()))) | ||
| 149 | + ) | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +// 清除搜索 | ||
| 153 | +const clearSearch = () => { | ||
| 154 | + searchTerm.value = '' | ||
| 155 | + isSearching.value = false | ||
| 156 | +} | ||
| 157 | +</script> |
src/pages/Messages.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50"> | ||
| 3 | + <!-- Header --> | ||
| 4 | + <div class="bg-white shadow-sm sticky top-0 z-10"> | ||
| 5 | + <div class="container mx-auto px-4 py-3"> | ||
| 6 | + <div class="flex items-center justify-between"> | ||
| 7 | + <div class="flex items-center"> | ||
| 8 | + <button @click="goBack" class="mr-3 text-gray-600 hover:text-gray-900"> | ||
| 9 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" | ||
| 10 | + fill="currentColor"> | ||
| 11 | + <path fill-rule="evenodd" | ||
| 12 | + d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" | ||
| 13 | + clip-rule="evenodd" /> | ||
| 14 | + </svg> | ||
| 15 | + </button> | ||
| 16 | + <div> | ||
| 17 | + <h1 class="text-lg font-medium text-gray-900 truncate max-w-xs">{{ activity?.title }}</h1> | ||
| 18 | + <p class="text-sm text-gray-500">消息交流</p> | ||
| 19 | + </div> | ||
| 20 | + </div> | ||
| 21 | + <router-link :to="`/activity/${activityId}`" | ||
| 22 | + class="text-sm text-green-600 hover:text-green-700 font-medium"> | ||
| 23 | + 活动详情 | ||
| 24 | + </router-link> | ||
| 25 | + </div> | ||
| 26 | + </div> | ||
| 27 | + </div> | ||
| 28 | + | ||
| 29 | + <!-- Message Tabs --> | ||
| 30 | + <div class="bg-white shadow-sm"> | ||
| 31 | + <div class="container mx-auto px-4"> | ||
| 32 | + <div class="flex overflow-x-auto hide-scrollbar"> | ||
| 33 | + <button v-for="tab in tabs" :key="tab.value" :class="[ | ||
| 34 | + 'py-3 px-4 text-sm font-medium border-b-2 whitespace-nowrap', | ||
| 35 | + activeTab === tab.value | ||
| 36 | + ? 'border-green-500 text-green-600' | ||
| 37 | + : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' | ||
| 38 | + ]" @click="activeTab = tab.value"> | ||
| 39 | + {{ tab.label }} | ||
| 40 | + </button> | ||
| 41 | + </div> | ||
| 42 | + </div> | ||
| 43 | + </div> | ||
| 44 | + | ||
| 45 | + <!-- Messages Container --> | ||
| 46 | + <div class="container mx-auto px-4 py-4 flex flex-col h-[calc(100vh-13rem)]"> | ||
| 47 | + <!-- Message List --> | ||
| 48 | + <div class="flex-grow overflow-y-auto mb-4 pr-1"> | ||
| 49 | + <div v-if="filteredMessages.length === 0" class="flex flex-col items-center justify-center h-full"> | ||
| 50 | + <div class="text-gray-400"> | ||
| 51 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16" fill="none" viewBox="0 0 24 24" | ||
| 52 | + stroke="currentColor"> | ||
| 53 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" | ||
| 54 | + d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /> | ||
| 55 | + </svg> | ||
| 56 | + </div> | ||
| 57 | + <p class="text-gray-500 mt-2">暂无消息</p> | ||
| 58 | + <button v-if="activeTab !== 'all'" @click="activeTab = 'all'" | ||
| 59 | + class="mt-4 text-green-600 hover:text-green-700 font-medium text-sm"> | ||
| 60 | + 查看全部消息 | ||
| 61 | + </button> | ||
| 62 | + </div> | ||
| 63 | + <div v-else> | ||
| 64 | + <div v-for="date in sortedDates" :key="date"> | ||
| 65 | + <div class="flex items-center justify-center my-4"> | ||
| 66 | + <div class="border-t border-gray-200 flex-grow"></div> | ||
| 67 | + <span class="mx-4 text-xs text-gray-500">{{ formatDate(date) }}</span> | ||
| 68 | + <div class="border-t border-gray-200 flex-grow"></div> | ||
| 69 | + </div> | ||
| 70 | + <div v-for="message in groupedMessages[date]" :key="message.id"> | ||
| 71 | + <component :is="messageComponent(message)" :message="message" /> | ||
| 72 | + </div> | ||
| 73 | + </div> | ||
| 74 | + <div ref="messageEndRef" /> | ||
| 75 | + </div> | ||
| 76 | + </div> | ||
| 77 | + | ||
| 78 | + <!-- Message Input --> | ||
| 79 | + <div class="bg-white border border-gray-200 rounded-lg overflow-hidden"> | ||
| 80 | + <div v-if="isOrganizer" class="p-2 bg-gray-50 border-b border-gray-200"> | ||
| 81 | + <div class="flex items-center"> | ||
| 82 | + <span | ||
| 83 | + class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800"> | ||
| 84 | + 组织者 | ||
| 85 | + </span> | ||
| 86 | + <span class="text-xs text-gray-500 ml-2"> | ||
| 87 | + 您可以发送公告消息 | ||
| 88 | + </span> | ||
| 89 | + </div> | ||
| 90 | + </div> | ||
| 91 | + <form @submit.prevent="handleSendMessage" class="flex p-2"> | ||
| 92 | + <input type="text" v-model="messageInput" placeholder="输入消息..." | ||
| 93 | + class="flex-grow border-none focus:ring-0 focus:outline-none" :disabled="isSubmitting" /> | ||
| 94 | + <Button type="submit" variant="primary" size="sm" :disabled="!messageInput.trim() || isSubmitting"> | ||
| 95 | + 发送 | ||
| 96 | + </Button> | ||
| 97 | + </form> | ||
| 98 | + </div> | ||
| 99 | + </div> | ||
| 100 | + </div> | ||
| 101 | +</template> | ||
| 102 | + | ||
| 103 | +<script setup> | ||
| 104 | +import { ref, computed, onMounted, watch } from 'vue' | ||
| 105 | +import { useRoute, useRouter } from 'vue-router' | ||
| 106 | +import { useAppStore } from '../stores/app' | ||
| 107 | +import Button from '../components/shared/Button.vue' | ||
| 108 | + | ||
| 109 | +// Route and store setup | ||
| 110 | +const route = useRoute() | ||
| 111 | +const router = useRouter() | ||
| 112 | +const store = useAppStore() | ||
| 113 | + | ||
| 114 | +// Props and refs | ||
| 115 | +const activityId = route.params.activityId | ||
| 116 | +const messageEndRef = ref(null) | ||
| 117 | +const messageInput = ref('') | ||
| 118 | +const activeTab = ref('all') | ||
| 119 | +const isSubmitting = ref(false) | ||
| 120 | +const activity = ref(null) | ||
| 121 | +const filteredMessages = ref([]) | ||
| 122 | +const loading = ref(true) | ||
| 123 | +const error = ref(null) | ||
| 124 | + | ||
| 125 | +// Computed properties | ||
| 126 | +const isOrganizer = computed(() => { | ||
| 127 | + return store.currentUser && store.currentUser.id === activity.value?.organizer_id | ||
| 128 | +}) | ||
| 129 | + | ||
| 130 | +// Tabs configuration | ||
| 131 | +const tabs = [ | ||
| 132 | + { label: '全部消息', value: 'all' }, | ||
| 133 | + { label: '活动公告', value: 'announcements' }, | ||
| 134 | + { label: '问答交流', value: 'questions' }, | ||
| 135 | + { label: '我的消息', value: 'personal' } | ||
| 136 | +] | ||
| 137 | + | ||
| 138 | +// Methods | ||
| 139 | +const goBack = () => router.back() | ||
| 140 | + | ||
| 141 | +const formatTime = (dateString) => { | ||
| 142 | + const date = new Date(dateString.replace(' ', 'T')) | ||
| 143 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 144 | + month: 'short', | ||
| 145 | + day: 'numeric', | ||
| 146 | + hour: '2-digit', | ||
| 147 | + minute: '2-digit', | ||
| 148 | + hour12: false | ||
| 149 | + }).format(date) | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +const formatDate = (dateString) => { | ||
| 153 | + return new Date(dateString).toLocaleDateString('zh-CN') | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +const handleSendMessage = async () => { | ||
| 157 | + if (!messageInput.value.trim()) return | ||
| 158 | + | ||
| 159 | + if (!store.currentUser) { | ||
| 160 | + alert('请先登录再发送消息') | ||
| 161 | + return | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + isSubmitting.value = true | ||
| 165 | + | ||
| 166 | + try { | ||
| 167 | + const now = new Date().toISOString().replace('T', ' ').substring(0, 19) | ||
| 168 | + | ||
| 169 | + const newMessage = { | ||
| 170 | + activity_id: activityId, | ||
| 171 | + user_id: store.currentUser.id, | ||
| 172 | + type: 'question', | ||
| 173 | + content: messageInput.value, | ||
| 174 | + timestamp: now, | ||
| 175 | + user_name: store.currentUser.name, | ||
| 176 | + user_avatar: store.currentUser.avatar | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + const result = await store.addMessage(newMessage) | ||
| 180 | + | ||
| 181 | + if (result.success) { | ||
| 182 | + messageInput.value = '' | ||
| 183 | + } else { | ||
| 184 | + alert(`发送失败: ${result.error}`) | ||
| 185 | + } | ||
| 186 | + } catch (error) { | ||
| 187 | + console.error('Failed to send message:', error) | ||
| 188 | + alert('发送消息失败,请稍后重试') | ||
| 189 | + } finally { | ||
| 190 | + isSubmitting.value = false | ||
| 191 | + } | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +// Message components | ||
| 195 | +const AnnouncementMessage = { | ||
| 196 | + props: ['message'], | ||
| 197 | + template: ` | ||
| 198 | + <div class="bg-blue-50 border border-blue-100 rounded-lg p-4 mb-4"> | ||
| 199 | + <div class="flex items-center mb-2"> | ||
| 200 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-blue-500 mr-2" viewBox="0 0 20 20" fill="currentColor"> | ||
| 201 | + <path fill-rule="evenodd" d="M18 3a1 1 0 00-1.447-.894L8.763 6H5a3 3 0 000 6h.28l1.771 5.316A1 1 0 008 18h1a1 1 0 001-1v-4.382l6.553 3.276A1 1 0 0018 15V3z" clip-rule="evenodd" /> | ||
| 202 | + </svg> | ||
| 203 | + <span class="font-semibold text-blue-800">活动公告</span> | ||
| 204 | + </div> | ||
| 205 | + <p class="text-gray-700">{{ message.content }}</p> | ||
| 206 | + <div class="mt-2 text-xs text-gray-500 flex items-center justify-between"> | ||
| 207 | + <span>{{ message.user_name }}</span> | ||
| 208 | + <span>{{ formatTime(message.timestamp) }}</span> | ||
| 209 | + </div> | ||
| 210 | + </div> | ||
| 211 | + ` | ||
| 212 | +} | ||
| 213 | + | ||
| 214 | +const AnswerMessage = { | ||
| 215 | + props: ['message'], | ||
| 216 | + template: ` | ||
| 217 | + <div class="bg-green-50 border border-green-100 rounded-lg p-4 mb-4"> | ||
| 218 | + <div class="flex items-center mb-2"> | ||
| 219 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" viewBox="0 0 20 20" fill="currentColor"> | ||
| 220 | + <path fill-rule="evenodd" d="M18 13V5a2 2 0 00-2-2H4a2 2 0 00-2 2v8a2 2 0 002 2h3l3 3 3-3h3a2 2 0 002-2zM5 7a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1zm1 3a1 1 0 100 2h3a1 1 0 100-2H6z" clip-rule="evenodd" /> | ||
| 221 | + </svg> | ||
| 222 | + <span class="font-semibold text-green-800">回复</span> | ||
| 223 | + </div> | ||
| 224 | + <div v-if="message.reply_to" class="bg-white rounded p-2 mb-2 text-sm text-gray-600 border-l-2 border-gray-300"> | ||
| 225 | + <p class="truncate">{{ message.reply_to }}</p> | ||
| 226 | + </div> | ||
| 227 | + <p class="text-gray-700">{{ message.content }}</p> | ||
| 228 | + <div class="mt-2 text-xs text-gray-500 flex items-center justify-between"> | ||
| 229 | + <span>{{ message.user_name }}</span> | ||
| 230 | + <span>{{ formatTime(message.timestamp) }}</span> | ||
| 231 | + </div> | ||
| 232 | + </div> | ||
| 233 | + ` | ||
| 234 | +} | ||
| 235 | + | ||
| 236 | +const DefaultMessage = { | ||
| 237 | + props: ['message'], | ||
| 238 | + setup(props) { | ||
| 239 | + const store = useAppStore() | ||
| 240 | + const isCurrentUser = computed(() => props.message.user_id === store.currentUser?.id) | ||
| 241 | + return { isCurrentUser, formatTime } | ||
| 242 | + }, | ||
| 243 | + template: ` | ||
| 244 | + <div :class="['flex', isCurrentUser ? 'justify-end' : 'justify-start', 'mb-4']"> | ||
| 245 | + <div :class="['max-w-[80%]', isCurrentUser ? 'order-1' : 'order-2']"> | ||
| 246 | + <div :class="['flex items-center', isCurrentUser ? 'justify-end' : 'justify-start', 'mb-1']"> | ||
| 247 | + <span class="text-xs text-gray-500 mr-2">{{ message.user_name }}</span> | ||
| 248 | + <div class="h-6 w-6 rounded-full overflow-hidden bg-gray-200"> | ||
| 249 | + <img v-if="message.user_avatar" :src="message.user_avatar" :alt="message.user_name" class="h-full w-full object-cover" /> | ||
| 250 | + <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-full w-full text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| 251 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> | ||
| 252 | + </svg> | ||
| 253 | + </div> | ||
| 254 | + </div> | ||
| 255 | + <div :class="['rounded-lg p-3', isCurrentUser ? 'bg-green-100' : 'bg-white border border-gray-200']"> | ||
| 256 | + <p class="text-gray-700">{{ message.content }}</p> | ||
| 257 | + </div> | ||
| 258 | + <div :class="['text-xs text-gray-500 mt-1', isCurrentUser ? 'text-right' : 'text-left']"> | ||
| 259 | + {{ formatTime(message.timestamp) }} | ||
| 260 | + </div> | ||
| 261 | + </div> | ||
| 262 | + </div> | ||
| 263 | + ` | ||
| 264 | +} | ||
| 265 | + | ||
| 266 | +const messageComponent = (message) => { | ||
| 267 | + switch (message.type) { | ||
| 268 | + case 'announcement': | ||
| 269 | + return AnnouncementMessage | ||
| 270 | + case 'answer': | ||
| 271 | + return AnswerMessage | ||
| 272 | + default: | ||
| 273 | + return DefaultMessage | ||
| 274 | + } | ||
| 275 | +} | ||
| 276 | + | ||
| 277 | +// Computed properties for message grouping | ||
| 278 | +const groupedMessages = computed(() => { | ||
| 279 | + return filteredMessages.value.reduce((groups, message) => { | ||
| 280 | + const date = message.timestamp.split(' ')[0] | ||
| 281 | + if (!groups[date]) { | ||
| 282 | + groups[date] = [] | ||
| 283 | + } | ||
| 284 | + groups[date].push(message) | ||
| 285 | + return groups | ||
| 286 | + }, {}) | ||
| 287 | +}) | ||
| 288 | + | ||
| 289 | +const sortedDates = computed(() => { | ||
| 290 | + return Object.keys(groupedMessages.value).sort() | ||
| 291 | +}) | ||
| 292 | + | ||
| 293 | +// Watch for changes in messages and scroll to bottom | ||
| 294 | +watch(filteredMessages, () => { | ||
| 295 | + if (messageEndRef.value) { | ||
| 296 | + messageEndRef.value.scrollIntoView({ behavior: 'smooth' }) | ||
| 297 | + } | ||
| 298 | +}) | ||
| 299 | + | ||
| 300 | +// Filter messages based on active tab | ||
| 301 | +watch([() => store.messages, activeTab], () => { | ||
| 302 | + if (!store.messages) return | ||
| 303 | + | ||
| 304 | + let filtered = store.messages.filter(msg => msg.activity_id === activityId) | ||
| 305 | + | ||
| 306 | + switch (activeTab.value) { | ||
| 307 | + case 'announcements': | ||
| 308 | + filtered = filtered.filter(msg => msg.type === 'announcement') | ||
| 309 | + break | ||
| 310 | + case 'questions': | ||
| 311 | + filtered = filtered.filter(msg => msg.type === 'question' || msg.type === 'answer') | ||
| 312 | + break | ||
| 313 | + case 'personal': | ||
| 314 | + filtered = filtered.filter(msg => | ||
| 315 | + msg.user_id === store.currentUser?.id || msg.to_user_id === store.currentUser?.id | ||
| 316 | + ) | ||
| 317 | + break | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + filteredMessages.value = filtered.sort((a, b) => { | ||
| 321 | + return new Date(a.timestamp.replace(' ', 'T')) - new Date(b.timestamp.replace(' ', 'T')) | ||
| 322 | + }) | ||
| 323 | +}) | ||
| 324 | + | ||
| 325 | +// Initial data fetch | ||
| 326 | +onMounted(async () => { | ||
| 327 | + try { | ||
| 328 | + if (!store.currentUser) { | ||
| 329 | + error.value = '请先登录' | ||
| 330 | + loading.value = false | ||
| 331 | + return | ||
| 332 | + } | ||
| 333 | + | ||
| 334 | + if (store.activities.length > 0) { | ||
| 335 | + const foundActivity = store.getActivityById(activityId) | ||
| 336 | + | ||
| 337 | + if (foundActivity) { | ||
| 338 | + activity.value = foundActivity | ||
| 339 | + | ||
| 340 | + // Filter messages for this activity | ||
| 341 | + const activityMessages = store.messages.filter( | ||
| 342 | + msg => msg.activity_id === activityId | ||
| 343 | + ).sort((a, b) => { | ||
| 344 | + return new Date(a.timestamp.replace(' ', 'T')) - new Date(b.timestamp.replace(' ', 'T')) | ||
| 345 | + }) | ||
| 346 | + | ||
| 347 | + filteredMessages.value = activityMessages | ||
| 348 | + } else { | ||
| 349 | + error.value = '未找到活动信息' | ||
| 350 | + } | ||
| 351 | + } | ||
| 352 | + loading.value = false | ||
| 353 | + } catch (err) { | ||
| 354 | + console.error('Failed to fetch data:', err) | ||
| 355 | + error.value = '加载数据失败' | ||
| 356 | + loading.value = false | ||
| 357 | + } | ||
| 358 | +}) | ||
| 359 | +</script> | ||
| 360 | + | ||
| 361 | +<style scoped> | ||
| 362 | +.hide-scrollbar { | ||
| 363 | + -ms-overflow-style: none; | ||
| 364 | + scrollbar-width: none; | ||
| 365 | +} | ||
| 366 | + | ||
| 367 | +.hide-scrollbar::-webkit-scrollbar { | ||
| 368 | + display: none; | ||
| 369 | +} | ||
| 370 | +</style> |
src/pages/Registration.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50"> | ||
| 3 | + <!-- Loading State --> | ||
| 4 | + <div v-if="loading" class="min-h-screen flex justify-center items-center bg-gray-50"> | ||
| 5 | + <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-green-500"></div> | ||
| 6 | + </div> | ||
| 7 | + | ||
| 8 | + <!-- Error State --> | ||
| 9 | + <div v-else-if="error || !activity" | ||
| 10 | + class="min-h-screen flex flex-col justify-center items-center bg-gray-50 px-4"> | ||
| 11 | + <div class="text-red-500 text-6xl mb-4"> | ||
| 12 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-24 w-24" fill="none" viewBox="0 0 24 24" | ||
| 13 | + stroke="currentColor"> | ||
| 14 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 15 | + d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 16 | + </svg> | ||
| 17 | + </div> | ||
| 18 | + <h1 class="text-2xl font-bold mb-2">出错了</h1> | ||
| 19 | + <p class="text-gray-600 mb-6">{{ error || '无法加载活动信息' }}</p> | ||
| 20 | + <Button @click="$router.push('/')" variant="primary">返回首页</Button> | ||
| 21 | + </div> | ||
| 22 | + | ||
| 23 | + <!-- Registration Closed State --> | ||
| 24 | + <div v-else-if="!isRegistrationOpen" | ||
| 25 | + class="min-h-screen flex flex-col justify-center items-center bg-gray-50 px-4"> | ||
| 26 | + <div class="text-yellow-500 text-6xl mb-4"> | ||
| 27 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-24 w-24" fill="none" viewBox="0 0 24 24" | ||
| 28 | + stroke="currentColor"> | ||
| 29 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 30 | + d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> | ||
| 31 | + </svg> | ||
| 32 | + </div> | ||
| 33 | + <h1 class="text-2xl font-bold mb-2">报名已截止</h1> | ||
| 34 | + <p class="text-gray-600 mb-6">该活动的报名时间为 {{ formatDate(activity.registration_start) }} 至 {{ | ||
| 35 | + formatDate(activity.registration_end) }}</p> | ||
| 36 | + <Button @click="$router.push(`/activity/${activityId}`)" variant="primary">查看活动详情</Button> | ||
| 37 | + </div> | ||
| 38 | + | ||
| 39 | + <!-- Full State --> | ||
| 40 | + <div v-else-if="isFull" class="min-h-screen flex flex-col justify-center items-center bg-gray-50 px-4"> | ||
| 41 | + <div class="text-blue-500 text-6xl mb-4"> | ||
| 42 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-24 w-24" fill="none" viewBox="0 0 24 24" | ||
| 43 | + stroke="currentColor"> | ||
| 44 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 45 | + d="M13 10V3L4 14h7v7l9-11h-7z" /> | ||
| 46 | + </svg> | ||
| 47 | + </div> | ||
| 48 | + <h1 class="text-2xl font-bold mb-2">名额已满</h1> | ||
| 49 | + <p class="text-gray-600 mb-6">该活动名额已满,请关注其他精彩活动</p> | ||
| 50 | + <div class="flex space-x-4"> | ||
| 51 | + <Button @click="$router.push(`/activity/${activityId}`)" variant="secondary">查看活动详情</Button> | ||
| 52 | + <Button @click="$router.push('/')" variant="primary">浏览更多活动</Button> | ||
| 53 | + </div> | ||
| 54 | + </div> | ||
| 55 | + | ||
| 56 | + <!-- Registration Form --> | ||
| 57 | + <div v-else class="py-8"> | ||
| 58 | + <div class="container mx-auto px-4"> | ||
| 59 | + <div class="max-w-3xl mx-auto bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 60 | + <!-- Header --> | ||
| 61 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 px-6 py-4"> | ||
| 62 | + <h1 class="text-2xl font-bold text-white">活动报名</h1> | ||
| 63 | + </div> | ||
| 64 | + | ||
| 65 | + <!-- Activity Info --> | ||
| 66 | + <div class="border-b border-gray-200 bg-gray-50 px-6 py-4"> | ||
| 67 | + <h2 class="text-xl font-semibold text-gray-800 mb-2">{{ activity.title }}</h2> | ||
| 68 | + <div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm text-gray-600"> | ||
| 69 | + <div class="flex items-center"> | ||
| 70 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mr-2" fill="none" | ||
| 71 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 72 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 73 | + d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> | ||
| 74 | + </svg> | ||
| 75 | + <span>活动时间:{{ formatDate(activity.start_time) }}</span> | ||
| 76 | + </div> | ||
| 77 | + <div class="flex items-center"> | ||
| 78 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mr-2" fill="none" | ||
| 79 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 80 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 81 | + d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /> | ||
| 82 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 83 | + d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /> | ||
| 84 | + </svg> | ||
| 85 | + <span>{{ activity.activity_type === 'online' ? '线上活动' : `活动地点:${activity.location}` | ||
| 86 | + }}</span> | ||
| 87 | + </div> | ||
| 88 | + <div class="flex items-center"> | ||
| 89 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mr-2" fill="none" | ||
| 90 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 91 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 92 | + d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /> | ||
| 93 | + </svg> | ||
| 94 | + <span>已报名:{{ activity.participant_count }}/{{ activity.max_participants }}</span> | ||
| 95 | + </div> | ||
| 96 | + <div class="flex items-center"> | ||
| 97 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-500 mr-2" fill="none" | ||
| 98 | + viewBox="0 0 24 24" stroke="currentColor"> | ||
| 99 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" | ||
| 100 | + d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" /> | ||
| 101 | + </svg> | ||
| 102 | + <span>报名截止:{{ formatDate(activity.registration_end) }}</span> | ||
| 103 | + </div> | ||
| 104 | + </div> | ||
| 105 | + </div> | ||
| 106 | + | ||
| 107 | + <!-- Registration Form --> | ||
| 108 | + <form class="p-6" @submit.prevent="handleSubmit"> | ||
| 109 | + <h3 class="text-lg font-medium text-gray-900 mb-4">填写报名信息</h3> | ||
| 110 | + | ||
| 111 | + <div class="space-y-6"> | ||
| 112 | + <Input id="name" label="姓名" v-model="formState.name" :error="formErrors.name" | ||
| 113 | + placeholder="请输入您的姓名" required /> | ||
| 114 | + | ||
| 115 | + <Input id="phone" label="手机号码" v-model="formState.phone" :error="formErrors.phone" | ||
| 116 | + placeholder="请输入您的手机号码" required /> | ||
| 117 | + | ||
| 118 | + <Input id="email" label="电子邮箱" type="email" v-model="formState.email" | ||
| 119 | + :error="formErrors.email" placeholder="请输入您的电子邮箱" required /> | ||
| 120 | + | ||
| 121 | + <div> | ||
| 122 | + <label for="reason" class="block text-sm font-medium text-gray-700 mb-1"> | ||
| 123 | + 参加原因 <span class="text-red-500">*</span> | ||
| 124 | + </label> | ||
| 125 | + <textarea id="reason" v-model="formState.reason" rows="4" :class="[ | ||
| 126 | + 'block w-full border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm', | ||
| 127 | + formErrors.reason ? 'border-red-300' : '' | ||
| 128 | + ]" placeholder="请简要说明您参加本次活动的原因或期望..."></textarea> | ||
| 129 | + <p v-if="formErrors.reason" class="mt-1 text-sm text-red-600">{{ formErrors.reason }} | ||
| 130 | + </p> | ||
| 131 | + </div> | ||
| 132 | + | ||
| 133 | + <div class="flex items-start"> | ||
| 134 | + <div class="flex items-center h-5"> | ||
| 135 | + <input id="agreeTerms" type="checkbox" v-model="formState.agreeTerms" | ||
| 136 | + class="focus:ring-green-500 h-4 w-4 text-green-600 border-gray-300 rounded" /> | ||
| 137 | + </div> | ||
| 138 | + <div class="ml-3 text-sm"> | ||
| 139 | + <label for="agreeTerms" | ||
| 140 | + :class="['font-medium', formErrors.agreeTerms ? 'text-red-600' : 'text-gray-700']"> | ||
| 141 | + 我同意活动条款和隐私政策 | ||
| 142 | + </label> | ||
| 143 | + <p class="text-gray-500"> | ||
| 144 | + 注册即表示您同意我们的 | ||
| 145 | + <a href="#" class="text-green-600 hover:text-green-500">服务条款</a>和 | ||
| 146 | + <a href="#" class="text-green-600 hover:text-green-500">隐私政策</a>。 | ||
| 147 | + </p> | ||
| 148 | + <p v-if="formErrors.agreeTerms" class="mt-1 text-sm text-red-600">{{ | ||
| 149 | + formErrors.agreeTerms }}</p> | ||
| 150 | + </div> | ||
| 151 | + </div> | ||
| 152 | + </div> | ||
| 153 | + | ||
| 154 | + <div class="mt-8 flex justify-between"> | ||
| 155 | + <Button type="button" variant="secondary" @click="$router.push(`/activity/${activityId}`)"> | ||
| 156 | + 返回活动详情 | ||
| 157 | + </Button> | ||
| 158 | + <Button type="submit" variant="primary" :disabled="isSubmitting"> | ||
| 159 | + {{ isSubmitting ? '提交中...' : '确认报名' }} | ||
| 160 | + </Button> | ||
| 161 | + </div> | ||
| 162 | + </form> | ||
| 163 | + </div> | ||
| 164 | + </div> | ||
| 165 | + </div> | ||
| 166 | + </div> | ||
| 167 | +</template> | ||
| 168 | + | ||
| 169 | +<script setup> | ||
| 170 | +import { ref, computed, onMounted } from 'vue' | ||
| 171 | +import { useRoute, useRouter } from 'vue-router' | ||
| 172 | +import { useAppStore } from '../stores/app' | ||
| 173 | +import Button from '../components/shared/Button.vue' | ||
| 174 | +import Input from '../components/shared/Input.vue' | ||
| 175 | + | ||
| 176 | +const route = useRoute() | ||
| 177 | +const router = useRouter() | ||
| 178 | +const store = useAppStore() | ||
| 179 | + | ||
| 180 | +const activityId = route.params.activityId | ||
| 181 | +const activity = ref(null) | ||
| 182 | +const loading = ref(true) | ||
| 183 | +const error = ref(null) | ||
| 184 | +const isSubmitting = ref(false) | ||
| 185 | + | ||
| 186 | +const formState = ref({ | ||
| 187 | + name: '', | ||
| 188 | + phone: '', | ||
| 189 | + email: '', | ||
| 190 | + reason: '', | ||
| 191 | + agreeTerms: false | ||
| 192 | +}) | ||
| 193 | + | ||
| 194 | +const formErrors = ref({}) | ||
| 195 | + | ||
| 196 | +// Fetch activity details | ||
| 197 | +onMounted(async () => { | ||
| 198 | + try { | ||
| 199 | + if (store.activities.length > 0) { | ||
| 200 | + const foundActivity = store.getActivityById(activityId) | ||
| 201 | + | ||
| 202 | + if (foundActivity) { | ||
| 203 | + activity.value = foundActivity | ||
| 204 | + | ||
| 205 | + // Pre-fill form with user data if available | ||
| 206 | + if (store.currentUser) { | ||
| 207 | + formState.value = { | ||
| 208 | + ...formState.value, | ||
| 209 | + name: store.currentUser.name || '', | ||
| 210 | + phone: store.currentUser.phone || '', | ||
| 211 | + email: store.currentUser.email || '' | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + } else { | ||
| 215 | + error.value = '未找到活动信息' | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + loading.value = false | ||
| 219 | + } catch (err) { | ||
| 220 | + console.error('Failed to fetch activity details:', err) | ||
| 221 | + error.value = '加载活动详情失败' | ||
| 222 | + loading.value = false | ||
| 223 | + } | ||
| 224 | +}) | ||
| 225 | + | ||
| 226 | +// Validate form | ||
| 227 | +const validateForm = () => { | ||
| 228 | + const errors = {} | ||
| 229 | + | ||
| 230 | + if (!formState.value.name.trim()) { | ||
| 231 | + errors.name = '请输入您的姓名' | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + if (!formState.value.phone.trim()) { | ||
| 235 | + errors.phone = '请输入您的手机号码' | ||
| 236 | + } else if (!/^1[3-9]\d{9}$/.test(formState.value.phone)) { | ||
| 237 | + errors.phone = '请输入有效的手机号码' | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + if (!formState.value.email.trim()) { | ||
| 241 | + errors.email = '请输入您的电子邮箱' | ||
| 242 | + } else if (!/\S+@\S+\.\S+/.test(formState.value.email)) { | ||
| 243 | + errors.email = '请输入有效的电子邮箱' | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + if (!formState.value.reason.trim()) { | ||
| 247 | + errors.reason = '请简要说明参加原因' | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + if (!formState.value.agreeTerms) { | ||
| 251 | + errors.agreeTerms = '请同意活动条款和隐私政策' | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + formErrors.value = errors | ||
| 255 | + return Object.keys(errors).length === 0 | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +// Handle form submission | ||
| 259 | +const handleSubmit = async () => { | ||
| 260 | + if (!store.currentUser) { | ||
| 261 | + alert('请先登录再进行报名') | ||
| 262 | + // Redirect to login page in a real app | ||
| 263 | + return | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + if (!validateForm()) { | ||
| 267 | + // Focus on first error field | ||
| 268 | + const firstErrorField = Object.keys(formErrors.value)[0] | ||
| 269 | + const element = document.getElementById(firstErrorField) | ||
| 270 | + if (element) { | ||
| 271 | + element.scrollIntoView({ behavior: 'smooth', block: 'center' }) | ||
| 272 | + } | ||
| 273 | + return | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + isSubmitting.value = true | ||
| 277 | + | ||
| 278 | + try { | ||
| 279 | + const registrationData = { | ||
| 280 | + fields: { | ||
| 281 | + 姓名: true, | ||
| 282 | + 手机号: true, | ||
| 283 | + 邮箱: true, | ||
| 284 | + 参加原因: true | ||
| 285 | + }, | ||
| 286 | + answers: { | ||
| 287 | + 姓名: formState.value.name, | ||
| 288 | + 手机号: formState.value.phone, | ||
| 289 | + 邮箱: formState.value.email, | ||
| 290 | + 参加原因: formState.value.reason | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + const result = await store.registerForActivity(activityId, registrationData) | ||
| 295 | + | ||
| 296 | + if (result.success) { | ||
| 297 | + alert('报名成功,请等待审核') | ||
| 298 | + router.push(`/activity/${activityId}`) | ||
| 299 | + } else { | ||
| 300 | + alert(`报名失败: ${result.error}`) | ||
| 301 | + isSubmitting.value = false | ||
| 302 | + } | ||
| 303 | + } catch (error) { | ||
| 304 | + console.error('Registration error:', error) | ||
| 305 | + alert('报名失败,请稍后再试') | ||
| 306 | + isSubmitting.value = false | ||
| 307 | + } | ||
| 308 | +} | ||
| 309 | + | ||
| 310 | +// Format date for display | ||
| 311 | +const formatDate = (dateString) => { | ||
| 312 | + if (!dateString) return '' | ||
| 313 | + const date = new Date(dateString.replace(' ', 'T')) | ||
| 314 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 315 | + year: 'numeric', | ||
| 316 | + month: 'long', | ||
| 317 | + day: 'numeric', | ||
| 318 | + hour: '2-digit', | ||
| 319 | + minute: '2-digit', | ||
| 320 | + hour12: false | ||
| 321 | + }).format(date) | ||
| 322 | +} | ||
| 323 | + | ||
| 324 | +// Check if registration is still open | ||
| 325 | +const isRegistrationOpen = computed(() => { | ||
| 326 | + if (!activity.value) return false | ||
| 327 | + return ( | ||
| 328 | + new Date() >= new Date(activity.value.registration_start.replace(' ', 'T')) && | ||
| 329 | + new Date() <= new Date(activity.value.registration_end.replace(' ', 'T')) | ||
| 330 | + ) | ||
| 331 | +}) | ||
| 332 | + | ||
| 333 | +// Check if activity is full | ||
| 334 | +const isFull = computed(() => { | ||
| 335 | + if (!activity.value) return false | ||
| 336 | + return activity.value.participant_count >= activity.value.max_participants | ||
| 337 | +}) | ||
| 338 | +</script> |
src/pages/UserProfile.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="min-h-screen bg-gray-50"> | ||
| 3 | + <!-- Loading UI if no current user --> | ||
| 4 | + <div v-if="!currentUser" class="min-h-screen flex justify-center items-center bg-gray-50"> | ||
| 5 | + <div class="text-center"> | ||
| 6 | + <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-green-500 mx-auto"></div> | ||
| 7 | + <p class="mt-4 text-gray-600">加载用户资料...</p> | ||
| 8 | + </div> | ||
| 9 | + </div> | ||
| 10 | + | ||
| 11 | + <template v-else> | ||
| 12 | + <!-- Profile Header --> | ||
| 13 | + <div class="bg-gradient-to-r from-green-500 to-blue-500 py-12 px-4"> | ||
| 14 | + <div class="container mx-auto"> | ||
| 15 | + <div class="flex flex-col md:flex-row items-center justify-between"> | ||
| 16 | + <!-- User Info --> | ||
| 17 | + <div class="flex flex-col md:flex-row items-center"> | ||
| 18 | + <div | ||
| 19 | + class="h-24 w-24 md:h-32 md:w-32 rounded-full overflow-hidden border-4 border-white mb-4 md:mb-0 md:mr-6"> | ||
| 20 | + <img :src="currentUser.avatar || '/assets/images/avatars/default_avatar.png'" | ||
| 21 | + :alt="currentUser.name" class="h-full w-full object-cover" /> | ||
| 22 | + </div> | ||
| 23 | + <div class="text-center md:text-left"> | ||
| 24 | + <h1 class="text-2xl md:text-3xl font-bold text-white">{{ currentUser.name }}</h1> | ||
| 25 | + <p class="text-white mt-2 opacity-90">@{{ currentUser.username }}</p> | ||
| 26 | + <div class="flex flex-wrap justify-center md:justify-start mt-3 gap-2"> | ||
| 27 | + <span v-for="(interest, index) in displayedInterests" :key="index" | ||
| 28 | + class="bg-white bg-opacity-20 text-white px-3 py-1 rounded-full text-sm"> | ||
| 29 | + {{ interest }} | ||
| 30 | + </span> | ||
| 31 | + <span v-if="currentUser.interests && currentUser.interests.length > 3" | ||
| 32 | + class="bg-white bg-opacity-20 text-white px-3 py-1 rounded-full text-sm"> | ||
| 33 | + +{{ currentUser.interests.length - 3 }} | ||
| 34 | + </span> | ||
| 35 | + </div> | ||
| 36 | + </div> | ||
| 37 | + </div> | ||
| 38 | + | ||
| 39 | + <!-- Actions --> | ||
| 40 | + <div class="mt-6 md:mt-0 flex gap-2"> | ||
| 41 | + <Button @click="isEditModalOpen = true" variant="secondary"> | ||
| 42 | + <template #leftIcon> | ||
| 43 | + <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" | ||
| 44 | + fill="currentColor"> | ||
| 45 | + <path | ||
| 46 | + d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" /> | ||
| 47 | + </svg> | ||
| 48 | + </template> | ||
| 49 | + 编辑资料 | ||
| 50 | + </Button> | ||
| 51 | + </div> | ||
| 52 | + </div> | ||
| 53 | + </div> | ||
| 54 | + </div> | ||
| 55 | + | ||
| 56 | + <!-- Profile Content --> | ||
| 57 | + <div class="container mx-auto py-8 px-4"> | ||
| 58 | + <div class="bg-white rounded-lg shadow-sm overflow-hidden"> | ||
| 59 | + <Tabs :tabs="profileTabs" /> | ||
| 60 | + </div> | ||
| 61 | + </div> | ||
| 62 | + | ||
| 63 | + <!-- Edit Profile Modal --> | ||
| 64 | + <Modal v-model:show="isEditModalOpen" title="编辑个人资料"> | ||
| 65 | + <div class="space-y-4"> | ||
| 66 | + <Input v-model="editForm.name" label="姓名" placeholder="请输入姓名" /> | ||
| 67 | + <Input v-model="editForm.email" label="电子邮箱" type="email" placeholder="请输入电子邮箱" /> | ||
| 68 | + <Input v-model="editForm.phone" label="手机号码" placeholder="请输入手机号码" /> | ||
| 69 | + <Input v-model="editForm.location" label="所在地" placeholder="请输入所在地" /> | ||
| 70 | + <div> | ||
| 71 | + <label class="block text-sm font-medium text-gray-700 mb-1">个人简介</label> | ||
| 72 | + <textarea v-model="editForm.bio" rows="4" | ||
| 73 | + class="w-full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring-green-500" | ||
| 74 | + placeholder="请输入个人简介"></textarea> | ||
| 75 | + </div> | ||
| 76 | + <div> | ||
| 77 | + <label class="block text-sm font-medium text-gray-700 mb-1">兴趣标签</label> | ||
| 78 | + <div class="flex flex-wrap gap-2 mb-2"> | ||
| 79 | + <span v-for="interest in editForm.interests" :key="interest" | ||
| 80 | + class="bg-green-50 text-green-700 px-3 py-1 rounded-full text-sm flex items-center"> | ||
| 81 | + {{ interest }} | ||
| 82 | + <button @click="handleRemoveInterest(interest)" | ||
| 83 | + class="ml-2 text-green-500 hover:text-green-700"> | ||
| 84 | + × | ||
| 85 | + </button> | ||
| 86 | + </span> | ||
| 87 | + </div> | ||
| 88 | + <div class="flex gap-2"> | ||
| 89 | + <Input v-model="interestInput" placeholder="添加兴趣标签" @keyup.enter="handleAddInterest" /> | ||
| 90 | + <Button @click="handleAddInterest" variant="secondary">添加</Button> | ||
| 91 | + </div> | ||
| 92 | + </div> | ||
| 93 | + </div> | ||
| 94 | + <template #footer> | ||
| 95 | + <div class="flex justify-end gap-2"> | ||
| 96 | + <Button @click="isEditModalOpen = false" variant="ghost">取消</Button> | ||
| 97 | + <Button @click="handleSubmitEdit" variant="primary">保存</Button> | ||
| 98 | + </div> | ||
| 99 | + </template> | ||
| 100 | + </Modal> | ||
| 101 | + </template> | ||
| 102 | + </div> | ||
| 103 | +</template> | ||
| 104 | + | ||
| 105 | +<script setup> | ||
| 106 | +import { ref, computed, onMounted } from 'vue' | ||
| 107 | +import { useAppStore } from '../stores/app' | ||
| 108 | +import Button from '../components/shared/Button.vue' | ||
| 109 | +import Input from '../components/shared/Input.vue' | ||
| 110 | +import Tabs from '../components/shared/Tabs.vue' | ||
| 111 | +import ActivityCard from '../components/shared/ActivityCard.vue' | ||
| 112 | +import Modal from '../components/shared/Modal.vue' | ||
| 113 | + | ||
| 114 | +const store = useAppStore() | ||
| 115 | +const { currentUser, activities, registrations } = store | ||
| 116 | + | ||
| 117 | +const userRegistrations = ref([]) | ||
| 118 | +const registeredActivities = ref([]) | ||
| 119 | +const pastActivities = ref([]) | ||
| 120 | +const upcomingActivities = ref([]) | ||
| 121 | +const isEditModalOpen = ref(false) | ||
| 122 | +const editForm = ref({ | ||
| 123 | + name: '', | ||
| 124 | + bio: '', | ||
| 125 | + email: '', | ||
| 126 | + phone: '', | ||
| 127 | + location: '', | ||
| 128 | + interests: [] | ||
| 129 | +}) | ||
| 130 | +const interestInput = ref('') | ||
| 131 | + | ||
| 132 | +// Computed properties | ||
| 133 | +const displayedInterests = computed(() => { | ||
| 134 | + return currentUser.value?.interests?.slice(0, 3) || [] | ||
| 135 | +}) | ||
| 136 | + | ||
| 137 | +// Methods | ||
| 138 | +const handleInputChange = (e) => { | ||
| 139 | + const { name, value } = e.target | ||
| 140 | + editForm.value[name] = value | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +const handleAddInterest = () => { | ||
| 144 | + const interest = interestInput.value.trim() | ||
| 145 | + if (interest && !editForm.value.interests.includes(interest)) { | ||
| 146 | + editForm.value.interests.push(interest) | ||
| 147 | + interestInput.value = '' | ||
| 148 | + } | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +const handleRemoveInterest = (interestToRemove) => { | ||
| 152 | + editForm.value.interests = editForm.value.interests.filter( | ||
| 153 | + interest => interest !== interestToRemove | ||
| 154 | + ) | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +const handleSubmitEdit = () => { | ||
| 158 | + // In a real app, this would make an API call to update the user profile | ||
| 159 | + console.log('Profile update submitted:', editForm.value) | ||
| 160 | + isEditModalOpen.value = false | ||
| 161 | + // Update would be handled through context in a real app | ||
| 162 | +} | ||
| 163 | + | ||
| 164 | +const formatRegistrationDate = (dateString) => { | ||
| 165 | + const date = new Date(dateString.replace(' ', 'T')) | ||
| 166 | + return new Intl.DateTimeFormat('zh-CN', { | ||
| 167 | + year: 'numeric', | ||
| 168 | + month: 'short', | ||
| 169 | + day: 'numeric', | ||
| 170 | + hour: '2-digit', | ||
| 171 | + minute: '2-digit', | ||
| 172 | + hour12: false | ||
| 173 | + }).format(date) | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +// Profile tabs configuration | ||
| 177 | +const profileTabs = computed(() => [ | ||
| 178 | + { | ||
| 179 | + label: "个人资料", | ||
| 180 | + content: { | ||
| 181 | + component: 'div', | ||
| 182 | + class: 'p-6', | ||
| 183 | + children: [ | ||
| 184 | + // Basic Info section | ||
| 185 | + { | ||
| 186 | + component: 'div', | ||
| 187 | + class: 'grid grid-cols-1 md:grid-cols-2 gap-8', | ||
| 188 | + children: [ | ||
| 189 | + // Left column | ||
| 190 | + { | ||
| 191 | + component: 'div', | ||
| 192 | + children: [ | ||
| 193 | + { | ||
| 194 | + component: 'h3', | ||
| 195 | + class: 'text-lg font-medium text-gray-900 mb-4', | ||
| 196 | + text: '基本信息' | ||
| 197 | + }, | ||
| 198 | + // User info fields | ||
| 199 | + { | ||
| 200 | + component: 'div', | ||
| 201 | + class: 'space-y-4', | ||
| 202 | + children: [ | ||
| 203 | + // Name | ||
| 204 | + { | ||
| 205 | + component: 'div', | ||
| 206 | + children: [ | ||
| 207 | + { | ||
| 208 | + component: 'h4', | ||
| 209 | + class: 'text-sm font-medium text-gray-500', | ||
| 210 | + text: '姓名' | ||
| 211 | + }, | ||
| 212 | + { | ||
| 213 | + component: 'p', | ||
| 214 | + class: 'mt-1 text-gray-900', | ||
| 215 | + text: currentUser.value?.name | ||
| 216 | + } | ||
| 217 | + ] | ||
| 218 | + }, | ||
| 219 | + // Location | ||
| 220 | + { | ||
| 221 | + component: 'div', | ||
| 222 | + children: [ | ||
| 223 | + { | ||
| 224 | + component: 'h4', | ||
| 225 | + class: 'text-sm font-medium text-gray-500', | ||
| 226 | + text: '所在地' | ||
| 227 | + }, | ||
| 228 | + { | ||
| 229 | + component: 'p', | ||
| 230 | + class: 'mt-1 text-gray-900', | ||
| 231 | + text: currentUser.value?.location || '未设置' | ||
| 232 | + } | ||
| 233 | + ] | ||
| 234 | + } | ||
| 235 | + ] | ||
| 236 | + } | ||
| 237 | + ] | ||
| 238 | + }, | ||
| 239 | + // Right column | ||
| 240 | + { | ||
| 241 | + component: 'div', | ||
| 242 | + children: [ | ||
| 243 | + { | ||
| 244 | + component: 'h3', | ||
| 245 | + class: 'text-lg font-medium text-gray-900 mb-4', | ||
| 246 | + text: '联系方式' | ||
| 247 | + }, | ||
| 248 | + // Contact info | ||
| 249 | + { | ||
| 250 | + component: 'div', | ||
| 251 | + class: 'space-y-4', | ||
| 252 | + children: [ | ||
| 253 | |||
| 254 | + { | ||
| 255 | + component: 'div', | ||
| 256 | + children: [ | ||
| 257 | + { | ||
| 258 | + component: 'h4', | ||
| 259 | + class: 'text-sm font-medium text-gray-500', | ||
| 260 | + text: '电子邮箱' | ||
| 261 | + }, | ||
| 262 | + { | ||
| 263 | + component: 'p', | ||
| 264 | + class: 'mt-1 text-gray-900', | ||
| 265 | + text: currentUser.value?.email | ||
| 266 | + } | ||
| 267 | + ] | ||
| 268 | + }, | ||
| 269 | + // Phone | ||
| 270 | + { | ||
| 271 | + component: 'div', | ||
| 272 | + children: [ | ||
| 273 | + { | ||
| 274 | + component: 'h4', | ||
| 275 | + class: 'text-sm font-medium text-gray-500', | ||
| 276 | + text: '手机号码' | ||
| 277 | + }, | ||
| 278 | + { | ||
| 279 | + component: 'p', | ||
| 280 | + class: 'mt-1 text-gray-900', | ||
| 281 | + text: currentUser.value?.phone | ||
| 282 | + } | ||
| 283 | + ] | ||
| 284 | + } | ||
| 285 | + ] | ||
| 286 | + } | ||
| 287 | + ] | ||
| 288 | + } | ||
| 289 | + ] | ||
| 290 | + } | ||
| 291 | + ] | ||
| 292 | + } | ||
| 293 | + }, | ||
| 294 | + { | ||
| 295 | + label: "我的活动", | ||
| 296 | + content: { | ||
| 297 | + component: 'div', | ||
| 298 | + class: 'p-6', | ||
| 299 | + children: [ | ||
| 300 | + // Upcoming activities section | ||
| 301 | + { | ||
| 302 | + component: 'div', | ||
| 303 | + class: 'mb-8', | ||
| 304 | + children: [ | ||
| 305 | + { | ||
| 306 | + component: 'h3', | ||
| 307 | + class: 'text-lg font-medium text-gray-900 mb-4', | ||
| 308 | + children: [ | ||
| 309 | + { | ||
| 310 | + component: 'span', | ||
| 311 | + class: 'inline-block w-3 h-3 bg-green-500 rounded-full mr-2' | ||
| 312 | + }, | ||
| 313 | + { | ||
| 314 | + component: 'span', | ||
| 315 | + text: '即将参加的活动' | ||
| 316 | + } | ||
| 317 | + ] | ||
| 318 | + }, | ||
| 319 | + // Activity cards | ||
| 320 | + { | ||
| 321 | + component: 'div', | ||
| 322 | + class: 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6', | ||
| 323 | + children: upcomingActivities.value.map(activity => ({ | ||
| 324 | + component: ActivityCard, | ||
| 325 | + props: { activity } | ||
| 326 | + })) | ||
| 327 | + } | ||
| 328 | + ] | ||
| 329 | + } | ||
| 330 | + ] | ||
| 331 | + } | ||
| 332 | + }, | ||
| 333 | + { | ||
| 334 | + label: "报名记录", | ||
| 335 | + content: { | ||
| 336 | + component: 'div', | ||
| 337 | + class: 'p-6', | ||
| 338 | + children: [ | ||
| 339 | + { | ||
| 340 | + component: 'div', | ||
| 341 | + class: 'overflow-x-auto', | ||
| 342 | + children: [ | ||
| 343 | + // Registration table | ||
| 344 | + { | ||
| 345 | + component: 'table', | ||
| 346 | + class: 'min-w-full divide-y divide-gray-200', | ||
| 347 | + children: [ | ||
| 348 | + // Table header | ||
| 349 | + { | ||
| 350 | + component: 'thead', | ||
| 351 | + class: 'bg-gray-50', | ||
| 352 | + children: [ | ||
| 353 | + { | ||
| 354 | + component: 'tr', | ||
| 355 | + children: [ | ||
| 356 | + { | ||
| 357 | + component: 'th', | ||
| 358 | + class: 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider', | ||
| 359 | + text: '活动信息' | ||
| 360 | + }, | ||
| 361 | + { | ||
| 362 | + component: 'th', | ||
| 363 | + class: 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider', | ||
| 364 | + text: '报名时间' | ||
| 365 | + }, | ||
| 366 | + { | ||
| 367 | + component: 'th', | ||
| 368 | + class: 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider', | ||
| 369 | + text: '状态' | ||
| 370 | + } | ||
| 371 | + ] | ||
| 372 | + } | ||
| 373 | + ] | ||
| 374 | + }, | ||
| 375 | + // Table body | ||
| 376 | + { | ||
| 377 | + component: 'tbody', | ||
| 378 | + class: 'bg-white divide-y divide-gray-200', | ||
| 379 | + children: userRegistrations.value.map(registration => ({ | ||
| 380 | + component: 'tr', | ||
| 381 | + key: registration.id, | ||
| 382 | + children: [ | ||
| 383 | + // Activity info | ||
| 384 | + { | ||
| 385 | + component: 'td', | ||
| 386 | + class: 'px-6 py-4 whitespace-nowrap', | ||
| 387 | + children: [ | ||
| 388 | + { | ||
| 389 | + component: 'div', | ||
| 390 | + class: 'flex items-center', | ||
| 391 | + children: [ | ||
| 392 | + { | ||
| 393 | + component: 'div', | ||
| 394 | + class: 'text-sm font-medium text-gray-900', | ||
| 395 | + text: activities.value.find(a => a.id === registration.activity_id)?.title || '未知活动' | ||
| 396 | + } | ||
| 397 | + ] | ||
| 398 | + } | ||
| 399 | + ] | ||
| 400 | + }, | ||
| 401 | + // Registration time | ||
| 402 | + { | ||
| 403 | + component: 'td', | ||
| 404 | + class: 'px-6 py-4 whitespace-nowrap', | ||
| 405 | + children: [ | ||
| 406 | + { | ||
| 407 | + component: 'div', | ||
| 408 | + class: 'text-sm text-gray-900', | ||
| 409 | + text: formatRegistrationDate(registration.registration_time) | ||
| 410 | + } | ||
| 411 | + ] | ||
| 412 | + }, | ||
| 413 | + // Status | ||
| 414 | + { | ||
| 415 | + component: 'td', | ||
| 416 | + class: 'px-6 py-4 whitespace-nowrap', | ||
| 417 | + children: [ | ||
| 418 | + { | ||
| 419 | + component: 'span', | ||
| 420 | + class: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${registration.status === 'approved' | ||
| 421 | + ? 'bg-green-100 text-green-800' | ||
| 422 | + : registration.status === 'pending' | ||
| 423 | + ? 'bg-yellow-100 text-yellow-800' | ||
| 424 | + : 'bg-gray-100 text-gray-800' | ||
| 425 | + }`, | ||
| 426 | + text: registration.status === 'approved' | ||
| 427 | + ? '已通过' | ||
| 428 | + : registration.status === 'pending' | ||
| 429 | + ? '审核中' | ||
| 430 | + : registration.status | ||
| 431 | + } | ||
| 432 | + ] | ||
| 433 | + } | ||
| 434 | + ] | ||
| 435 | + })) | ||
| 436 | + } | ||
| 437 | + ] | ||
| 438 | + } | ||
| 439 | + ] | ||
| 440 | + } | ||
| 441 | + ] | ||
| 442 | + } | ||
| 443 | + } | ||
| 444 | +]) | ||
| 445 | + | ||
| 446 | +// Lifecycle hooks | ||
| 447 | +onMounted(() => { | ||
| 448 | + if (currentUser.value) { | ||
| 449 | + editForm.value = { | ||
| 450 | + name: currentUser.value.name || '', | ||
| 451 | + bio: currentUser.value.bio || '', | ||
| 452 | + email: currentUser.value.email || '', | ||
| 453 | + phone: currentUser.value.phone || '', | ||
| 454 | + location: currentUser.value.location || '', | ||
| 455 | + interests: currentUser.value.interests || [] | ||
| 456 | + } | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + if (currentUser.value && registrations.value && activities.value) { | ||
| 460 | + // Filter user registrations | ||
| 461 | + const userRegs = registrations.value.filter(reg => reg.user_id === currentUser.value.id) | ||
| 462 | + userRegistrations.value = userRegs | ||
| 463 | + | ||
| 464 | + // Get activities the user has registered for | ||
| 465 | + const regActivityIds = userRegs.map(reg => reg.activity_id) | ||
| 466 | + const regActivities = activities.value.filter(act => regActivityIds.includes(act.id)) | ||
| 467 | + registeredActivities.value = regActivities | ||
| 468 | + | ||
| 469 | + const now = new Date() | ||
| 470 | + | ||
| 471 | + // Split activities into past and upcoming | ||
| 472 | + pastActivities.value = regActivities.filter(act => { | ||
| 473 | + return new Date(act.end_time.replace(' ', 'T')) < now | ||
| 474 | + }) | ||
| 475 | + | ||
| 476 | + upcomingActivities.value = regActivities.filter(act => { | ||
| 477 | + return new Date(act.start_time.replace(' ', 'T')) > now | ||
| 478 | + }) | ||
| 479 | + } | ||
| 480 | +}) | ||
| 481 | +</script> |
src/providers/AppProvider.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-04-17 13:41:17 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 13:41:18 | ||
| 5 | + * @FilePath: /reading-club-app/src/providers/AppProvider.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <slot></slot> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script setup> | ||
| 13 | +import { onMounted } from 'vue' | ||
| 14 | +import { useAppStore } from '../stores/app' | ||
| 15 | + | ||
| 16 | +const store = useAppStore() | ||
| 17 | + | ||
| 18 | +onMounted(() => { | ||
| 19 | + store.fetchInitialData() | ||
| 20 | +}) | ||
| 21 | +</script> |
src/stores/app.js
0 → 100644
| 1 | +import { defineStore } from 'pinia' | ||
| 2 | +import { ref, computed } from 'vue' | ||
| 3 | + | ||
| 4 | +export const useAppStore = defineStore('app', () => { | ||
| 5 | + const currentUser = ref(null) | ||
| 6 | + const activities = ref([]) | ||
| 7 | + const loading = ref(true) | ||
| 8 | + const error = ref(null) | ||
| 9 | + const registrations = ref([]) | ||
| 10 | + const userMessages = ref([]) | ||
| 11 | + | ||
| 12 | + // 初始化应用数据 | ||
| 13 | + async function fetchInitialData() { | ||
| 14 | + try { | ||
| 15 | + loading.value = true | ||
| 16 | + | ||
| 17 | + // 获取用户数据 | ||
| 18 | + const usersResponse = await fetch('/data/users.json') | ||
| 19 | + const usersData = await usersResponse.json() | ||
| 20 | + currentUser.value = usersData[0] | ||
| 21 | + | ||
| 22 | + // 获取活动数据 | ||
| 23 | + const activitiesResponse = await fetch('/data/activities.json') | ||
| 24 | + const activitiesData = await activitiesResponse.json() | ||
| 25 | + activities.value = activitiesData | ||
| 26 | + | ||
| 27 | + // 获取报名数据 | ||
| 28 | + const registrationsResponse = await fetch('/data/registrations.json') | ||
| 29 | + const registrationsData = await registrationsResponse.json() | ||
| 30 | + registrations.value = registrationsData | ||
| 31 | + | ||
| 32 | + // 获取消息数据 | ||
| 33 | + const messagesResponse = await fetch('/data/messages.json') | ||
| 34 | + const messagesData = await messagesResponse.json() | ||
| 35 | + userMessages.value = messagesData | ||
| 36 | + | ||
| 37 | + loading.value = false | ||
| 38 | + } catch (err) { | ||
| 39 | + console.error('Failed to fetch initial data:', err) | ||
| 40 | + error.value = '加载应用数据失败,请稍后重试。' | ||
| 41 | + loading.value = false | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + // 根据ID获取活动 | ||
| 46 | + const getActivityById = computed(() => { | ||
| 47 | + return (activityId) => activities.value.find(activity => activity.id === activityId) || null | ||
| 48 | + }) | ||
| 49 | + | ||
| 50 | + // 获取用户的报名记录 | ||
| 51 | + const getUserRegistrations = computed(() => { | ||
| 52 | + return () => currentUser.value ? registrations.value.filter(reg => reg.user_id === currentUser.value.id) : [] | ||
| 53 | + }) | ||
| 54 | + | ||
| 55 | + // 报名活动 | ||
| 56 | + function registerForActivity(activityId, formData) { | ||
| 57 | + if (!currentUser.value) return { success: false, error: '用户未登录' } | ||
| 58 | + | ||
| 59 | + const newRegistration = { | ||
| 60 | + id: `R${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 61 | + activity_id: activityId, | ||
| 62 | + user_id: currentUser.value.id, | ||
| 63 | + registration_time: new Date().toISOString().replace('T', ' ').substring(0, 19), | ||
| 64 | + status: 'pending', | ||
| 65 | + custom_fields: formData.fields, | ||
| 66 | + custom_answers: formData.answers | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + registrations.value.push(newRegistration) | ||
| 70 | + return { success: true, registrationId: newRegistration.id } | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + // 创建新活动 | ||
| 74 | + function createActivity(activityData) { | ||
| 75 | + if (!currentUser.value) return { success: false, error: '用户未登录' } | ||
| 76 | + | ||
| 77 | + const newActivity = { | ||
| 78 | + id: `A${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 79 | + organizer_id: currentUser.value.id, | ||
| 80 | + organizer_name: currentUser.value.name, | ||
| 81 | + ...activityData, | ||
| 82 | + participant_count: 0, | ||
| 83 | + is_published: activityData.is_published || true, | ||
| 84 | + is_public: activityData.is_public || true, | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + activities.value.push(newActivity) | ||
| 88 | + return { success: true, activityId: newActivity.id } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + // 活动签到 | ||
| 92 | + function checkInForActivity(activityId, registrationId, method = 'manual') { | ||
| 93 | + if (!currentUser.value) return { success: false, error: '用户未登录' } | ||
| 94 | + | ||
| 95 | + const checkinData = { | ||
| 96 | + id: `C${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 97 | + activity_id: activityId, | ||
| 98 | + user_id: currentUser.value.id, | ||
| 99 | + registration_id: registrationId, | ||
| 100 | + checkin_time: new Date().toISOString().replace('T', ' ').substring(0, 19), | ||
| 101 | + checkin_type: method, | ||
| 102 | + status: 'successful', | ||
| 103 | + is_late: false | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + return { success: true, checkin: checkinData } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + // 获取用户消息 | ||
| 110 | + const getUserMessages = computed(() => { | ||
| 111 | + return () => currentUser.value ? userMessages.value.filter(msg => msg.recipient_id === currentUser.value.id) : [] | ||
| 112 | + }) | ||
| 113 | + | ||
| 114 | + // 切换消息已读状态 | ||
| 115 | + function toggleMessageReadStatus(messageId) { | ||
| 116 | + userMessages.value = userMessages.value.map(msg => | ||
| 117 | + msg.id === messageId | ||
| 118 | + ? { ...msg, read_status: !msg.read_status } | ||
| 119 | + : msg | ||
| 120 | + ) | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + return { | ||
| 124 | + currentUser, | ||
| 125 | + activities, | ||
| 126 | + loading, | ||
| 127 | + error, | ||
| 128 | + registrations, | ||
| 129 | + userMessages, | ||
| 130 | + fetchInitialData, | ||
| 131 | + getActivityById, | ||
| 132 | + getUserRegistrations, | ||
| 133 | + registerForActivity, | ||
| 134 | + createActivity, | ||
| 135 | + checkInForActivity, | ||
| 136 | + getUserMessages, | ||
| 137 | + toggleMessageReadStatus | ||
| 138 | + } | ||
| 139 | +}) |
src/utils/api.js
0 → 100644
| 1 | +// Mock API functions to fetch data from JSON files | ||
| 2 | + | ||
| 3 | +// Fetch activities from mock data | ||
| 4 | +export const fetchActivities = async () => { | ||
| 5 | + try { | ||
| 6 | + const response = await fetch('/data/activities.json'); | ||
| 7 | + if (!response.ok) throw new Error('Failed to fetch activities'); | ||
| 8 | + const data = await response.json(); | ||
| 9 | + return data; | ||
| 10 | + } catch (error) { | ||
| 11 | + console.error('Error fetching activities:', error); | ||
| 12 | + throw error; | ||
| 13 | + } | ||
| 14 | +}; | ||
| 15 | + | ||
| 16 | +// Fetch a single activity by ID | ||
| 17 | +export const fetchActivityById = async (activityId) => { | ||
| 18 | + try { | ||
| 19 | + const response = await fetch('/data/activities.json'); | ||
| 20 | + if (!response.ok) throw new Error('Failed to fetch activity'); | ||
| 21 | + const activities = await response.json(); | ||
| 22 | + const activity = activities.find(act => act.id === activityId); | ||
| 23 | + | ||
| 24 | + if (!activity) throw new Error('Activity not found'); | ||
| 25 | + return activity; | ||
| 26 | + } catch (error) { | ||
| 27 | + console.error(`Error fetching activity ${activityId}:`, error); | ||
| 28 | + throw error; | ||
| 29 | + } | ||
| 30 | +}; | ||
| 31 | + | ||
| 32 | +// Fetch users data | ||
| 33 | +export const fetchUsers = async () => { | ||
| 34 | + try { | ||
| 35 | + const response = await fetch('/data/users.json'); | ||
| 36 | + if (!response.ok) throw new Error('Failed to fetch users'); | ||
| 37 | + const data = await response.json(); | ||
| 38 | + return data; | ||
| 39 | + } catch (error) { | ||
| 40 | + console.error('Error fetching users:', error); | ||
| 41 | + throw error; | ||
| 42 | + } | ||
| 43 | +}; | ||
| 44 | + | ||
| 45 | +// Fetch a single user by ID | ||
| 46 | +export const fetchUserById = async (userId) => { | ||
| 47 | + try { | ||
| 48 | + const response = await fetch('/data/users.json'); | ||
| 49 | + if (!response.ok) throw new Error('Failed to fetch user'); | ||
| 50 | + const users = await response.json(); | ||
| 51 | + const user = users.find(u => u.id === userId); | ||
| 52 | + | ||
| 53 | + if (!user) throw new Error('User not found'); | ||
| 54 | + return user; | ||
| 55 | + } catch (error) { | ||
| 56 | + console.error(`Error fetching user ${userId}:`, error); | ||
| 57 | + throw error; | ||
| 58 | + } | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +// Fetch registrations data | ||
| 62 | +export const fetchRegistrations = async (activityId = null, userId = null) => { | ||
| 63 | + try { | ||
| 64 | + const response = await fetch('/data/registrations.json'); | ||
| 65 | + if (!response.ok) throw new Error('Failed to fetch registrations'); | ||
| 66 | + let registrations = await response.json(); | ||
| 67 | + | ||
| 68 | + // Filter by activity ID if provided | ||
| 69 | + if (activityId) { | ||
| 70 | + registrations = registrations.filter(reg => reg.activity_id === activityId); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + // Filter by user ID if provided | ||
| 74 | + if (userId) { | ||
| 75 | + registrations = registrations.filter(reg => reg.user_id === userId); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + return registrations; | ||
| 79 | + } catch (error) { | ||
| 80 | + console.error('Error fetching registrations:', error); | ||
| 81 | + throw error; | ||
| 82 | + } | ||
| 83 | +}; | ||
| 84 | + | ||
| 85 | +// Fetch check-in data | ||
| 86 | +export const fetchCheckins = async (activityId = null, userId = null) => { | ||
| 87 | + try { | ||
| 88 | + const response = await fetch('/data/checkins.json'); | ||
| 89 | + if (!response.ok) throw new Error('Failed to fetch check-ins'); | ||
| 90 | + let checkins = await response.json(); | ||
| 91 | + | ||
| 92 | + // Filter by activity ID if provided | ||
| 93 | + if (activityId) { | ||
| 94 | + checkins = checkins.filter(check => check.activity_id === activityId); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + // Filter by user ID if provided | ||
| 98 | + if (userId) { | ||
| 99 | + checkins = checkins.filter(check => check.user_id === userId); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + return checkins; | ||
| 103 | + } catch (error) { | ||
| 104 | + console.error('Error fetching check-ins:', error); | ||
| 105 | + throw error; | ||
| 106 | + } | ||
| 107 | +}; | ||
| 108 | + | ||
| 109 | +// Fetch messages data | ||
| 110 | +export const fetchMessages = async (recipientId = null) => { | ||
| 111 | + try { | ||
| 112 | + const response = await fetch('/data/messages.json'); | ||
| 113 | + if (!response.ok) throw new Error('Failed to fetch messages'); | ||
| 114 | + let messages = await response.json(); | ||
| 115 | + | ||
| 116 | + // Filter by recipient ID if provided | ||
| 117 | + if (recipientId) { | ||
| 118 | + messages = messages.filter(msg => msg.recipient_id === recipientId); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + return messages; | ||
| 122 | + } catch (error) { | ||
| 123 | + console.error('Error fetching messages:', error); | ||
| 124 | + throw error; | ||
| 125 | + } | ||
| 126 | +}; | ||
| 127 | + | ||
| 128 | +// Mock function for creating an activity (would be an API POST in a real app) | ||
| 129 | +export const createActivity = async (activityData) => { | ||
| 130 | + // In a real app, this would send a POST request | ||
| 131 | + console.log('Creating activity with data:', activityData); | ||
| 132 | + return { | ||
| 133 | + success: true, | ||
| 134 | + id: `A${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 135 | + ...activityData | ||
| 136 | + }; | ||
| 137 | +}; | ||
| 138 | + | ||
| 139 | +// Mock function for registering to an activity | ||
| 140 | +export const registerForActivity = async (activityId, userData) => { | ||
| 141 | + // In a real app, this would send a POST request | ||
| 142 | + console.log(`Registering for activity ${activityId} with data:`, userData); | ||
| 143 | + return { | ||
| 144 | + success: true, | ||
| 145 | + id: `R${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 146 | + activity_id: activityId, | ||
| 147 | + ...userData | ||
| 148 | + }; | ||
| 149 | +}; | ||
| 150 | + | ||
| 151 | +// Mock function for checking in to an activity | ||
| 152 | +export const checkInForActivity = async (registrationId, checkinData) => { | ||
| 153 | + // In a real app, this would send a POST request | ||
| 154 | + console.log(`Checking in for registration ${registrationId} with data:`, checkinData); | ||
| 155 | + return { | ||
| 156 | + success: true, | ||
| 157 | + id: `C${Math.floor(Math.random() * 10000).toString().padStart(4, '0')}`, | ||
| 158 | + registration_id: registrationId, | ||
| 159 | + ...checkinData | ||
| 160 | + }; | ||
| 161 | +}; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
tailwind.config.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-04-16 22:22:18 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 14:09:27 | ||
| 5 | + * @FilePath: /reading-club-app/tailwind.config.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +/** @type {import('tailwindcss').Config} */ | ||
| 9 | +export default { | ||
| 10 | + content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], | ||
| 11 | + theme: { | ||
| 12 | + extend: { | ||
| 13 | + colors: { | ||
| 14 | + primary: '#4caf50', | ||
| 15 | + secondary: '#2196f3', | ||
| 16 | + 'background-start': '#f0f9ef', | ||
| 17 | + 'background-end': '#e6f4ff', | ||
| 18 | + 'text-base': '#333333', | ||
| 19 | + 'text-light': '#6e6e6e' | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + }, | ||
| 23 | + plugins: [], | ||
| 24 | +}; |
template_config.json
0 → 100644
| 1 | +{ | ||
| 2 | + "description": " - This is a template for general web app, game, common application,client,tool,component development. It is based on React framework with Tailwind CSS. The template includes the basic structure of a React project, including an index.html file and a src directory with an App.jsx file.\n - Modify index.html to change web title, create new jsx files under src if needed, and rewrite src/App.jsx to meet the user's requirements. You should NOT modify src/main.jsx and src/index.css. Modify vite.config.js only if extra config is absolutely necessary.\n - Style your elements with Tailwind CSS classes directly in the jsx files.\n - If the user's requirements do not specify a technology stack, development language, development tools, components, etc., this template will be used by default. For example, developing an XXX application, XXX client, etc. all use this template.", | ||
| 3 | + "required_fields": [], | ||
| 4 | + "required_files": [ | ||
| 5 | + "index.html", | ||
| 6 | + "src/main.jsx", | ||
| 7 | + "src/App.jsx", | ||
| 8 | + "src/index.css", | ||
| 9 | + "vite.config.js" | ||
| 10 | + ], | ||
| 11 | + "lang": "JavaScript", | ||
| 12 | + "framework": "React", | ||
| 13 | + "style": "react_template", | ||
| 14 | + "scene": "default_web_project" | ||
| 15 | +} |
vite.config.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-04-16 22:22:18 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-04-17 14:11:13 | ||
| 5 | + * @FilePath: /reading-club-app/vite.config.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import { defineConfig } from 'vite' | ||
| 9 | +import vue from '@vitejs/plugin-vue' | ||
| 10 | +import vueJsx from '@vitejs/plugin-vue-jsx' | ||
| 11 | + | ||
| 12 | +// https://vitejs.dev/config/ | ||
| 13 | +export default defineConfig({ | ||
| 14 | + plugins: [ | ||
| 15 | + vue(), | ||
| 16 | + vueJsx(), | ||
| 17 | + ], | ||
| 18 | +}) |
-
Please register or login to post a comment