diff --git a/members/Old000Driver/readme.md b/members/Old000Driver/readme.md new file mode 100644 index 000000000..ae2f61888 --- /dev/null +++ b/members/Old000Driver/readme.md @@ -0,0 +1,15 @@ +# Web3 前端训练营报名 + +## 个人信息 + +* GitHub ID:Old000Driver +* OpenBuild Username:792002710 +* ERC20 钱包地址:0x2282050684b096d36393e3d60F4bBa3f3d0cC661 + +### 个人介绍 + +`有4年前端开发经验,从事过网络安全行业和金融行业,目前已经学习并练习过 solidity、etherjs、nextjs、tailwind,以成为 web3 合格前端为目标继续补充学习` + +## 任务提交 + +`建议所有的作业结果在个人的 GitHub 下单独建立仓库放置,在此 readme 里只当相关链接或简介描述即可` diff --git a/members/Old000Driver/task1/.gitignore b/members/Old000Driver/task1/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/members/Old000Driver/task1/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/members/Old000Driver/task1/README.md b/members/Old000Driver/task1/README.md new file mode 100644 index 000000000..74872fd4a --- /dev/null +++ b/members/Old000Driver/task1/README.md @@ -0,0 +1,50 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default tseslint.config({ + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` +- Optionally add `...tseslint.configs.stylisticTypeChecked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: + +```js +// eslint.config.js +import react from 'eslint-plugin-react' + +export default tseslint.config({ + // Set the react version + settings: { react: { version: '18.3' } }, + plugins: { + // Add the react plugin + react, + }, + rules: { + // other rules... + // Enable its recommended rules + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + }, +}) +``` diff --git a/members/Old000Driver/task1/eslint.config.js b/members/Old000Driver/task1/eslint.config.js new file mode 100644 index 000000000..092408a9f --- /dev/null +++ b/members/Old000Driver/task1/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/members/Old000Driver/task1/index.html b/members/Old000Driver/task1/index.html new file mode 100644 index 000000000..480c218ca --- /dev/null +++ b/members/Old000Driver/task1/index.html @@ -0,0 +1,14 @@ + + + + + + + + Vite + React + TS + + +
+ + + diff --git a/members/Old000Driver/task1/package.json b/members/Old000Driver/task1/package.json new file mode 100644 index 000000000..3487f93ab --- /dev/null +++ b/members/Old000Driver/task1/package.json @@ -0,0 +1,29 @@ +{ + "name": "openbuildtasks", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.17.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.18.2", + "vite": "^6.0.5" + } +} diff --git a/members/Old000Driver/task1/public/vite.svg b/members/Old000Driver/task1/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/members/Old000Driver/task1/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/members/Old000Driver/task1/src/App.tsx b/members/Old000Driver/task1/src/App.tsx new file mode 100644 index 000000000..077368158 --- /dev/null +++ b/members/Old000Driver/task1/src/App.tsx @@ -0,0 +1,60 @@ +import { useState, useEffect } from "react"; +import Header from "./components/Header"; +import ToDoList from "./components/ToDoList"; +import AddToDo from "./components/AddToDo"; + +export interface Todo { + id: number; + text: string; + completed: boolean; +} + +function App() { + const [todos, setTodos] = useState(() => { + const savedTodos = localStorage.getItem("todos"); + return savedTodos ? JSON.parse(savedTodos) : []; + }); + + useEffect(() => { + localStorage.setItem("todos", JSON.stringify(todos)); + }, [todos]); + + const addTodo = (text: string) => { + if (text.trim()) { + setTodos([ + ...todos, + { + id: Date.now(), + text: text.trim(), + completed: false, + }, + ]); + } + }; + + const deleteTodo = (id: number) => { + setTodos(todos.filter((todo) => todo.id !== id)); + }; + + const toggleTodo = (id: number) => { + setTodos( + todos.map((todo) => + todo.id === id ? { ...todo, completed: !todo.completed } : todo + ) + ); + }; + + return ( +
+
+
+
+ + +
+
+
+ ); +} + +export default App; diff --git a/members/Old000Driver/task1/src/assets/react.svg b/members/Old000Driver/task1/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/members/Old000Driver/task1/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/members/Old000Driver/task1/src/components/AddToDo.tsx b/members/Old000Driver/task1/src/components/AddToDo.tsx new file mode 100644 index 000000000..cb0fb05c1 --- /dev/null +++ b/members/Old000Driver/task1/src/components/AddToDo.tsx @@ -0,0 +1,34 @@ +import React, { useState } from "react"; + +interface AddToDoProps { + onAdd: (text: string) => void; +} + +const AddToDo: React.FC = ({ onAdd }) => { + const [text, setText] = useState(""); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + onAdd(text); + setText(""); + }; + + return ( +
+
+ setText(e.target.value)} + placeholder="添加新的待办事项" + className="add-todo-input" + /> + +
+
+ ); +}; + +export default AddToDo; diff --git a/members/Old000Driver/task1/src/components/Header.tsx b/members/Old000Driver/task1/src/components/Header.tsx new file mode 100644 index 000000000..ec48b4e9b --- /dev/null +++ b/members/Old000Driver/task1/src/components/Header.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const Header: React.FC = () => { + return ( +
+

待办事项列表

+
+ ) +} + +export default Header \ No newline at end of file diff --git a/members/Old000Driver/task1/src/components/ToDoItem.tsx b/members/Old000Driver/task1/src/components/ToDoItem.tsx new file mode 100644 index 000000000..9d5959c13 --- /dev/null +++ b/members/Old000Driver/task1/src/components/ToDoItem.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import { Todo } from '../App' + +interface ToDoItemProps { + todo: Todo + onDelete: (id: number) => void + onToggle: (id: number) => void +} + +const ToDoItem: React.FC = ({ todo, onDelete, onToggle }) => { + return ( +
+
+
+ +
+ ) +} + +export default ToDoItem \ No newline at end of file diff --git a/members/Old000Driver/task1/src/components/ToDoList.tsx b/members/Old000Driver/task1/src/components/ToDoList.tsx new file mode 100644 index 000000000..339bbddea --- /dev/null +++ b/members/Old000Driver/task1/src/components/ToDoList.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import ToDoItem from "./ToDoItem"; +import { Todo } from "../App"; + +interface ToDoListProps { + todos: Todo[]; + onDelete: (id: number) => void; + onToggle: (id: number) => void; +} + +const ToDoList: React.FC = ({ todos, onDelete, onToggle }) => { + return ( +
+ {todos.map((todo) => ( + + ))} +
+ ); +}; + +export default ToDoList; diff --git a/members/Old000Driver/task1/src/index.css b/members/Old000Driver/task1/src/index.css new file mode 100644 index 000000000..9a51dc2af --- /dev/null +++ b/members/Old000Driver/task1/src/index.css @@ -0,0 +1,177 @@ +/* 基础样式 */ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* 容器样式 */ +.container { + min-height: 100vh; + background-color: white; +} + +.content { + width: auto; + margin: 0 auto; + padding: 1rem; + display: flex; + flex-direction: column; + gap: 1rem; + margin-top: 2rem; + justify-content: center; + align-items: center; +} + +/* Header 样式 */ +.header { + text-align: center; + margin-bottom: 2rem; +} + +.header h1 { + font-size: 1.875rem; + font-weight: bold; + color: #111827; +} + +/* AddToDo 样式 */ +.add-todo-form { + display: flex; + gap: 0.75rem; + margin-bottom: 1.5rem; + width: 400px; + margin-left: auto; + margin-right: auto; +} + +.add-todo-input { + flex: 1; + padding: 0.5rem 1rem; + border: 1px solid #d1d5db; + border-radius: 0.5rem; + outline: none; +} + +.add-todo-input:focus { + border-color: #3b82f6; +} + +.add-button { + min-width: 80px; + padding: 0.5rem 1.5rem; + background-color: #0ea5e9; + color: white; + font-weight: 500; + border: none; + border-radius: 0.5rem; + cursor: pointer; + transition: all 0.2s ease-in-out; +} + +.add-button:hover { + background-color: #0284c7; +} + +/* ToDoList 样式 */ +.todo-list { + width: 400px; + margin-left: auto; + margin-right: auto; +} + +.todo-list > * + * { + margin-top: 0.75rem; +} + +.todo-container { + padding: 36px; + border: 2px solid black; + width: 400px; + border-radius: 25px; + box-shadow: #111827; +} + +/* ToDoItem 样式 */ +.todo-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem; + background-color: #f9fafb; + border-radius: 0.5rem; +} + +.todo-item.completed { + opacity: 0.6; +} + +.todo-text { + cursor: pointer; + color: #111827; +} + +.todo-text.completed { + text-decoration: line-through; +} + +.delete-button { + min-width: 60px; + padding: 0.5rem 1rem; + background-color: #ef4444; + color: white; + font-weight: 500; + border: none; + border-radius: 0.5rem; + cursor: pointer; + transition: all 0.2s ease-in-out; +} + +.delete-button:hover { + background-color: #dc2626; +} + +/* 添加复选框按钮样式 */ +.toggle-button { + width: 24px; + height: 24px; + border: 2px solid #d1d5db; + border-radius: 50%; + margin-right: 12px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + background: white; + transition: all 0.2s ease-in-out; +} + +.toggle-button.completed { + background: #10b981; + border-color: #10b981; +} + +.toggle-button.completed::after { + content: "✓"; + color: white; + font-size: 14px; +} + +/* 修改 todo-item 样式 */ +.todo-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem; + background-color: #f9fafb; + border-radius: 0.5rem; +} + +.todo-left { + display: flex; + align-items: center; + flex: 1; +} diff --git a/members/Old000Driver/task1/src/main.tsx b/members/Old000Driver/task1/src/main.tsx new file mode 100644 index 000000000..bef5202a3 --- /dev/null +++ b/members/Old000Driver/task1/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/members/Old000Driver/task1/src/vite-env.d.ts b/members/Old000Driver/task1/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/members/Old000Driver/task1/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/members/Old000Driver/task1/tsconfig.app.json b/members/Old000Driver/task1/tsconfig.app.json new file mode 100644 index 000000000..358ca9ba9 --- /dev/null +++ b/members/Old000Driver/task1/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/members/Old000Driver/task1/tsconfig.json b/members/Old000Driver/task1/tsconfig.json new file mode 100644 index 000000000..1ffef600d --- /dev/null +++ b/members/Old000Driver/task1/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/members/Old000Driver/task1/tsconfig.node.json b/members/Old000Driver/task1/tsconfig.node.json new file mode 100644 index 000000000..db0becc8b --- /dev/null +++ b/members/Old000Driver/task1/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/members/Old000Driver/task1/vite.config.ts b/members/Old000Driver/task1/vite.config.ts new file mode 100644 index 000000000..0e43ae8de --- /dev/null +++ b/members/Old000Driver/task1/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +});