添加搜索框
This commit is contained in:
		
							
								
								
									
										5
									
								
								.eslintrc.js
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										5
									
								
								.eslintrc.js
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -23,5 +23,10 @@ module.exports = {
 | 
			
		||||
    camelcase: 'off',
 | 
			
		||||
    'no-unused-vars': 'warn',
 | 
			
		||||
    'no-use-before-define': 'off'
 | 
			
		||||
  },
 | 
			
		||||
  settings: {
 | 
			
		||||
    react: {
 | 
			
		||||
      version: '17.0.0'
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										13
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										13
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,4 +1,15 @@
 | 
			
		||||
{
 | 
			
		||||
  "editor.defaultFormatter": "dbaeumer.vscode-eslint",
 | 
			
		||||
  "editor.formatOnSave": true
 | 
			
		||||
  "editor.formatOnSave": true,
 | 
			
		||||
  "editor.tabSize": 2,
 | 
			
		||||
  "eslint.trace.server": "verbose",
 | 
			
		||||
  "eslint.validate": [
 | 
			
		||||
    "javascript",
 | 
			
		||||
    "javascriptreact",
 | 
			
		||||
    "typescript",
 | 
			
		||||
    "typescriptreact",
 | 
			
		||||
    "html",
 | 
			
		||||
    "vue",
 | 
			
		||||
  ],
 | 
			
		||||
  "eslint.format.enable": true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								index.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								index.html
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								package.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								package.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/App.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/App.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/App.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/App.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/api/api.d.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/api/api.d.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/api/repository.ts
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/api/repository.ts
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/components/RepositoryItem.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/components/RepositoryItem.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										26
									
								
								src/components/RepositoryList.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										26
									
								
								src/components/RepositoryList.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,9 +1,11 @@
 | 
			
		||||
import React, { useEffect, useState } from 'react'
 | 
			
		||||
import React, { useEffect, useState, useContext } from 'react'
 | 
			
		||||
import { search as SearchRepository } from '../api/repository'
 | 
			
		||||
import RepopositoryItem from './RepositoryItem'
 | 
			
		||||
import { RepositorySearchResultItem } from '../api/api'
 | 
			
		||||
import classes from './style/RepositoryList.module.css'
 | 
			
		||||
import { RepositorySearchCache } from '../utils/cache/RepositorySearch'
 | 
			
		||||
import RepositorySearchInput from './RepositorySearchInput'
 | 
			
		||||
import { RepositorySearchContext } from '../context/RepositorySearchContext'
 | 
			
		||||
 | 
			
		||||
interface RepositoryListProps {
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +23,12 @@ interface RepositoryListProps {
 | 
			
		||||
const DEFAULT_PER_PAGE = 30
 | 
			
		||||
 | 
			
		||||
export default function RepositoryList (props:RepositoryListProps) {
 | 
			
		||||
  const cache = RepositorySearchCache(props.keyword, props.max_cache_page)
 | 
			
		||||
  useContext(RepositorySearchContext)
 | 
			
		||||
 | 
			
		||||
  /** 搜索关键词 */
 | 
			
		||||
  const [keyword, setKeyword] = useState(props.keyword)
 | 
			
		||||
 | 
			
		||||
  const cache = RepositorySearchCache(keyword, props.max_cache_page)
 | 
			
		||||
 | 
			
		||||
  /** 当前页 */
 | 
			
		||||
  const [current_page, setCurrentPage] = useState(1)
 | 
			
		||||
@@ -36,10 +43,11 @@ export default function RepositoryList (props:RepositoryListProps) {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 调用搜索接口
 | 
			
		||||
   * @param {string} keyword 搜索关键词
 | 
			
		||||
   * @param {number} page 页码
 | 
			
		||||
   * @returns {Promise<void>}
 | 
			
		||||
   */
 | 
			
		||||
  async function search (page:number):Promise<void> {
 | 
			
		||||
  async function search (keyword:string, page:number):Promise<void> {
 | 
			
		||||
    setLoading(true)
 | 
			
		||||
 | 
			
		||||
    const cache_list = cache.read(page)
 | 
			
		||||
@@ -54,7 +62,7 @@ export default function RepositoryList (props:RepositoryListProps) {
 | 
			
		||||
      // 没有缓存,调用接口
 | 
			
		||||
      try {
 | 
			
		||||
        /* eslint-disable */
 | 
			
		||||
        var result = await SearchRepository(props.keyword, page)
 | 
			
		||||
        var result = await SearchRepository(keyword, page)
 | 
			
		||||
        
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        console.log('fetch',err);
 | 
			
		||||
@@ -80,20 +88,23 @@ export default function RepositoryList (props:RepositoryListProps) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    search(1)
 | 
			
		||||
    search(keyword,1)
 | 
			
		||||
  }, [])
 | 
			
		||||
 | 
			
		||||
  function onClickPrev(){
 | 
			
		||||
    search(current_page-1)
 | 
			
		||||
    search(keyword,current_page-1)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function onClickNext(){
 | 
			
		||||
    search(current_page+1)
 | 
			
		||||
    search(keyword,current_page+1)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <RepositorySearchContext.Provider value={{search,setKeyword,keyword,loading}}>
 | 
			
		||||
    <div className={classes.wrapper}>
 | 
			
		||||
      <RepositorySearchInput />
 | 
			
		||||
      <div className={classes['list-wrapper']}>
 | 
			
		||||
        
 | 
			
		||||
        <ul className={classes.list}>
 | 
			
		||||
          {
 | 
			
		||||
            list.map(item => <RepopositoryItem key={item.id} name={item.name} star_count={item.stargazers_count} fork_count={item.forks_count} />)
 | 
			
		||||
@@ -114,5 +125,6 @@ export default function RepositoryList (props:RepositoryListProps) {
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    </RepositorySearchContext.Provider>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								src/components/RepositorySearchInput.tsx
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								src/components/RepositorySearchInput.tsx
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
import React, { useContext } from 'react'
 | 
			
		||||
import { RepositorySearchContext } from '../context/RepositorySearchContext'
 | 
			
		||||
 | 
			
		||||
export default function RepositorySearchInput () {
 | 
			
		||||
  const context = useContext(RepositorySearchContext)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <label htmlFor="keyword-input">
 | 
			
		||||
      搜索关键词:
 | 
			
		||||
      <input type="text" id="keyword-input"
 | 
			
		||||
        value={context.keyword}
 | 
			
		||||
        onChange={({ target }) => {
 | 
			
		||||
          context.setKeyword(target.value)
 | 
			
		||||
        }}
 | 
			
		||||
        onKeyDown={evt => {
 | 
			
		||||
          const value = (evt.target as HTMLInputElement).value
 | 
			
		||||
          if (evt.key.toLocaleLowerCase() === 'enter') {
 | 
			
		||||
            context.setKeyword(value)
 | 
			
		||||
            context.search(value, 1)
 | 
			
		||||
          }
 | 
			
		||||
        }}
 | 
			
		||||
      />
 | 
			
		||||
      </label>
 | 
			
		||||
 | 
			
		||||
      <button onClick={() => {
 | 
			
		||||
        context.search(context.keyword, 1)
 | 
			
		||||
      }} disabled={context.loading}>搜索</button>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								src/components/style/RepositoryList.module.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/components/style/RepositoryList.module.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										23
									
								
								src/context/RepositorySearchContext.ts
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										23
									
								
								src/context/RepositorySearchContext.ts
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
import React from 'react'
 | 
			
		||||
 | 
			
		||||
export const RepositorySearchContext = React.createContext({
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 调用搜索接口
 | 
			
		||||
   * @param {string} keyword 搜索关键词
 | 
			
		||||
   * @param {number} page 页码
 | 
			
		||||
   */
 | 
			
		||||
  search (keyword:string, page:number) {},
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 更新搜索关键词
 | 
			
		||||
   * @param {string} keyword 搜索关键词
 | 
			
		||||
   */
 | 
			
		||||
  setKeyword (keyword:string) {},
 | 
			
		||||
 | 
			
		||||
  /** 搜索关键词 */
 | 
			
		||||
  keyword: '',
 | 
			
		||||
 | 
			
		||||
  /** 接口调用中 */
 | 
			
		||||
  loading: false
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										0
									
								
								src/favicon.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/favicon.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| 
		 Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										0
									
								
								src/index.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/index.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/logo.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/logo.svg
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| 
		 Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB  | 
							
								
								
									
										0
									
								
								src/main.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/main.tsx
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/utils/cache/RepositorySearch.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/utils/cache/RepositorySearch.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								src/vite-env.d.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								src/vite-env.d.ts
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								tsconfig.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								tsconfig.json
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								vite.config.ts
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								vite.config.ts
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
		Reference in New Issue
	
	Block a user