├── src ├── pages │ ├── Blog │ │ ├── blog.less │ │ ├── Detail │ │ │ ├── detail.less │ │ │ └── index.tsx │ │ ├── Lists │ │ │ ├── lists.less │ │ │ └── index.tsx │ │ ├── action.ts │ │ └── index.tsx │ ├── Music │ │ ├── Sheet │ │ │ ├── sheet.less │ │ │ └── index.tsx │ │ ├── index.tsx │ │ ├── Search │ │ │ ├── search.less │ │ │ └── index.tsx │ │ ├── Rank │ │ │ ├── rank.less │ │ │ └── index.tsx │ │ ├── SheetDetail │ │ │ ├── sheet-detail.less │ │ │ └── index.tsx │ │ └── action.ts │ ├── InterLink │ │ ├── action.ts │ │ ├── inter-link.less │ │ └── index.tsx │ ├── Home │ │ ├── home.less │ │ └── index.tsx │ └── Setting │ │ ├── setting.less │ │ └── index.tsx ├── style │ ├── common │ │ ├── base.less │ │ ├── README.md │ │ ├── _utils.less │ │ └── _mixin.less │ ├── common.less │ ├── index.less │ ├── type-writer.less │ ├── reset.less │ ├── val.less │ ├── high-custom.less │ ├── main.less │ ├── transition.less │ └── high-default.less ├── config │ ├── storage.ts │ ├── color.ts │ ├── nav.ts │ ├── constance.ts │ └── music.ts ├── assets │ ├── favicon │ │ └── favicon.ico │ └── svg │ │ ├── index.ts │ │ ├── pause.svg │ │ ├── play.svg │ │ ├── menu.svg │ │ ├── creat.svg │ │ ├── next.svg │ │ ├── close.svg │ │ ├── read.svg │ │ ├── cat.svg │ │ ├── tag.svg │ │ └── logo.svg ├── components │ ├── MusicListGroup │ │ ├── music-list-group.less │ │ └── index.tsx │ ├── Icon │ │ ├── icon.less │ │ └── index.tsx │ ├── Loading │ │ ├── loading.less │ │ └── index.tsx │ ├── Generic │ │ ├── generic.less │ │ └── index.tsx │ ├── SheetGroup │ │ ├── sheet-group.less │ │ └── index.tsx │ ├── LoadingTips │ │ ├── loading-tips.less │ │ └── index.tsx │ ├── Notice │ │ ├── message.less │ │ ├── Notice.tsx │ │ ├── index.ts │ │ ├── notice.less │ │ └── Message.tsx │ ├── LazyImg │ │ ├── lazy-img.less │ │ └── index.tsx │ ├── CopyRight │ │ ├── copy-right.less │ │ └── index.tsx │ ├── MenuBar │ │ ├── menu-bar.less │ │ └── index.tsx │ ├── SheetList │ │ ├── sheet-list.less │ │ └── index.tsx │ ├── Switch │ │ ├── switch.less │ │ └── index.tsx │ ├── BlogList │ │ ├── blog-list.less │ │ └── index.tsx │ ├── SiderWarp │ │ ├── sider-warp.less │ │ └── index.tsx │ ├── Nav │ │ ├── index.tsx │ │ └── nav.less │ ├── Lyric │ │ ├── lyric.less │ │ └── index.tsx │ ├── MusicList │ │ ├── music-list.less │ │ └── index.tsx │ ├── Dialog │ │ └── index.tsx │ └── DAudio │ │ ├── d-audio.less │ │ └── index.tsx ├── use │ ├── useNavType │ │ └── index.ts │ ├── useScroll │ │ └── index.ts │ └── useLoadingTips │ │ └── index.ts ├── enum.ts ├── store │ ├── index.ts │ ├── models │ │ ├── color.ts │ │ ├── nav.ts │ │ └── music.ts │ └── types.ts ├── app.tsx ├── type.ts ├── utils │ ├── use.ts │ ├── event.ts │ ├── typewriter.ts │ ├── utils.ts │ ├── fetch.ts │ └── music.ts ├── index.tsx ├── Main.tsx ├── api │ └── api.ts └── loadable.ts ├── README.md ├── global.d.ts ├── url ├── .gitignore ├── .babelrc ├── tsconfig.json ├── index.html ├── webpack.dev.js ├── package.json ├── webpack.prod.js └── webpack.common.js /src/pages/Blog/blog.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-website 2 | 第三版个人网站更新 3 | -------------------------------------------------------------------------------- /src/style/common/base.less: -------------------------------------------------------------------------------- 1 | @import "./_utils.less"; 2 | -------------------------------------------------------------------------------- /src/style/common/README.md: -------------------------------------------------------------------------------- 1 | 这里是less的通用样式,mixin,和一些方法,同scss 2 | -------------------------------------------------------------------------------- /global.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | __FIRST_IN_HOME__: boolean 3 | } 4 | -------------------------------------------------------------------------------- /src/style/common.less: -------------------------------------------------------------------------------- 1 | @import "./common/base.less"; 2 | @import "./val.less"; -------------------------------------------------------------------------------- /url: -------------------------------------------------------------------------------- 1 | [dw 2b6b230] music—— 2 | 4 files changed, 15 insertions(+), 4 deletions(-) 3 | -------------------------------------------------------------------------------- /src/config/storage.ts: -------------------------------------------------------------------------------- 1 | export const StorageKeys = { 2 | color: 'react_website_color' 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/Music/Sheet/sheet.less: -------------------------------------------------------------------------------- 1 | 2 | // .@{project-prefix}-music-sheet { 3 | // width: 4 | // } 5 | -------------------------------------------------------------------------------- /src/style/index.less: -------------------------------------------------------------------------------- 1 | 2 | @import "./reset.less"; 3 | @import "./main.less"; 4 | @import "./transition.less"; 5 | -------------------------------------------------------------------------------- /src/assets/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IFmiss/react-website/HEAD/src/assets/favicon/favicon.ico -------------------------------------------------------------------------------- /src/style/type-writer.less: -------------------------------------------------------------------------------- 1 | .type-writer-bar { 2 | display: inline-block; 3 | width: 3px; 4 | background: red; 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /src/components/MusicListGroup/music-list-group.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-music-list-group { 2 | &-transition { 3 | width: 100%; 4 | } 5 | } -------------------------------------------------------------------------------- /src/components/Icon/icon.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-comp-icon { 2 | width: 100%; 3 | height: 100%; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | line-height: 1; 8 | } -------------------------------------------------------------------------------- /src/components/Loading/loading.less: -------------------------------------------------------------------------------- 1 | .loadable-loading { 2 | width: 100%; 3 | height: 300px; 4 | margin: 0 auto; 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/svg/index.ts: -------------------------------------------------------------------------------- 1 | const requireAll = (requireContext: any) => requireContext.keys().map(requireContext) 2 | const req = require.context('./', false, /\.svg$/) 3 | requireAll(req) 4 | export default req 5 | -------------------------------------------------------------------------------- /src/use/useNavType/index.ts: -------------------------------------------------------------------------------- 1 | import store from './../../store' 2 | import { useEffect } from 'react' 3 | export default function useNavType(type: number) { 4 | useEffect(() => { 5 | store.navStore.setNavLists(type) 6 | }, []) 7 | } -------------------------------------------------------------------------------- /src/components/Generic/generic.less: -------------------------------------------------------------------------------- 1 | .generic-component { 2 | transition: color,background 0.3s; 3 | .transition-text { 4 | transition: color 0.3s; 5 | } 6 | .transition-ele { 7 | transition: color,background 0.3s; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/SheetGroup/sheet-group.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-sheet-group { 2 | margin-top: 30px; 3 | > div { 4 | display: flex; 5 | align-items: center; 6 | justify-content: flex-start; 7 | flex-wrap: wrap; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/LoadingTips/loading-tips.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-comp-loading-tips { 2 | display: none; 3 | align-items: center; 4 | justify-content: center; 5 | padding: 5px 0; 6 | &.loading-tips-active { 7 | display: flex; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/pages/InterLink/action.ts: -------------------------------------------------------------------------------- 1 | import Http from '../../utils/fetch' 2 | import API from '../../api/api' 3 | export const getLinkLists = async () => { 4 | const data = await Http.get(API.OTHER.links, { 5 | name: 'getLinks' 6 | }) 7 | return data 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/pages/Home/home.less: -------------------------------------------------------------------------------- 1 | .@{home-prefix} { 2 | span { 3 | cursor: pointer; 4 | transition: color 0.3s; 5 | &.underline { 6 | text-decoration: underline; 7 | &:hover { 8 | color: var(--text-color-active); 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/enum.ts: -------------------------------------------------------------------------------- 1 | export enum NAV_TYPE { 2 | HOME = 1, 3 | MUSIC = 2 4 | } 5 | 6 | export enum MUSIC_SHEET_TYPE { 7 | LANGUAGES, 8 | STYLES, 9 | SCENCE, 10 | EMOTION, 11 | THEME, 12 | ALL 13 | } 14 | 15 | export enum IAMGE_LOAD_STATUS { 16 | LOADING, 17 | SUCCES, 18 | ERRER 19 | } 20 | -------------------------------------------------------------------------------- /src/assets/svg/pause.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import ColorModel from './models/color' 2 | import NavModel from './models/nav' 3 | import MusicModel from './models/music' 4 | import { IStore } from './types' 5 | const store: IStore = { 6 | colorStore: new ColorModel(), 7 | navStore: new NavModel(), 8 | musicStore: new MusicModel() 9 | } 10 | export default store 11 | -------------------------------------------------------------------------------- /src/components/Notice/message.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-comp-notice-queue { 2 | position: fixed; 3 | right: 0; 4 | padding-right: 40px; 5 | top: @nav-height + 40px; 6 | width: 300px; 7 | max-height: calc(100vh - (@nav-height + 80px)); 8 | z-index: @notice-z-index; 9 | overflow: auto; 10 | &::-webkit-scrollbar { 11 | display: none; 12 | width: 0; 13 | } 14 | } -------------------------------------------------------------------------------- /src/components/LazyImg/lazy-img.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-comp-lazy-img { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | width: 100%; 6 | height: 100%; 7 | .tips { 8 | display: flex; 9 | align-items: center; 10 | justify-content: center; 11 | font-size: 12px; 12 | height: 100%; 13 | width: 100%; 14 | border-bottom: 1px solid var(--border-color) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/store/models/color.ts: -------------------------------------------------------------------------------- 1 | import { observable, computed, action } from 'mobx' 2 | 3 | import { getNewSelfColor } from './../../config/color' 4 | export default class ColorModel { 5 | @observable 6 | mode: string = 'light' 7 | 8 | @action 9 | changeMode (mode?: string) { 10 | if (mode) { 11 | this.mode = mode 12 | return 13 | } 14 | this.mode = this.mode === 'light' ? 'dark' : 'light' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Route, Switch } from 'react-router' 3 | import { BrowserRouter } from 'react-router-dom' 4 | import store from './store' 5 | import { storeContext } from './utils/use' 6 | import Main from './Main' 7 | 8 | const App = () => { 9 | return ( 10 | 11 | 12 |
13 | 14 | 15 | ) 16 | } 17 | 18 | export default App 19 | -------------------------------------------------------------------------------- /src/assets/svg/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Loading/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './loading.less'; 3 | 4 | interface ILoadingProps { 5 | tip?: string 6 | isLoading: boolean; 7 | pastDelay: boolean; 8 | timedOut: boolean; 9 | error: any; 10 | retry: () => void; 11 | } 12 | 13 | const Loading = (props: ILoadingProps) => { 14 | return ( 15 |
16 | { props.tip } 17 |
18 | ) 19 | } 20 | 21 | Loading.defaultPorps = { 22 | tip: 'loading ...' 23 | } 24 | 25 | export default Loading 26 | -------------------------------------------------------------------------------- /src/store/models/nav.ts: -------------------------------------------------------------------------------- 1 | import { get, set, observable, values, computed, action } from 'mobx' 2 | import { INavLists, HomeNav, MusicNav } from './../../config/nav' 3 | import { NAV_TYPE } from './../../enum' 4 | export default class ColorModel { 5 | @observable 6 | lists: INavLists = HomeNav 7 | 8 | @action.bound 9 | setNavLists (type: NAV_TYPE) { 10 | switch (type) { 11 | case NAV_TYPE.MUSIC: 12 | this.lists = MusicNav 13 | break; 14 | default: 15 | this.lists = HomeNav 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/CopyRight/copy-right.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-comp-copy-right { 2 | position: fixed; 3 | right: 0; 4 | bottom: 0; 5 | width: auto; 6 | display: inline-block; 7 | font-size: 14px; 8 | padding: 6px 10px; 9 | font-weight: 200; 10 | cursor: default; 11 | .list { 12 | opacity: 0.3; 13 | margin: 0 5px; 14 | } 15 | &-info, .split { 16 | .mixinTextColor(); 17 | } 18 | a { 19 | &:hover { 20 | opacity: 0.6; 21 | color: var(--primary-color); 22 | text-decoration: underline; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/pages/Blog/Detail/detail.less: -------------------------------------------------------------------------------- 1 | .@{blog-prefix}-detail { 2 | padding: 0 0 40px 0; 3 | &-entry { 4 | margin-top: 50px; 5 | padding: 10px 0; 6 | display: flex; 7 | align-items: center; 8 | justify-content: space-between; 9 | &-prev, &-next { 10 | flex: 1; 11 | overflow: hidden; 12 | text-overflow: ellipsis; 13 | white-space: nowrap; 14 | } 15 | &-prev { 16 | margin-right: 20px!important; 17 | } 18 | &-next { 19 | margin-left: 20px!important; 20 | text-align: right; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/type.ts: -------------------------------------------------------------------------------- 1 | export type SheetGroupLists = SheetGroupList[] | any 2 | export interface SheetGroupList { 3 | 4 | } 5 | 6 | export type artists = artist[] 7 | export interface artist { 8 | id: number; 9 | img1v1Url: string; 10 | name: string; 11 | picId: number; 12 | } 13 | 14 | export type MusicGroupLists = MusicGroupList[] 15 | export interface MusicGroupList { 16 | album: any; 17 | alias: any[]; 18 | artists: artists; 19 | duration: number; 20 | id: number; 21 | name: string; 22 | status: number; 23 | rtype: number; 24 | fee: number; 25 | ftype: number; 26 | } 27 | -------------------------------------------------------------------------------- /src/pages/InterLink/inter-link.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-interlink { 2 | position: relative; 3 | & > div { 4 | display: flex; 5 | align-items: flex-start; 6 | justify-content: flex-start; 7 | flex-wrap: wrap; 8 | } 9 | .list { 10 | width: auto; 11 | padding: 30px 40px; 12 | box-sizing: border-box; 13 | overflow: hidden; 14 | text-overflow: ellipsis; 15 | white-space: nowrap; 16 | &-href { 17 | &:hover { 18 | opacity: 0.6; 19 | color: var(--primary-color); 20 | text-decoration: underline; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/assets/svg/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/svg/creat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/use.ts: -------------------------------------------------------------------------------- 1 | import { useContext, useState } from 'react' 2 | import { MUSIC_SHEET_TRANSITION_DURATION } from './../config/constance' 3 | import React, { useEffect, useLayoutEffect } from 'react' 4 | import store from './../store' 5 | 6 | // react context 7 | export const storeContext = React.createContext(store); 8 | 9 | // store数据 10 | export const useStore = () => { 11 | const store = useContext(storeContext) 12 | return store; 13 | } 14 | 15 | export function useUpdate () { 16 | const [isUpdate, setIsUpdate] = useState(false) 17 | useEffect(() => { 18 | }, [isUpdate]) 19 | 20 | setIsUpdate((isUpdate) => !isUpdate) 21 | } 22 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "modules": "false" 5 | }], 6 | ["@babel/preset-react"] 7 | ], 8 | "compact": false, 9 | "plugins":[ 10 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 11 | ["@babel/plugin-syntax-dynamic-import"], 12 | ["@babel/plugin-proposal-class-properties", { "loose" : true }], 13 | [ 14 | "@babel/plugin-transform-runtime", 15 | { 16 | "absoluteRuntime": false, 17 | "corejs": false, 18 | "helpers": true, 19 | "regenerator": true, 20 | "useESModules": false 21 | } 22 | ] 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "experimentalDecorators": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "preserve" 22 | }, 23 | "include": [ 24 | "src", 25 | "global.d.ts" 26 | ] 27 | } -------------------------------------------------------------------------------- /src/assets/svg/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/svg/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/LoadingTips/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classNames from 'classnames' 3 | import { PROJECT_NAME } from '../../config/constance'; 4 | import './loading-tips.less' 5 | 6 | interface ILoadingTips { 7 | show?: boolean; 8 | text?: string; 9 | } 10 | 11 | const LoadingTips = (props: ILoadingTips) => { 12 | const classString = classNames({ 13 | [`${PROJECT_NAME}-comp-loading-tips`]: true, 14 | ['loading-tips-active']: props.show 15 | }) 16 | return ( 17 |
18 | {props.text} 19 |
20 | ) 21 | } 22 | 23 | LoadingTips.defaultProps = { 24 | show: false, 25 | text: '加载中...' 26 | } 27 | 28 | export default LoadingTips 29 | -------------------------------------------------------------------------------- /src/utils/event.ts: -------------------------------------------------------------------------------- 1 | import { TITLE, TITLE_ENTRY, TITLE_OUT } from './../config/constance' 2 | class EventClass { 3 | private t: any = null 4 | public addVisiblityChange () { 5 | const self = this 6 | // visibilitychange 7 | const onVisibilityChange = function () { 8 | clearTimeout(self.t) 9 | if (!document['hidden']) { 10 | document.title = TITLE_ENTRY 11 | self.t = setTimeout(() => { 12 | document.title = TITLE 13 | }, 3000) 14 | } else { 15 | document.title = TITLE_OUT 16 | } 17 | } 18 | document.addEventListener('visibilitychange', onVisibilityChange) 19 | } 20 | } 21 | 22 | const selfEvent = new EventClass() 23 | export default selfEvent 24 | -------------------------------------------------------------------------------- /src/config/color.ts: -------------------------------------------------------------------------------- 1 | import { StorageKeys } from './storage' 2 | 3 | export interface IColorInfo { 4 | primaryColor: string 5 | } 6 | 7 | export const selfColor: IColorInfo = { 8 | primaryColor: 'blue' 9 | } 10 | 11 | export const getNewSelfColor = (): any => { 12 | const colorStorage = localStorage.getItem(StorageKeys.color) 13 | if (colorStorage) { 14 | return localStorage.getItem(JSON.parse(StorageKeys.color)) 15 | } 16 | return selfColor 17 | } 18 | 19 | export const setNewSelfColor = (data: any) => { 20 | // const colorStorage = localStorage.getItem(StorageKeys.color) 21 | // if (colorStorage) { 22 | // return localStorage.getItem(JSON.parse(StorageKeys.color)) 23 | // } 24 | // return defaultColor 25 | } 26 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './app' 4 | import './style/index.less' 5 | import { initPageMode, initDAudiConfig } from './utils/utils' 6 | import selfEvent from './utils/event' 7 | import './assets/svg' 8 | import PF from 'd-utils/lib/performanceUtils' 9 | import LogUtils from 'd-utils/lib/logUtils' 10 | import { CONSOLE_TEXT, CONSOLE_BGS } from './config/constance' 11 | 12 | PF.logger() 13 | LogUtils.logBeauty(CONSOLE_TEXT, { 14 | isMax: true, 15 | colors: CONSOLE_BGS 16 | }) 17 | 18 | selfEvent.addVisiblityChange() 19 | initDAudiConfig() 20 | 21 | ReactDOM.render( 22 |
23 | 24 |
, 25 | document.getElementById('react-website') 26 | ) 27 | -------------------------------------------------------------------------------- /src/components/Generic/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './generic.less' 3 | import { IColorInfo } from './../../config/color' 4 | import { NameSpaceStore } from './../../store/types' 5 | import { IStore } from './../../store/types' 6 | import { PROJECT_NAME } from './../../config/constance' 7 | 8 | export interface GenericProps { 9 | className?: string; 10 | store?: IStore; 11 | color?: NameSpaceStore.IColorModel; 12 | prefixClass?: string; 13 | } 14 | 15 | export interface GenericState {} 16 | 17 | export default class GenericComponent extends React.Component { 18 | // props: P & GenericProps; 19 | // state: S & GenericState; 20 | 21 | static defaultProps = { 22 | prefixClass: PROJECT_NAME, 23 | className: `generic-component ${PROJECT_NAME}` 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/use/useScroll/index.ts: -------------------------------------------------------------------------------- 1 | import { debounce } from 'd-utils/lib/genericUtils' 2 | import { useEffect } from 'react' 3 | 4 | /** 5 | * 滚动监听 6 | * @param ref 7 | * @param requestCallBack 8 | */ 9 | export default function useScroll (ref: any, requestCallBack: () => void, t: number = 3000) { 10 | if (!ref) return 11 | const eventHandler = (e: any) => { 12 | const newRef = ref.current ? ref.current : ref 13 | if (newRef.clientHeight + newRef.scrollTop === newRef.scrollHeight) { 14 | callBack() 15 | } 16 | } 17 | 18 | const callBack = debounce(requestCallBack, t) 19 | 20 | useEffect(() => { 21 | const newRef = ref.current ? ref.current : ref 22 | newRef.addEventListener('scroll', eventHandler) 23 | 24 | return () => { 25 | newRef.removeEventListener('scroll', eventHandler) 26 | } 27 | }, []) 28 | } 29 | -------------------------------------------------------------------------------- /src/pages/Blog/Lists/lists.less: -------------------------------------------------------------------------------- 1 | .@{blog-prefix}-lists-info { 2 | .list-contariner { 3 | padding: 20px 0 40px 0; 4 | } 5 | .sider-title { 6 | margin: 0; 7 | padding: 10px 0; 8 | font-size: 14px; 9 | } 10 | .sider-lists { 11 | padding: 5px 0; 12 | span { 13 | display: inline-block; 14 | font-size: 12px; 15 | padding: 2px 10px; 16 | color: var(--text-color); 17 | border: 1px solid var(--text-color); 18 | border-radius: 1em; 19 | margin-left: 10px; 20 | margin-bottom: 15px; 21 | cursor: pointer; 22 | transition: all 0.3s; 23 | &:hover { 24 | color: var(--text-color-active); 25 | border: 1px solid var(--text-color-active); 26 | } 27 | &.active { 28 | color: var(--primary-color); 29 | border: 1px solid var(--primary-color); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/style/common/_utils.less: -------------------------------------------------------------------------------- 1 | @import "./_mixin.less"; 2 | // 浮动 3 | .right{ 4 | float: right; 5 | } 6 | 7 | .left{ 8 | float: left; 9 | } 10 | 11 | .center{ 12 | margin: 0 auto; 13 | float: none; 14 | } 15 | 16 | // 清除浮动 17 | .clear-both{ 18 | clear: both; 19 | height:1px; 20 | margin-top:-1px; 21 | overflow:hidden; 22 | &:before{ 23 | display:none; 24 | } 25 | &:after{ 26 | display:none; 27 | } 28 | } 29 | 30 | .block_area{ 31 | margin: 0 auto; 32 | position: relative; 33 | font-size: 14px; 34 | } 35 | 36 | // inline-block对齐 或者文本对齐 37 | .text-left{ 38 | text-align:left; 39 | } 40 | 41 | .text-right{ 42 | text-align:right; 43 | } 44 | 45 | .text-center{ 46 | text-align:center; 47 | } 48 | 49 | .text-bold{ 50 | font-weight:bold; 51 | } 52 | 53 | .activeB{ 54 | display: block; 55 | } 56 | 57 | .activeF{ 58 | display: flex; 59 | } 60 | 61 | .activeN{ 62 | display:none; 63 | } 64 | -------------------------------------------------------------------------------- /src/pages/Blog/action.ts: -------------------------------------------------------------------------------- 1 | // blog 的相关操作 2 | import { 3 | BLOG_LIST_DEFAULT_LIMIT 4 | } from './../../config/constance' 5 | import Http from './../../utils/fetch' 6 | import API from './../../api/api' 7 | 8 | export const getBlogLists = async (offset: number, tagName: string = '全部', limit: number = BLOG_LIST_DEFAULT_LIMIT): Promise => { 9 | return await Http.post(API.BLOG.list, { 10 | tagName, 11 | offset, 12 | limit, 13 | }) 14 | } 15 | 16 | export const getBolgTags = async () => { 17 | return await Http.get(API.BLOG.tags, { 18 | name: 'getArticleTags' 19 | }) 20 | } 21 | 22 | export const getBlogDetail = async (id: number | string): Promise => { 23 | return await Http.post(API.BLOG.detail, { 24 | id 25 | }) 26 | } 27 | 28 | export const pv = async (id: number | string): Promise => { 29 | return await Http.post(API.BLOG.pv, { 30 | id 31 | }) 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/pages/Blog/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import classNames from 'classnames' 3 | import { PROJECT_NAME } from './../../config/constance' 4 | import { Route, Switch, Redirect } from 'react-router-dom' 5 | import { BlogLists, BlogDetail } from './../../loadable'; 6 | import store from './../../store' 7 | 8 | interface IBlogProps {} 9 | 10 | const Blog: React.FC = (props: IBlogProps) => { 11 | const classString = classNames({ 12 | [`${PROJECT_NAME}-blog`]: true, 13 | [`dw-page-router`]: true 14 | }) 15 | 16 | store.navStore.setNavLists(1) 17 | 18 | return ( 19 |
20 | {/* this is Blog */} 21 | 22 | 23 | 24 | 25 | 26 |
27 | ) 28 | } 29 | 30 | export default Blog -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 未曾遗忘的青春 | web前端_技术分享_戴伟的个人网站 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | const path = require('path'); 4 | const resolve = function (dir) { 5 | return path.resolve(__dirname, dir); 6 | } 7 | module.exports = merge(common, { 8 | mode: 'development', 9 | entry: { 10 | app: './src/index.tsx' 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.(js|jsx)$/, 16 | loader: 'babel-loader' 17 | }, 18 | ] 19 | }, 20 | output: { 21 | path: resolve('dist'), 22 | publicPath: '/', 23 | filename: 'js/[name]-[hash].js' 24 | }, 25 | devtool: 'inline-source-map', 26 | devServer: { 27 | // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html。通过传入以下启用: 28 | // contentBase: "./", 29 | host: '0.0.0.0', 30 | // 端口号 31 | port: 2005, 32 | //当有编译器错误或警告时,在浏览器中显示全屏覆盖。默认禁用。如果您只想显示编译器错误: 33 | noInfo: true, 34 | // 配置端口号 35 | overlay: true, 36 | historyApiFallback: true 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /src/pages/Setting/setting.less: -------------------------------------------------------------------------------- 1 | .@{setting-prefix} { 2 | &-title { 3 | // font-weight: 400; 4 | .mixinTextColorActive(); 5 | transition: color 0.3s; 6 | } 7 | &-wrap-title { 8 | font-weight: 500; 9 | position: relative; 10 | text-indent: 10px; 11 | margin: 20px auto 15px auto; 12 | &::before { 13 | content: ''; 14 | position: absolute; 15 | top: 50%; 16 | left: 0; 17 | transform: translate(0, -50%); 18 | width: 3px; 19 | height: 18px; 20 | border-radius: 2px; 21 | .mixinPrimaryBg(); 22 | transition: background-color 0.3s; 23 | } 24 | } 25 | &-wrap-content { 26 | padding: 0 0 0 20px; 27 | margin: 10px auto; 28 | &-list { 29 | list-style: none; 30 | display: flex; 31 | align-items: center; 32 | justify-content: space-between; 33 | padding: 10px 0; 34 | font-size: 14px; 35 | border-bottom: 1px solid var(--border-color); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/components/MenuBar/menu-bar.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-menu-bar { 2 | &-main, &-cat { 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | margin: 6px auto; 7 | &-list { 8 | margin: 0 8px; 9 | padding: 10px 5px; 10 | cursor: pointer; 11 | font-size: 14px; 12 | font-weight: 500; 13 | .mixinTextColor(); 14 | position: relative; 15 | transition: color 0.3s; 16 | &.active { 17 | .mixinTextColorActive(); 18 | &::before { 19 | width: 50%; 20 | transform: translate(-50%, 0); 21 | } 22 | } 23 | &::before { 24 | content: ''; 25 | position: absolute; 26 | background: var(--primary-color); 27 | bottom: 5px; 28 | left: 50%; 29 | width: 0; 30 | height: 2px; 31 | border-radius: 4px; 32 | transition: all 0.3s; 33 | transform: translate(-50%, 400%); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/components/SheetList/sheet-list.less: -------------------------------------------------------------------------------- 1 | .@{project-prefix}-sheet-list { 2 | width: 20%; 3 | padding: 15px; 4 | box-sizing: border-box; 5 | &-content { 6 | position: relative; 7 | width: 100%; 8 | height: 100%; 9 | cursor: pointer; 10 | box-shadow: 1px 1px 24px 0 var(--shadow-color); 11 | border-radius: @raduis; 12 | &-top { 13 | width: 100%; 14 | padding-top: 100%; 15 | position: relative; 16 | .sheet-list-lazy-img { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | width: 100%; 21 | height: 100%; 22 | border-radius: @raduis @raduis 0 0; 23 | img { 24 | position: absolute; 25 | top: 0; 26 | left: 0; 27 | width: 100%; 28 | height: 100%; 29 | border: none; 30 | border-radius: @raduis @raduis 0 0; 31 | } 32 | } 33 | } 34 | &-title { 35 | margin: 0; 36 | margin: 8px; 37 | font-size: 14px; 38 | .lineclamp(44px, 2); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/use/useLoadingTips/index.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import LoadingTips from './../../components/Loading' 3 | 4 | interface IuseLoadingTips { 5 | /** 是否显示 提示信息 */ 6 | loading: boolean; 7 | 8 | /** 提示信息的文字信息 */ 9 | text: string; 10 | 11 | /** 显示LoadingTips 可以设置文字 可选 */ 12 | showLoading(text?: string): void; 13 | 14 | /** 关闭 */ 15 | hideLoading(): void; 16 | } 17 | 18 | 19 | /** 20 | * 控制显示LoadingTips的组件 21 | * 依赖于LoadingTips组件 22 | */ 23 | export default function useLoadingTips(state: boolean = false, text: string = 'loading...'): IuseLoadingTips { 24 | const [loading, setLoading] = useState(state) 25 | const [loadingText, setLoadingText] = useState(text) 26 | 27 | function showLoading (text?: string) { 28 | setLoading((loading) => loading = true) 29 | text && setLoadingText((loadingText) => loadingText = text) 30 | } 31 | 32 | function hideLoading () { 33 | setLoading((loading) => loading = false) 34 | } 35 | 36 | return { 37 | loading, 38 | text: loadingText, 39 | showLoading, 40 | hideLoading 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/pages/Music/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import classNames from 'classnames' 3 | import { PROJECT_NAME } from './../../config/constance' 4 | import { Route, Switch, Redirect } from 'react-router-dom' 5 | import { MusicSheet, MusicRank, MusicSearch, MusicSheetDetail } from './../../loadable' 6 | import useNavType from './../../use/useNavType' 7 | interface IMusicProps {} 8 | 9 | const Music: React.FC = (props: IMusicProps) => { 10 | const classString = classNames({ 11 | [`${PROJECT_NAME}-music`]: true, 12 | [`dw-page-router`]: true 13 | }) 14 | 15 | useNavType(2) 16 | 17 | return ( 18 |
19 | {/* this is Music */} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | ) 29 | } 30 | 31 | export default Music -------------------------------------------------------------------------------- /src/assets/svg/read.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/CopyRight/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { PROJECT_NAME, COPY_RIGHT_CONFIG } from './../../config/constance' 3 | import classNames from 'classnames' 4 | import { formatDate } from 'd-utils/lib/genericUtils' 5 | import './copy-right.less'; 6 | import { Link } from 'react-router-dom' 7 | 8 | const CopyRight: React.FC = () => { 9 | const classString = classNames({ 10 | [`${PROJECT_NAME}-comp-copy-right`]: true 11 | }) 12 | 13 | return ( 14 |
15 | © 2016 - { formatDate('yyyy', new Date()) } from dw 16 | | 17 | 18 | { 19 | COPY_RIGHT_CONFIG.map((item) => ( 20 | item.to.includes('http') ? ( 21 | {item.name} 22 | ) : ( 23 | {item.name} 24 | ) 25 | )) 26 | } 27 | 28 |
29 | ) 30 | } 31 | export default CopyRight 32 | -------------------------------------------------------------------------------- /src/Main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | // import { Route, Switch, Redirect } from 'react-router' 3 | import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom' 4 | import { Home, Blog, Music, Setting, InterLink } from './loadable' 5 | import Nav from './components/Nav/index' 6 | import CopyRight from './components/CopyRight' 7 | 8 | interface IMainProps { 9 | prefixClass?: string; 10 | history?: any; 11 | } 12 | 13 | interface IMainState {} 14 | 15 | const Main = (props: IMainProps) => { 16 | return ( 17 | 18 | 19 | 20 |