├── .vscode └── settings.json ├── pages ├── favicon.ico ├── _error.js ├── 3-me │ ├── 5-about.js │ ├── 3-favorite.js │ ├── 4-history.js │ ├── 6-feedback.js │ ├── 1-home.js │ └── 2-login.js ├── _document.js ├── 2-card │ ├── 2-list.js │ ├── 1-home.js │ └── 3-detail.js ├── 1-loan │ ├── 1-home.js │ ├── 3-goLoan.js │ └── 2-detail.js ├── index.js └── search.js ├── static ├── scripts │ ├── just-generate-css │ │ ├── app-min.js │ │ └── antd-mobile-min.js │ ├── hd.js │ └── local-storage.js ├── fonts │ ├── dudu.ttf │ └── dudu.woff ├── images │ ├── login.gif │ ├── me_bg.png │ ├── card_bg.png │ ├── logo_bg.png │ ├── about_bg.png │ ├── logo_head.png │ ├── logo_text.png │ ├── card_list_bg.png │ ├── loan_type_0.png │ ├── loan_type_1.png │ ├── loan_type_2.png │ ├── card_detail_bg.png │ └── loan_detail_bg.png └── styles │ ├── 488af5aa9faf725b13461ff0fd6f5cbe.png │ ├── b7c1e74437090be81397e7bd879b5fba.png │ ├── f003959aac799c2ada52c1098c138999.png │ └── common │ ├── antd-mobile.less │ ├── common.scss │ ├── antd-mobile-config │ └── config.less │ ├── base │ ├── plugin.scss │ ├── app.scss │ ├── special.scss │ ├── normalize.scss │ └── font.scss │ └── custom │ ├── animation.scss │ ├── color.scss │ ├── size.scss │ ├── other.scss │ └── layout.scss ├── .eslintignore ├── postcss.config.js ├── components ├── 0-09-Loading.js ├── 0-10-MultiColorIco.js ├── 0-08-NoDataIco.js ├── 0-07-NoData.js ├── 0-13-AlertBg.js ├── 4-01-SwitchList.js ├── 0-06-ErrorFetch.js ├── 0-15-DetailFoot.js ├── 0-04-Nav.js ├── 0-02-Btn.js ├── 0-03-ActiveLink.js ├── 1-02-Limit.js ├── 4-02-ChangeList.js ├── 1-03-LoanTypes.js ├── 1-04-SearchItem.js ├── 1-01-Message.js ├── 0-01-WrapLink.js ├── index.js ├── 0-00-Layout.js ├── 0-05-WithData.js ├── 0-16-MeProductList.js ├── 3-01-Recommend.js ├── 0-11-ProductList.js ├── 0-12-ScrollLoad.js └── 0-14-SwitchSelect.js ├── store ├── reducers │ ├── 0-01-fetchOnce.js │ ├── 1-02-hotSearch.js │ ├── 1-01-home.js │ ├── 1-03-mySearch.js │ ├── 3-01-cardsHome.js │ ├── 4-01-user.js │ ├── 2-01-loansFilter.js │ ├── 3-02-cardsFilter.js │ └── index.js ├── reduxPage.js ├── middleware │ └── api.js └── actions │ └── index.js ├── utils ├── index.js ├── 02-cache.js ├── 04-wxapi.js ├── 03-http.js └── 01-common.js ├── .editorconfig ├── .babelrc ├── .next ├── bundles │ └── pages │ │ └── _error.js ├── dist │ └── pages │ │ ├── _error.js │ │ └── _document.js ├── manifest.js └── main.js ├── next.config.js ├── .gitignore ├── webpack-handle-css.js ├── README.md ├── .eslintrc.js ├── package.json └── server.js /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /pages/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/pages/favicon.ico -------------------------------------------------------------------------------- /static/scripts/just-generate-css/app-min.js: -------------------------------------------------------------------------------- 1 | import '../../styles/common/common.scss' 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | node_modules 4 | !.eslintrc.js 5 | static 6 | outCDN 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /static/fonts/dudu.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/fonts/dudu.ttf -------------------------------------------------------------------------------- /static/fonts/dudu.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/fonts/dudu.woff -------------------------------------------------------------------------------- /static/images/login.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/login.gif -------------------------------------------------------------------------------- /static/images/me_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/me_bg.png -------------------------------------------------------------------------------- /static/images/card_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/card_bg.png -------------------------------------------------------------------------------- /static/images/logo_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/logo_bg.png -------------------------------------------------------------------------------- /static/scripts/just-generate-css/antd-mobile-min.js: -------------------------------------------------------------------------------- 1 | import '../../styles/common/antd-mobile.less' 2 | -------------------------------------------------------------------------------- /static/images/about_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/about_bg.png -------------------------------------------------------------------------------- /static/images/logo_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/logo_head.png -------------------------------------------------------------------------------- /static/images/logo_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/logo_text.png -------------------------------------------------------------------------------- /static/images/card_list_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/card_list_bg.png -------------------------------------------------------------------------------- /static/images/loan_type_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/loan_type_0.png -------------------------------------------------------------------------------- /static/images/loan_type_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/loan_type_1.png -------------------------------------------------------------------------------- /static/images/loan_type_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/loan_type_2.png -------------------------------------------------------------------------------- /static/images/card_detail_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/card_detail_bg.png -------------------------------------------------------------------------------- /static/images/loan_detail_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/images/loan_detail_bg.png -------------------------------------------------------------------------------- /static/styles/488af5aa9faf725b13461ff0fd6f5cbe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/styles/488af5aa9faf725b13461ff0fd6f5cbe.png -------------------------------------------------------------------------------- /static/styles/b7c1e74437090be81397e7bd879b5fba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/styles/b7c1e74437090be81397e7bd879b5fba.png -------------------------------------------------------------------------------- /static/styles/f003959aac799c2ada52c1098c138999.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minooo/react-ssr/HEAD/static/styles/f003959aac799c2ada52c1098c138999.png -------------------------------------------------------------------------------- /static/styles/common/antd-mobile.less: -------------------------------------------------------------------------------- 1 | @import "../../../node_modules/antd-mobile/dist/antd-mobile.less"; // 引入官方提供的 less 样式入口文件 2 | @import "./antd-mobile-config/config.less"; 3 | -------------------------------------------------------------------------------- /components/0-09-Loading.js: -------------------------------------------------------------------------------- 1 | export default ({ text }) => ( 2 |
3 |   4 | {text || '加载中...'} 5 |
6 | ) 7 | -------------------------------------------------------------------------------- /components/0-10-MultiColorIco.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid/v4' 2 | 3 | export default ({ ico, num }) => ( 4 | 5 | {Array(num).fill(1).map((item, index) => )} 6 | 7 | ) 8 | -------------------------------------------------------------------------------- /store/reducers/0-01-fetchOnce.js: -------------------------------------------------------------------------------- 1 | import { FETCH_ONCE } from '@actions' 2 | 3 | export default (state = false, action) => { 4 | switch (action.type) { 5 | case FETCH_ONCE: 6 | return true 7 | default: 8 | return state 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /store/reducers/1-02-hotSearch.js: -------------------------------------------------------------------------------- 1 | import { HOT_SEARCH } from '@actions' 2 | 3 | export default (state = [], action) => { 4 | switch (action.type) { 5 | case HOT_SEARCH: 6 | return [...(action.payload.length > 0 && action.payload)] 7 | default: 8 | return state 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /store/reducers/1-01-home.js: -------------------------------------------------------------------------------- 1 | import { HOME } from '@actions' 2 | 3 | export default (state = null, action) => { 4 | switch (action.type) { 5 | case HOME: 6 | return { 7 | ...state, 8 | ...action.payload, 9 | } 10 | default: 11 | return state 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /store/reducers/1-03-mySearch.js: -------------------------------------------------------------------------------- 1 | import { GET_MY_SEARCH } from '@actions' 2 | 3 | export default (state = [], action) => { 4 | switch (action.type) { 5 | case GET_MY_SEARCH: 6 | return [...(action.payload.length > 0 && action.payload)] 7 | default: 8 | return state 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /store/reducers/3-01-cardsHome.js: -------------------------------------------------------------------------------- 1 | import { CARDS_HOME } from '@actions' 2 | 3 | export default (state = null, action) => { 4 | switch (action.type) { 5 | case CARDS_HOME: 6 | return { 7 | ...state, 8 | ...action.payload, 9 | } 10 | default: 11 | return state 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/0-08-NoDataIco.js: -------------------------------------------------------------------------------- 1 | export default ({ text, ico }) => ( 2 |
3 | 4 | {text} 5 |
6 | ) 7 | -------------------------------------------------------------------------------- /static/styles/common/common.scss: -------------------------------------------------------------------------------- 1 | @import "./base/normalize"; 2 | @import "./base/app"; 3 | @import "./base/font"; 4 | @import "./base/plugin"; 5 | @import "./base/special"; 6 | 7 | @import "./custom/animation"; 8 | @import "./custom/color"; 9 | @import "./custom/layout"; 10 | @import "./custom/size"; 11 | @import "./custom/other"; 12 | -------------------------------------------------------------------------------- /store/reducers/4-01-user.js: -------------------------------------------------------------------------------- 1 | import { USER, LOGOUT } from '@actions' 2 | 3 | export default (state = null, action) => { 4 | switch (action.type) { 5 | case USER: 6 | return { 7 | ...state, 8 | ...action.payload, 9 | } 10 | case LOGOUT: 11 | return null 12 | default: 13 | return state 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | export { 2 | CALL_API, serializeParams, isMobile, isIOS, isAndroid, setTitle, clipPrice, getSomeFromArr, 3 | searchToObj, addDefault, imgUrl, clipBigNum, setCookie, getCookie, delCookie, getUrlLastStr, 4 | isIDNumber, isName, 5 | } from './01-common' 6 | export { default as cache } from './02-cache' 7 | export { default as http } from './03-http' 8 | export { setConfig, setShare } from './04-wxapi' 9 | -------------------------------------------------------------------------------- /components/0-07-NoData.js: -------------------------------------------------------------------------------- 1 | export default ({ text }) => ( 2 |
9 | 16 | {text || '没有更多数据了'} 17 | 18 |
19 | ) 20 | -------------------------------------------------------------------------------- /components/0-13-AlertBg.js: -------------------------------------------------------------------------------- 1 | export default ({ 2 | zIndex = 10, alpha = 0.4, top = 0, right = 0, bottom = 0, left = 0, onClick, 3 | }) => ( 4 |
19 | ) 20 | -------------------------------------------------------------------------------- /pages/_error.js: -------------------------------------------------------------------------------- 1 | import { Icon } from 'antd-mobile' 2 | import { WrapLink } from '@components' 3 | 4 | export default () => ( 5 |
6 | 7 |
404
8 |
访问的页面不存在,请 返回首页
9 |
10 | ) 11 | -------------------------------------------------------------------------------- /components/4-01-SwitchList.js: -------------------------------------------------------------------------------- 1 | import { Btn } from '@components' 2 | 3 | export default ({ 4 | title, onSwitch, keyVal, stateVal, yes = '是', no = '否', 5 | }) => ( 6 | 11 |
{title}
12 |
{stateVal === 1 ? yes : no}
13 |
14 | } 15 | onClick={() => onSwitch(keyVal)} 16 | /> 17 | ) 18 | -------------------------------------------------------------------------------- /store/reducers/2-01-loansFilter.js: -------------------------------------------------------------------------------- 1 | import { LOANS_FILTER } from '@actions' 2 | import { addDefault } from '@utils' 3 | 4 | const TITLE = [{ title: '综合排序', key: 'sort' }, { title: '全部类型', key: 'type' }, { title: '不限额度', key: 'limit' }] 5 | 6 | export default (state = null, action) => { 7 | switch (action.type) { 8 | case LOANS_FILTER: 9 | return { 10 | ...state, 11 | currentTitle: TITLE, 12 | selectList: addDefault(TITLE, action.payload.selectList), 13 | } 14 | default: 15 | return state 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /store/reducers/3-02-cardsFilter.js: -------------------------------------------------------------------------------- 1 | import { CARDS_FILTER } from '@actions' 2 | import { addDefault } from '@utils' 3 | 4 | const TITLE = [{ title: '全部银行', key: 'bank' }, { title: '所有卡型', key: 'use' }, { title: '不限等级', key: 'level' }] 5 | 6 | export default (state = null, action) => { 7 | switch (action.type) { 8 | case CARDS_FILTER: 9 | return { 10 | ...state, 11 | currentTitle: TITLE, 12 | selectList: addDefault(TITLE, action.payload.selectList), 13 | } 14 | default: 15 | return state 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | # EditorConfig 帮助开发者在不同的编辑器和IDE中保持一致的代码风格 3 | # 为了支持该文件保存后自动执行,请先下载该 EditorConfig for Vs Code 4 | 5 | # top-most EditorConfig file 6 | root = true 7 | 8 | # 应用于所有文件 9 | [*] 10 | 11 | charset = utf-8 12 | 13 | # 首行缩进 14 | indent_style = space 15 | indent_size = 2 16 | 17 | # 关于换行符的介绍 http://blog.csdn.net/timberwolf_2012/article/details/28687477 18 | end_of_line = lf 19 | # 在文件的最后需要有换行回车 20 | insert_final_newline = true 21 | # 去除每行末尾的空白符 22 | trim_trailing_whitespace = true 23 | 24 | [*.json] 25 | indent_size = 4 26 | -------------------------------------------------------------------------------- /static/styles/common/antd-mobile-config/config.less: -------------------------------------------------------------------------------- 1 | // 主题样式修改 https://github.com/ant-design/ant-design-mobile/blob/master/components/style/themes/default.less 2 | 3 | @hd: 0.02rem; 4 | @color-text-base: #333; 5 | @brand-primary: #4c8dfc; 6 | @brand-primary-tap: #4681e6; 7 | @primary-button-fill-tap: #4681e6; 8 | @input-font-size: 0.28rem; 9 | @font-size-heading: 0.28rem; 10 | @h-spacing-sm: 0.1rem; 11 | @h-spacing-md: 0.2rem; 12 | @h-spacing-lg: 0.3rem; 13 | @v-spacing-xs: 0.05rem; 14 | @v-spacing-sm: 0.1rem; 15 | @v-spacing-md: 0.2rem; 16 | @v-spacing-lg: 0.3rem; 17 | @v-spacing-xl: 0.4rem; 18 | -------------------------------------------------------------------------------- /store/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import fetchOnce from './0-01-fetchOnce' 3 | import home from './1-01-home' 4 | import hotSearch from './1-02-hotSearch' 5 | import mySearch from './1-03-mySearch' 6 | import loansFilter from './2-01-loansFilter' 7 | import cardsHome from './3-01-cardsHome' 8 | import cardsFilter from './3-02-cardsFilter' 9 | import user from './4-01-user' 10 | 11 | export default combineReducers({ 12 | fetchOnce, 13 | home, 14 | hotSearch, 15 | mySearch, 16 | loansFilter, 17 | cardsHome, 18 | cardsFilter, 19 | user, 20 | }) 21 | -------------------------------------------------------------------------------- /components/0-06-ErrorFetch.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Icon } from 'antd-mobile' 3 | 4 | export default class extends React.Component { 5 | componentDidMount() { 6 | console.info(this.props.err) 7 | } 8 | render() { 9 | return ( 10 |
11 | 12 |
无法显示页面
13 |
抱歉,服务器获取数据失败,请稍后再试!
14 |
15 | ) 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /components/0-15-DetailFoot.js: -------------------------------------------------------------------------------- 1 | import { Btn } from '@components' 2 | 3 | export default ({ isFavorite, onLike, onApply }) => ( 4 |
5 | { isFavorite ? '已收藏' : '收藏' }} 10 | onClick={onLike} 11 | /> 12 | 马上申请} 16 | onClick={onApply} 17 | /> 18 |
19 | ) 20 | -------------------------------------------------------------------------------- /components/0-04-Nav.js: -------------------------------------------------------------------------------- 1 | import { ActiveLink } from '@components' 2 | import uuid from 'uuid/v4' 3 | 4 | const config = [ 5 | { 6 | ico: 'i-home', text: '首页', href: '/index', as: '/', 7 | }, 8 | { 9 | ico: 'i-loan', text: '贷款', href: '/1-loan/1-home', as: '/loan', 10 | }, 11 | { 12 | ico: 'i-card', text: '信用卡', href: '/2-card/1-home', as: '/card', 13 | }, 14 | { 15 | ico: 'i-user', text: '我的', href: '/3-me/1-home', as: '/me', 16 | }, 17 | ] 18 | 19 | export default () => ( 20 |
21 | {config.map(item => )} 22 |
23 | ) 24 | -------------------------------------------------------------------------------- /components/0-02-Btn.js: -------------------------------------------------------------------------------- 1 | import { WrapLink } from '@components' 2 | 3 | export default ({ 4 | ver, hor, btnClass, path, icoClass, con, ...rest 5 | }) => ( 6 | 11 | {icoClass && } 12 | {con} 13 | 14 | ) 15 | 16 | /* 17 | * 使用范例 18 | 123} 25 | onClick={balabala} 26 | /> 27 | */ 28 | -------------------------------------------------------------------------------- /components/0-03-ActiveLink.js: -------------------------------------------------------------------------------- 1 | import { withRouter } from 'next/router' 2 | import Link from 'next/link' 3 | 4 | // typically you want to use `next/link` for this usecase 5 | // but this example shows how you can also access the router 6 | // using the withRouter utility. 7 | 8 | const ActiveLink = ({ 9 | ico, text, router, href, as = href, ...rest 10 | }) => ( 11 | 12 | 13 | 14 | {text} 15 | 16 | 17 | ) 18 | 19 | export default withRouter(ActiveLink) 20 | -------------------------------------------------------------------------------- /utils/02-cache.js: -------------------------------------------------------------------------------- 1 | const setItem = (key, v, overtime = 30 * 24 * 60 * 60 * 1000) => { 2 | const val = { 3 | value: v, 4 | overtime: Date.now() + overtime, 5 | } 6 | localStorage.setItem(key, JSON.stringify(val)) 7 | console.info(`已经设置缓存字段:${key},值为:${val.value}`) 8 | } 9 | 10 | const getItem = (key) => { 11 | if (localStorage.getItem(key) && JSON.parse(localStorage.getItem(key)).overtime > Date.now()) { 12 | return JSON.parse(localStorage.getItem(key)).value 13 | } 14 | return null 15 | } 16 | 17 | const removeItem = (key) => { 18 | localStorage.removeItem(key) 19 | console.info(`已经删除缓存字段:${key}`) 20 | } 21 | 22 | export default { 23 | setItem, 24 | getItem, 25 | removeItem, 26 | } 27 | -------------------------------------------------------------------------------- /utils/04-wxapi.js: -------------------------------------------------------------------------------- 1 | // 思考,把配置信息缓存 2 | export const setConfig = (config) => { 3 | wx.config(config) 4 | } 5 | export const setShare = (config) => { 6 | const params = { 7 | title: config.title || '', 8 | desc: config.desc || '', 9 | imgUrl: config.imgUrl || 'http://public.duduapp.net/finance/static/logo.png', 10 | link: config.link || window.location.href, 11 | } 12 | wx.ready(() => { 13 | wx.onMenuShareAppMessage(params) // 分享给朋友 14 | wx.onMenuShareQQ(params) // 分享到QQ 15 | wx.onMenuShareWeibo(params) // 分享到腾讯微博 16 | wx.onMenuShareQZone(params) // 分享到QQ空间 17 | wx.onMenuShareTimeline(Object.assign({}, params, { 18 | title: `${params.title} ${params.desc}`, 19 | })) // 分享到朋友圈 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "plugins": [ 4 | "transform-decorators-legacy", 5 | ["import", { "libraryName": "antd-mobile" }], 6 | [ 7 | "transform-runtime", 8 | { 9 | "helpers": false, 10 | "polyfill": true, 11 | "regenerator": true, 12 | "moduleName": "babel-runtime" 13 | } 14 | ], 15 | [ 16 | "module-resolver", 17 | { 18 | "alias": { 19 | "@components": "./components/index.js", 20 | "@utils": "./utils/index.js", 21 | "@actions": "./store/actions/index.js", 22 | "@reduxPage": "./store/reduxPage.js" 23 | } 24 | } 25 | ] 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /components/1-02-Limit.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid/v4' 2 | import { WrapLink, MultiColorIco } from '@components' 3 | 4 | // 多色图片的path数量 5 | const pathNum = [3, 9, 12, 18] 6 | export default ({ list = [{ id: 0, title: '不限额度' }] }) => ( 7 |
8 | { 9 | list.slice(0, 4).map((item, index) => ( 10 | 16 | 17 | {item.title} 18 | 19 | )) 20 | } 21 |
22 | ) 23 | -------------------------------------------------------------------------------- /.next/bundles/pages/_error.js: -------------------------------------------------------------------------------- 1 | 2 | window.__NEXT_REGISTER_PAGE('/_error', function() { 3 | var comp = module.exports=webpackJsonp([14],{454:function(e,t,l){e.exports=l(455)},455:function(e,t,l){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var c=l(69),n=a(c),r=l(1),u=a(r),f=l(9);t.default=function(){return u.default.createElement("div",{className:"flex column ai-center jc-center plr25 ptb20 h-full"},u.default.createElement(n.default,{type:"cross-circle-o",className:"w100 h100",style:{fill:"#F13642"}}),u.default.createElement("div",{className:"font32 c333 ptb20"},"404"),u.default.createElement("div",{className:"font28 c999"},"访问的页面不存在,请 ",u.default.createElement(f.WrapLink,{href:"/",className:"font30 c-main"},"返回首页")))}}},[454]); 4 | return { page: comp.default } 5 | }) 6 | -------------------------------------------------------------------------------- /components/4-02-ChangeList.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid/v4' 2 | 3 | export default ({ 4 | title, types, stateVal, keyVal, onChange, 5 | }) => ( 6 | types && types.length > 0 ? 7 |
8 |
{title}
9 |
10 |
11 |
{types[types.findIndex(item => item.id === parseInt(stateVal, 0)) > -1 ? types.findIndex(item => item.id === parseInt(stateVal, 0)) : 0].name}
12 | 13 |
14 | 17 |
18 |
: null 19 | ) 20 | -------------------------------------------------------------------------------- /components/1-03-LoanTypes.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid/v4' 2 | import { WrapLink } from '@components' 3 | 4 | export default ({ list = [{ id: 0, title: '不限额度', description: '想贷就贷' }] }) => ( 5 |
6 | { 7 | list.map((item, index) => ( 8 | 14 |
15 | {item.title} 16 |
17 |
18 | {item.description} 19 |
20 |
21 | )) 22 | } 23 |
24 | ) 25 | -------------------------------------------------------------------------------- /components/1-04-SearchItem.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid/v4' 2 | import { Btn } from '@components' 3 | 4 | export default ({ 5 | title, list, onClick, border, 6 | }) => ( 7 |
8 |
{title}
9 |
10 | { 11 | list.map(item => ( 12 | 19 | {item.content ? item.content.substring(0, 9) : item.substring(0, 9)} 20 | 21 | } 22 | onClick={() => onClick(item.content || item)} 23 | /> 24 | )) 25 | } 26 |
27 |
28 | ) 29 | -------------------------------------------------------------------------------- /static/scripts/hd.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(a){if(i[a])return i[a].exports;var n=i[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=window;t["default"]=i.flex=function(normal,e,t){var a=e||100,n=t||1,r=i.document,o=navigator.userAgent,d=o.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i),l=o.match(/U3\/((\d+|\.){5,})/i),c=l&&parseInt(l[1].split(".").join(""),10)>=80,p=navigator.appVersion.match(/(iphone|ipad|ipod)/gi),s=i.devicePixelRatio||1;p||d&&d[1]>534||c||(s=1);var u=normal?1:1/s,m=r.querySelector('meta[name="viewport"]');m||(m=r.createElement("meta"),m.setAttribute("name","viewport"),r.head.appendChild(m)),m.setAttribute("content","width=device-width,user-scalable=no,initial-scale="+u+",maximum-scale="+u+",minimum-scale="+u),r.documentElement.style.fontSize=normal?"50px": a/2*s*n+"px"},e.exports=t["default"]}]); flex(false,100, 1); 2 | -------------------------------------------------------------------------------- /static/styles/common/base/plugin.scss: -------------------------------------------------------------------------------- 1 | // 插件样式的覆盖调整 2 | .am-list-item .am-input-extra { 3 | max-height: none; 4 | } 5 | 6 | .am-modal-close { 7 | top: 0.2rem; 8 | } 9 | 10 | .am-number-keyboard-wrapper table tr .am-number-keyboard-item { 11 | vertical-align: middle; 12 | } 13 | 14 | .change-input { 15 | .am-list-item.am-input-item { 16 | height: 0.5rem; 17 | min-height: 0.5rem; 18 | padding-left: 0.2rem; 19 | background: #ededed; 20 | border-radius: 0.04rem; 21 | .am-list-line { 22 | padding-right: 0.15rem; 23 | .am-input-label { 24 | color: #999; 25 | } 26 | .am-input-extra { 27 | font-size: 0.24rem; 28 | color: #666; 29 | } 30 | } 31 | } 32 | } 33 | 34 | .home-banner .slider-frame { 35 | height: 37.6vw!important; 36 | max-height: 3.76rem!important; 37 | } 38 | 39 | .am-steps-small .am-steps-item-title { 40 | font-size: 0.3rem; 41 | } 42 | 43 | .am-steps-label-vertical .am-steps-item-content { 44 | margin-top: 0.06rem; 45 | } 46 | -------------------------------------------------------------------------------- /.next/dist/pages/_error.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _icon = require('antd-mobile/lib/icon'); 8 | 9 | var _icon2 = _interopRequireDefault(_icon); 10 | 11 | var _react = require('react'); 12 | 13 | var _react2 = _interopRequireDefault(_react); 14 | 15 | var _index = require('../components/index.js'); 16 | 17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 18 | 19 | exports.default = function () { 20 | return _react2.default.createElement('div', { className: 'flex column ai-center jc-center plr25 ptb20 h-full' }, _react2.default.createElement(_icon2.default, { type: 'cross-circle-o', className: 'w100 h100', style: { fill: '#F13642' } }), _react2.default.createElement('div', { className: 'font32 c333 ptb20' }, '404'), _react2.default.createElement('div', { className: 'font28 c999' }, '\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728\uFF0C\u8BF7 ', _react2.default.createElement(_index.WrapLink, { href: '/', className: 'font30 c-main' }, '\u8FD4\u56DE\u9996\u9875'))); 21 | }; -------------------------------------------------------------------------------- /store/reduxPage.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware, compose } from 'redux' 2 | import thunkMiddleware from 'redux-thunk' 3 | import logger from 'redux-logger' 4 | import withRedux from 'next-redux-wrapper' 5 | import apiMiddleware from './middleware/api' 6 | import rootReducers from './reducers' 7 | 8 | const composeEnhancers = compose // eslint-disable-line 9 | 10 | // 产品模式 11 | function configureStorePro(initialState) { 12 | const middlewares = [thunkMiddleware, apiMiddleware] 13 | const store = createStore( 14 | rootReducers, 15 | initialState, 16 | compose(applyMiddleware(...middlewares)), 17 | ) 18 | return store 19 | } 20 | 21 | // 开发模式 22 | function configureStoreDev(initialState) { 23 | const middlewares = [thunkMiddleware, apiMiddleware, logger] 24 | const store = createStore( 25 | rootReducers, 26 | initialState, 27 | composeEnhancers(applyMiddleware(...middlewares)), 28 | ) 29 | return store 30 | } 31 | 32 | const initStore = process.env.NODE_ENV === 'production' ? configureStorePro : configureStoreDev 33 | 34 | export default com => withRedux(initStore)(com) 35 | 36 | // export default initStore 37 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') // eslint-disable-line 2 | 3 | const { ANALYZE } = process.env 4 | const pro = process.env.NODE_ENV === 'production' 5 | const test = process.env.NODE_TEST === 'test' 6 | 7 | // 开发模式下的页面缓存 8 | // SSR页面缓存配置 https://github.com/zeit/next.js/blob/canary/examples/ssr-caching/server.js 9 | 10 | const onDemandEntries = { 11 | // period (in ms) where the server will keep pages in the buffer 12 | maxInactiveAge: 25 * 1000, 13 | // number of pages that should be kept simultaneously without being disposed 14 | pagesBufferLength: 2, 15 | } 16 | 17 | module.exports = { 18 | useFileSystemPublicRoutes: false, 19 | assetPrefix: pro ? (test ? '' : 'http://public.duduapp.net/finance/static') : '', 20 | ...(!pro && !test && { onDemandEntries }), 21 | exportPathMap: () => ({ 22 | '/': { page: '/' }, 23 | }), 24 | webpack: (config) => { 25 | if (ANALYZE) { 26 | config.plugins.push(new BundleAnalyzerPlugin({ 27 | analyzerMode: 'server', 28 | analyzerPort: 7777, 29 | openAnalyzer: true, 30 | })) 31 | } 32 | return config 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | .next 8 | .next/ 9 | outCDN 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | -------------------------------------------------------------------------------- /utils/03-http.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | // axios config https://github.com/axios/axios#request-config 3 | // const myApi = 'https://www.easy-mock.com/mock/58fff6e5739ac1685205acb1/data/' 4 | 5 | // 'http://jr.duduapp.net/api/' : 'http://192.168.1.116/api/' 6 | const pro = process.env.NODE_ENV === 'production' 7 | const test = process.env.NODE_TEST === 'test' 8 | 9 | const callApi = (url, method, data, isServer = false, options = {}) => { 10 | const opts = { ...options } 11 | return axios(Object.assign({}, { 12 | baseURL: isServer ? ((pro && !test) ? 'http://jr.duduapp.net/api/' : 'http://jr.duduapp.net/api/') : '/api/', 13 | url, 14 | method, 15 | params: method === 'get' ? data : {}, // 添加在请求URL后面的参数 16 | data: method !== 'get' ? data : {}, // 适用于 PUT POST PATCH 17 | withCredentials: true, // 请求时是否携带cookie 18 | }, opts)).then(data => data.data) 19 | } 20 | 21 | export default { 22 | callApi, 23 | get: (url, data = {}, isServer) => callApi(url, 'get', data, isServer), 24 | put: (url, data = {}, isServer) => callApi(url, 'put', data, isServer), 25 | post: (url, data = {}, isServer) => callApi(url, 'post', data, isServer), 26 | delete: (url, data = {}, isServer) => callApi(url, 'delete', data, isServer), 27 | } 28 | -------------------------------------------------------------------------------- /static/styles/common/custom/animation.scss: -------------------------------------------------------------------------------- 1 | // 公用的动画样式 2 | // https://daneden.github.io/animate.css/ 3 | 4 | .bounceIn { 5 | animation-name: bounceIn; 6 | animation-duration: .75s; 7 | } 8 | 9 | @keyframes bounceIn { 10 | from, 20%, 40%, 60%, 80%, to { 11 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 12 | } 13 | 14 | 0% { 15 | opacity: 0; 16 | transform: scale3d(.3, .3, .3); 17 | } 18 | 19 | 20% { 20 | transform: scale3d(1.1, 1.1, 1.1); 21 | } 22 | 23 | 40% { 24 | transform: scale3d(.9, .9, .9); 25 | } 26 | 27 | 60% { 28 | opacity: 1; 29 | transform: scale3d(1.03, 1.03, 1.03); 30 | } 31 | 32 | 80% { 33 | transform: scale3d(.97, .97, .97); 34 | } 35 | 36 | to { 37 | opacity: 1; 38 | transform: scale3d(1, 1, 1); 39 | } 40 | } 41 | 42 | // 旋转 43 | .rotate { 44 | animation: rotate360 1s linear infinite; 45 | } 46 | @keyframes rotate360 { 47 | from { 48 | transform: rotate(0); 49 | } 50 | to { 51 | transform: rotate(360deg); 52 | } 53 | } 54 | 55 | .transition { 56 | transition: all 1s; 57 | transition-timing-function:ease-in; 58 | } 59 | 60 | .search-btn-ani { 61 | transition: margin-right 0.3s, opacity 0.3s; 62 | transition-delay: 0.1s; 63 | } 64 | -------------------------------------------------------------------------------- /components/1-01-Message.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Carousel } from 'antd-mobile' 3 | import uuid from 'uuid/v4' 4 | import { Btn } from '@components' 5 | 6 | export default ({ list = ['欢迎来到嘟嘟e贷'] }) => ( 7 |
8 | 13 | 26 | {list.map(item => ( 27 |
32 | {item} 33 |
34 | ))} 35 |
36 | 我要贷} 44 | /> 45 |
46 | ) 47 | -------------------------------------------------------------------------------- /pages/3-me/5-about.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { setShare } from '@utils' 3 | import { Layout } from '@components' 4 | 5 | export default class extends Component { 6 | componentDidMount() { 7 | setShare({ 8 | title: '嘟嘟e贷', 9 | desc: '关于我们', 10 | }) 11 | } 12 | render() { 13 | return ( 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 |
线
22 |
一站式专业贷款服务平台
23 |
24 |
25 |
26 | 官方邮箱:xc@duduapp.net
27 | 商务合作:13253595612 28 |
29 |
30 | 31 | ) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /components/0-01-WrapLink.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react' 2 | import Link from 'next/link' 3 | 4 | // 判断是否为站内路由 5 | const isLink = path => path && ( 6 | (typeof path === 'string' && !path.includes('http')) || 7 | (Object.prototype.toString.call(path) === '[object Object]') 8 | ) 9 | 10 | // 判断是否为站外链接 11 | const isHref = path => path && (typeof path === 'string' && path.includes('http')) 12 | 13 | export default class extends PureComponent { 14 | onClick = () => { 15 | const { onClick, clickparams } = this.props 16 | if (onClick) { 17 | onClick(clickparams) 18 | } 19 | } 20 | 21 | render() { 22 | const { 23 | href, children, className, as, style, ...rest 24 | } = this.props 25 | if (isLink(href)) { 26 | return {children} 27 | } else if (isHref(href)) { 28 | return {children} 29 | } 30 | return ( 31 |
39 | {children} 40 |
41 | ) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Head, Main, NextScript } from 'next/document' 2 | 3 | const pro = process.env.NODE_ENV === 'production' 4 | const test = process.env.NODE_TEST === 'test' 5 | const path = pro ? (test ? '' : 'http://public.duduapp.net/finance/static') : '' 6 | 7 | export default class MyDocument extends Document { 8 | static getInitialProps({ renderPage }) { 9 | const { 10 | html, head, errorHtml, chunks, 11 | } = renderPage() 12 | return { 13 | html, head, errorHtml, chunks, 14 | } 15 | } 16 | render() { 17 | return ( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 嘟嘟e贷 25 | 26 | 27 | {this.props.customValue} 28 |
29 | 30 |