├── CHANGELOG.md ├── static ├── .gitkeep ├── ionicons │ └── fonts │ │ ├── ionicons.eot │ │ ├── ionicons.ttf │ │ └── ionicons.woff ├── mock │ ├── job.json │ ├── companyDetail.json │ └── myresumeDetail.json └── weui │ └── weui.min.css ├── .eslintignore ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── src ├── pages │ ├── system │ │ ├── NotFoundPage.vue │ │ └── index.js │ ├── message │ │ ├── index.js │ │ └── MessagePage.vue │ ├── my │ │ ├── index.js │ │ ├── MyCollection.vue │ │ ├── MyPage.vue │ │ ├── my-control.vue │ │ ├── my-info.vue │ │ ├── collected-job.vue │ │ └── MySetting.vue │ ├── home │ │ ├── index.js │ │ ├── HomeSearch.vue │ │ └── HomePage.vue │ ├── search │ │ ├── index.js │ │ ├── SearchFilter.vue │ │ ├── company-detail.vue │ │ ├── search-needs.vue │ │ ├── SearchDetail.vue │ │ └── SearchPage.vue │ ├── hr │ │ ├── index.js │ │ ├── JobPreview.vue │ │ ├── TextEle.vue │ │ ├── TextareaEle.vue │ │ ├── SelectEle.vue │ │ ├── JobOpr.vue │ │ ├── VDialog.vue │ │ └── Job.vue │ ├── LayoutPage.vue │ ├── HR │ │ ├── JobMgnt.vue │ │ ├── ComInfoAdd.vue │ │ └── ComInfoEdit.vue │ ├── TestPage.vue │ └── testResumeDetail.vue ├── assets │ ├── 2.jpg │ ├── 3.jpg │ ├── logo.png │ └── banner.png ├── config │ ├── config.prod.js │ └── config.dev.js ├── store │ ├── modules │ │ ├── index.js │ │ ├── invite.js │ │ └── job.js │ ├── index.js │ └── constants.js ├── App.vue ├── components │ ├── job-split.vue │ ├── index.js │ ├── filterSearch │ │ ├── index.js │ │ ├── filter-item.vue │ │ └── filter-search.vue │ ├── img-upload.vue │ ├── input-line.vue │ ├── job-navbar.vue │ ├── job-item.vue │ └── job-info.vue ├── common │ ├── index.js │ ├── eventBus.js │ ├── formatDate.js │ ├── storage.js │ └── ajax.js ├── vw-ui │ ├── components │ │ ├── tabbar │ │ │ ├── Tabbar.vue │ │ │ └── tab-item.vue │ │ ├── toptip │ │ │ ├── toptip.vue │ │ │ └── toptip.js │ │ ├── swipe │ │ │ ├── swipe-item.vue │ │ │ └── swipe.vue │ │ ├── button │ │ │ └── Button.vue │ │ ├── actionsheet │ │ │ └── actionsheet.vue │ │ ├── toast │ │ │ ├── toast.vue │ │ │ └── toast.js │ │ └── slider │ │ │ └── slider.vue │ ├── index.js │ └── utils │ │ └── dom.js ├── scss │ └── all.scss ├── main.js └── router.config.js ├── docs ├── IT-Job UI设计稿.mp ├── UI稿_未完全匹配仅供参考.zip ├── API文档.md ├── 开发规范汇总.md ├── VW-UI使用说明.md └── DbDesign.md ├── test └── unit │ ├── .eslintrc │ ├── specs │ └── HomePage.spec.js │ ├── index.js │ └── karma.conf.js ├── .editorconfig ├── .postcssrc.js ├── .babelrc ├── index.html ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md └── package.json /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/system/NotFoundPage.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/assets/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/src/assets/2.jpg -------------------------------------------------------------------------------- /src/assets/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/src/assets/3.jpg -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /docs/IT-Job UI设计稿.mp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/docs/IT-Job UI设计稿.mp -------------------------------------------------------------------------------- /src/assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/src/assets/banner.png -------------------------------------------------------------------------------- /docs/UI稿_未完全匹配仅供参考.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/docs/UI稿_未完全匹配仅供参考.zip -------------------------------------------------------------------------------- /src/pages/message/index.js: -------------------------------------------------------------------------------- 1 | import MessagePage from './MessagePage'; 2 | 3 | export { 4 | MessagePage 5 | }; 6 | -------------------------------------------------------------------------------- /src/pages/system/index.js: -------------------------------------------------------------------------------- 1 | import NotFoundPage from './NotFoundPage'; 2 | 3 | export { 4 | NotFoundPage 5 | }; 6 | -------------------------------------------------------------------------------- /static/ionicons/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/static/ionicons/fonts/ionicons.eot -------------------------------------------------------------------------------- /static/ionicons/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/static/ionicons/fonts/ionicons.ttf -------------------------------------------------------------------------------- /static/ionicons/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chengdujs/cd-it-job/HEAD/static/ionicons/fonts/ionicons.woff -------------------------------------------------------------------------------- /src/pages/my/index.js: -------------------------------------------------------------------------------- 1 | import MyPage from './MyPage'; 2 | import MySetting from './MySetting'; 3 | 4 | export { 5 | MyPage, 6 | MySetting 7 | }; 8 | -------------------------------------------------------------------------------- /src/config/config.prod.js: -------------------------------------------------------------------------------- 1 | const conf = { 2 | isDebug: false, 3 | apiHost: 'http://chat.hstar.org:8601/HkGhqLCUg' 4 | }; 5 | 6 | window.AppConf = conf; 7 | -------------------------------------------------------------------------------- /src/pages/home/index.js: -------------------------------------------------------------------------------- 1 | import HomePage from './HomePage'; 2 | import HomeSearch from './HomeSearch'; 3 | 4 | export { 5 | HomePage, 6 | HomeSearch 7 | }; 8 | -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/store/modules/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * store 的[数据]中心以及[状态]改变的中心 3 | */ 4 | export { default as invite } from './invite'; 5 | export { default as job } from './job' 6 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /src/pages/search/index.js: -------------------------------------------------------------------------------- 1 | import SearchPage from './SearchPage'; 2 | import SearchDetail from './SearchDetail'; 3 | 4 | export { 5 | SearchPage, 6 | SearchDetail 7 | }; 8 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/pages/hr/index.js: -------------------------------------------------------------------------------- 1 | import Job from './Job'; 2 | import JobPreview from './JobPreview'; 3 | import JobMgnt from './JobMgnt'; 4 | 5 | export { 6 | Job, 7 | JobPreview, 8 | JobMgnt 9 | }; 10 | -------------------------------------------------------------------------------- /src/config/config.dev.js: -------------------------------------------------------------------------------- 1 | const conf = { 2 | isDebug: true, 3 | apiHost: 'http://chat.hstar.org:8601/HkGhqLCUg', 4 | testApiHost: 'http://chat.hstar.org:8601/By4TMsfKx' 5 | }; 6 | 7 | window.AppConf = conf; 8 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 12 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/components/job-split.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /src/common/index.js: -------------------------------------------------------------------------------- 1 | import { eventBus } from './eventBus'; 2 | import { ajax } from './ajax'; 3 | import { storage } from './storage'; 4 | import { formatDate } from './formatDate'; 5 | 6 | export { 7 | eventBus, 8 | ajax, 9 | storage, 10 | formatDate 11 | }; 12 | -------------------------------------------------------------------------------- /src/vw-ui/components/tabbar/Tabbar.vue: -------------------------------------------------------------------------------- 1 | 6 | 14 | -------------------------------------------------------------------------------- /docs/API文档.md: -------------------------------------------------------------------------------- 1 | # 此处为所有API的文档集中地,客户端调用也以该文档为准 2 | 3 | ## 1、用户类API 4 | 5 | ### 1.1、用户登录 6 | 7 | ``` 8 | POST /user/login 9 | 10 | Request: { 11 | headers: {}, 12 | body: {} 13 | } 14 | 15 | Response: { 16 | headers: { 17 | 18 | }, 19 | body: { 20 | 21 | } 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import jobInfo from './job-info'; 2 | import jobSplit from './job-split'; 3 | import imgUpload from './img-upload'; 4 | import inputLine from './input-line'; 5 | import jobNavbar from './job-navbar'; 6 | 7 | export { 8 | jobInfo, 9 | jobSplit, 10 | imgUpload, 11 | inputLine, 12 | jobNavbar 13 | }; 14 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | import { invite, job } from './modules'; 5 | 6 | Vue.use(Vuex); 7 | 8 | const debug = process.env.NODE_ENV !== 'production'; 9 | 10 | export default new Vuex.Store({ 11 | modules: { 12 | invite, 13 | job 14 | }, 15 | strict: debug, 16 | plugins: debug ? [] : [] 17 | }); 18 | -------------------------------------------------------------------------------- /src/pages/message/MessagePage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /src/pages/search/SearchFilter.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | -------------------------------------------------------------------------------- /test/unit/specs/HomePage.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import { HomePage } from 'src/pages/home'; 3 | 4 | describe('home/HomePage.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | el: document.createElement('div'), 8 | render: (h) => h(HomePage) 9 | }); 10 | expect(vm.$el.className).to.equal('invite-hot'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/scss/all.scss: -------------------------------------------------------------------------------- 1 | html{ 2 | font-size: calc(100vw / 16); // 设计稿320,每份20px 3 | } 4 | body{ 5 | font-size: 14px; 6 | font-family: '\5FAE\8F6F\96C5\9ED1'; 7 | background:#e5e5e5; 8 | } 9 | a{ 10 | color:#333; 11 | } 12 | a:hover{ 13 | color:#f00; 14 | } 15 | .clearfix{ 16 | zoom:1 17 | } 18 | .clearfix:after { 19 | content:"."; 20 | height:0; 21 | visibility:hidden; 22 | display:block; 23 | clear:both 24 | } -------------------------------------------------------------------------------- /src/store/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 每一个模块一个 key-value 结构 3 | */ 4 | 5 | /** 6 | * invite 模块的 actions 常量的配置 7 | * 导入方式 import { INVITE } from '' 8 | * 这样的好处就是能够添加数据的时候可以不用修改导入的地方 9 | */ 10 | export const INVITE = { 11 | GET_LIST: 'GET_LIST' 12 | }; 13 | 14 | /** 15 | * job模块 16 | * 包含首页、搜索页的招聘信息 17 | */ 18 | 19 | export const JOB = { 20 | GET_JOBS: 'GET_JOBS', 21 | GET_CITIES: 'GET_CITIES', 22 | GET_SEARCHED_JOBS: 'GET_SEARCHED_JOBS', 23 | GET_JOB_TAGS: 'GET_JOB_TAGS' 24 | }; 25 | -------------------------------------------------------------------------------- /src/vw-ui/components/toptip/toptip.vue: -------------------------------------------------------------------------------- 1 | 8 | 11 | 25 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | require('./scss/all.scss'); 2 | 3 | import Vue from 'vue'; 4 | import router from './router.config'; 5 | import store from './store'; 6 | Vue.config.productionTip = false; 7 | 8 | import App from './App'; 9 | 10 | import axios from 'axios'; 11 | window.axios = axios; 12 | 13 | import VwUI from './vw-ui'; 14 | Vue.use(VwUI); 15 | 16 | // 导入Config 17 | if (process.env.NODE_ENV !== 'production') { 18 | require('./config/config.dev.js'); 19 | } else { 20 | require('./config/config.prod.js'); 21 | } 22 | 23 | /* eslint-disable no-unused-vars */ 24 | const app = new Vue({ 25 | el: '#app', 26 | router, 27 | store, 28 | ...App 29 | }); 30 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | cd-it-job 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/vw-ui/components/swipe/swipe-item.vue: -------------------------------------------------------------------------------- 1 | 16 | 21 | 37 | -------------------------------------------------------------------------------- /static/mock/job.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": 1, 3 | "name": "前端开发", 4 | "position": "上海", 5 | "year": "1~3年", 6 | "education": "本科", 7 | "money": "10-20K", 8 | "status": "1", 9 | "company": { 10 | "name": "哔哩哔哩", 11 | "lastUpdateDate": 1484555342388, 12 | "logoUrl": "https://www.lgstatic.com/thumbnail_120x120/i/image/M00/37/52/CgqKkVdf7WuAfS4yAABKqTIhsAA794.jpg" 13 | } 14 | }, { 15 | "id": 2, 16 | "name": "PHP开发", 17 | "position": "北京", 18 | "year": "1~3年", 19 | "education": "硕士", 20 | "money": "10-20K", 21 | "status": "2", 22 | "company": { 23 | "name": "哔哩哔哩", 24 | "lastUpdateDate": 1484555342388, 25 | "logoUrl": "https://www.lgstatic.com/thumbnail_120x120/i/image/M00/37/52/CgqKkVdf7WuAfS4yAABKqTIhsAA794.jpg" 26 | } 27 | }] 28 | -------------------------------------------------------------------------------- /src/store/modules/invite.js: -------------------------------------------------------------------------------- 1 | import { INVITE } from '../constants' 2 | 3 | /** 4 | * 初始化的状态数据 5 | */ 6 | const state = { 7 | list: [] 8 | } 9 | 10 | /** 11 | * 用于更新 view 的 getters 12 | */ 13 | const getters = { 14 | getList: state => state.list 15 | } 16 | 17 | /** 18 | * commit 同步突变 19 | */ 20 | const mutations = { 21 | [INVITE.GET_LIST](state, list) { 22 | state.msg = 'xxxx'; 23 | state.list = list; 24 | } 25 | } 26 | 27 | /** 28 | * dispatch 异步改变 29 | */ 30 | const actions = { 31 | [INVITE.GET_LIST](store) { 32 | // axios('/static/mock/job.json').then(res => { 33 | // if (res.status === 200) { 34 | // store.commit(INVITE.GET_LIST, res.data); 35 | // } 36 | // }); 37 | } 38 | } 39 | 40 | export default { 41 | state, 42 | getters, 43 | mutations, 44 | actions 45 | } 46 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 26 | 'semi': 0, 27 | 'space-before-function-paren': 0, 28 | 'no-return-assign': 2 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/common/eventBus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | const bus = new Vue(); 4 | 5 | export const eventBus = { 6 | /** 7 | * 注册全局事件 8 | * @param eventName 事件名称 9 | * @param handler 事件处理函数 10 | * @param scope vm对象,一般传this 11 | * @param once 是否单次注册 12 | */ 13 | on(eventName, handler, scope = null, once = false) { 14 | if (once) { 15 | bus.$once(eventName, handler); 16 | return; 17 | } 18 | bus.$on(eventName, handler); 19 | if (scope) { 20 | let originalDestroy = scope.$destroy; 21 | scope.$destroy = function () { 22 | bus.$off(eventName, handler); 23 | originalDestroy.call(this); 24 | } 25 | } 26 | }, 27 | 28 | /** 29 | * 触发事件 30 | * @param eventName 要触发的事件名称 31 | * @param data 事件对象 32 | */ 33 | emit(eventName, data) { 34 | bus.$emit(eventName, data); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /src/pages/hr/JobPreview.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | 28 | 41 | -------------------------------------------------------------------------------- /src/common/formatDate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 格式化日期 3 | * @param date 时间对象 4 | * @param fmt 要格式化的日期 5 | * @returns {String} 6 | * @example formatDate(date, 'yyyy-MM-dd hh:mm:ss') => '2017-01-17 11:09:33' 7 | */ 8 | export function formatDate(date, fmt) { 9 | if (/(y+)/.test(fmt)) { 10 | fmt = fmt 11 | .replace(RegExp.$1, (date.getFullYear() + '')) 12 | .substring(4 - RegExp.$1.length); 13 | }; 14 | let o = { 15 | 'M+': date.getMonth() + 1, 16 | 'd+': date.getDate(), 17 | 'h+': date.getHours(), 18 | 'm+': date.getMinutes(), 19 | 's+': date.getSeconds() 20 | }; 21 | 22 | for (let k in o) { 23 | if (new RegExp(`(${k})`).test(fmt)) { 24 | let str = o[k] + ''; 25 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str)) 26 | } 27 | }; 28 | 29 | return fmt; 30 | } 31 | 32 | function padLeftZero(str) { 33 | return ('00' + str).substr(str.length) 34 | }; 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Custom 2 | .vscode/ 3 | .DS_Store 4 | node_modules/ 5 | dist/ 6 | npm-debug.log 7 | test/unit/coverage 8 | test/e2e/reports 9 | selenium-debug.log 10 | resources/ 11 | 12 | # Logs 13 | logs 14 | *.log 15 | npm-debug.log* 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (http://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules 42 | jspm_packages 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional REPL history 48 | .node_repl_history 49 | 50 | .idea/ 51 | -------------------------------------------------------------------------------- /src/components/filterSearch/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by yelingfeng on 17/1/16. 3 | * 4 | * 数据格式 5 | const filterData = [ 6 | { 7 | name: '工作经验', 8 | items: [ 9 | {label: '应届毕业生', value: '001'}, 10 | {label: '3年以下', value: '002'}, 11 | {label: '3-5年', value: '003'}, 12 | {label: '5-10年', value: '004'}, 13 | {label: '10年以上', value: '005'} 14 | ] 15 | }, 16 | { 17 | name: '学历要求', 18 | items: [ 19 | {label: '大专', value: '001'}, 20 | {label: '本科', value: '002'}, 21 | {label: '硕士', value: '003'}, 22 | {label: '博士', value: '004'} 23 | ] 24 | }, 25 | { 26 | name: '行业领域', 27 | items: [ 28 | {label: '移动互联网', value: '001'}, 29 | {label: '电子商务', value: '002'}, 30 | {label: '金融', value: '003'}, 31 | {label: '教育', value: '004'} 32 | ] 33 | } 34 | ]** 35 | * 36 | */ 37 | import filterSearch from './filter-search' 38 | 39 | export { 40 | filterSearch 41 | }; 42 | -------------------------------------------------------------------------------- /src/pages/hr/TextEle.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 36 | -------------------------------------------------------------------------------- /src/pages/search/company-detail.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 24 | 25 | 45 | -------------------------------------------------------------------------------- /src/components/filterSearch/filter-item.vue: -------------------------------------------------------------------------------- 1 | 14 | 38 | -------------------------------------------------------------------------------- /static/mock/companyDetail.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "body": { 4 | "name": "上海客汗网络科技有限公司", 5 | "job": "媒介合作人及运营负责人", 6 | "money": { 7 | "min":15, 8 | "max":20 9 | }, 10 | "tag": 11 | { 12 | "address": "上海", 13 | "property": "全职", 14 | "education": "大专及以上", 15 | "years": "1-3年" 16 | }, 17 | "addressDetail": "上海市浦东新区陆家嘴235弄32号", 18 | "jobDetail": "岗位职责:\n1、上海地区商务拓展工作,具体负责某一楼别相关行业或渠道;\n2、上海地区商务拓展工作,具体负责某一楼别相关行业或渠道;\n3、上海地区商务拓展工作,具体负责某一楼别相关行业或渠道;\n4、上海地区商务拓展工作,具体负责某一楼别相关行业或渠道;\n任职要求:\n1、1-3年相关工作经验;本科及以上学历;\n1、1-3年相关工作经验;本科及以上学历;\n1、1-3年相关工作经验;本科及以上学历;\n1、1-3年相关工作经验;本科及以上学历;", 19 | "companyName": [ 20 | "异乡好居", 21 | "留学生海外的家\n海外留学生租房买房平台\n业务覆盖美国/英国/加拿大/澳洲/新西兰,覆盖306座热门城市" 22 | ], 23 | "companyDetail": [ 24 | "公司介绍", 25 | "2015年1月,异乡好居公司(Uhouzz)在天津成立;\n2015年1月,异乡好居公司(Uhouzz)在天津成立;\n2015年1月,异乡好居公司(Uhouzz)在天津成立;\n2015年1月,异乡好居公司(Uhouzz)在天津成立;\n2015年1月,异乡好居公司(Uhouzz)在天津成立;\n2015年1月,异乡好居公司(Uhouzz)在天津成立;" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/common/storage.js: -------------------------------------------------------------------------------- 1 | const globalObj = {}; 2 | 3 | class WebStorage { 4 | constructor(storage) { 5 | this.storage = storage; 6 | } 7 | get(key) { 8 | let valueStr = this.storage.getItem(key); 9 | try { 10 | return JSON.parse(valueStr); 11 | } catch (e) { 12 | return valueStr; 13 | } 14 | } 15 | set(key, value) { 16 | let valueStr = JSON.stringify(value); 17 | return this.storage.setItem(key, valueStr); 18 | } 19 | remove(key) { 20 | this.storage.removeItem(key); 21 | } 22 | removeAll() { 23 | this.storage.clear(); 24 | } 25 | } 26 | 27 | export const storage = { 28 | local: new WebStorage(window.localStorage), 29 | session: new WebStorage(window.sessionStorage), 30 | memory: { 31 | get(key) { 32 | return globalObj[key]; 33 | }, 34 | set(key, value) { 35 | globalObj[key] = value; 36 | }, 37 | remove(key) { 38 | globalObj[key] = undefined; 39 | }, 40 | removeAll() { 41 | Object.keys(globalObj).forEach(key => { globalObj[key] = undefined }); 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /static/mock/myresumeDetail.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 1, 3 | "body": { 4 | "name": "豪情", 5 | "subtitle": "三年经验", 6 | "baseInfo": { 7 | "expectJob": "前端开发", 8 | "careerYear": "3年", 9 | "birthDate": "1992.11", 10 | "presentAddress": "上海", 11 | "phone": "12345678901", 12 | "email": "abc@163.com" 13 | }, 14 | "expectJob": { 15 | "post": "前端开发", 16 | "category": "全职", 17 | "city": "上海" 18 | }, 19 | "jobDetail": "1、热爱前端,喜欢用最扎实的代码技术做出效果上最炫,代码上最合理的页面;\n2、熟悉html,css,能够兼容主流各种浏览器,比如ie6-10, chrome,firefox,opera;\n3、熟悉js dom, event,ajax, jsop能够编写基本的js原生代码;\n4、熟悉jquery api,能够编写最基本的动态交互效果,并擅长用jquery插件来封装日常的开发组件,能够保证代码的性能或可难搞性。", 20 | "workExperience": "2011年—2012年 打杂队搬砖队工作", 21 | "worksShow": "http://jikeytang.github.io", 22 | "skills": [ 23 | { 24 | "skill": "HTML5", 25 | "degree": 80 26 | }, 27 | { 28 | "skill": "CSS3", 29 | "degree": 90 30 | }, 31 | { 32 | "skill": "JavaScript", 33 | "degree": 86 34 | }, 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 chengdujs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/pages/hr/TextareaEle.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 45 | -------------------------------------------------------------------------------- /src/vw-ui/index.js: -------------------------------------------------------------------------------- 1 | import ActionSheet from './components/actionsheet/actionsheet'; 2 | import Button from './components/button/button'; 3 | 4 | import Tabbar from './components/tabbar/tabbar'; 5 | import TabItem from './components/tabbar/tab-item'; 6 | 7 | import Slider from './components/slider/slider'; 8 | 9 | import Swipe from './components/swipe/swipe'; 10 | import SwipeItem from './components/swipe/swipe-item'; 11 | 12 | import Toast from './components/toast/toast.js'; 13 | import Toptip from './components/toptip/toptip.js'; 14 | 15 | // All components. 16 | const COMPONENTS = [ 17 | ActionSheet, 18 | Button, 19 | Tabbar, 20 | TabItem, 21 | Slider, 22 | Swipe, 23 | SwipeItem 24 | ]; 25 | 26 | const SERVICES = [ 27 | Toast, 28 | Toptip 29 | ]; 30 | 31 | const install = Vue => { 32 | if (install.installed) return; 33 | SERVICES.forEach(service => { 34 | Vue[service.name] = Vue.prototype[service.name] = service; 35 | }); 36 | COMPONENTS.forEach(comp => { 37 | Vue.component(comp.name, comp); 38 | }); 39 | }; 40 | 41 | // auto install 42 | if (typeof window !== 'undefined' && window.Vue) { 43 | install(window.Vue); 44 | }; 45 | 46 | export default { 47 | install, 48 | version: '0.0.1' 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/img-upload.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 46 | 47 | 52 | -------------------------------------------------------------------------------- /src/pages/LayoutPage.vue: -------------------------------------------------------------------------------- 1 | 28 | 51 | -------------------------------------------------------------------------------- /docs/开发规范汇总.md: -------------------------------------------------------------------------------- 1 | # 0x0、版本描述 2 | 3 | ### 版本发布记录 4 | 5 | v0.0.1 2017-1-22 13:30 初稿,根据现有代码进行归类,综合 6 | 7 | ### 开发规范贡献者 8 | 9 | 10 | hstarorg avator 11 | hstarorg 12 | 13 | 14 | # 0x1、基本编码规范 15 | 16 | 1. 统一使用2个空格缩进。(项目已包含editorconfig配置文件,建议安装编辑器/IDE的editorconfig插件) 17 | 2. 文件末尾添加新行 18 | 3. 语句需要加分号 19 | 4. 使用ES6编码风格最佳 20 | 5. 使用常规的JS规范(如逗号之后加空格,一般使用VSC格式化即可) 21 | 22 | # 0x2、文件命名规范 23 | 24 | 1. 页面命名统一大驼峰命名,可选加上Page后缀,如 `SearchPage` 25 | 2. 其他组件采用全小写命名,使用中横线风格,如 `job-item` 26 | 27 | 28 | # 0x3、Vue编码约定 29 | 30 | 1. 省略 `style, template, script` 的默认值,如使用 `css` 来写 `style`,不需要设定 `lang` 31 | 2. Vue组件配置属性,请参考如下顺序: 32 | 33 | 大致是基本属性,钩子函数,其他常用配置这样的先后顺序 34 | 35 | ``` 36 | { 37 | name: '', 38 | props: {}, 39 | components: {}, 40 | filters: {}, 41 | data(){ 42 | 43 | }, 44 | created(), 45 | ...生命周期钩子, 46 | computed: {}, 47 | watth: {}, 48 | methods: {} 49 | } 50 | ``` 51 | 3. 私有函数,请使用下划线开头 52 | 53 | # 0x4、Github PR规范 54 | 55 | 1. 发起PR的时候,请务必注明编写的功能 56 | 2. 请务必提交可运行的代码 57 | 3. 如果有单元测试,请务必保证测试通过之后再提交 58 | 4. PR只允许提交的 `develop` 分支 59 | 60 | # 0x5、单元测试规范 61 | 62 | 1. 尽可能的编写单元测试代码 63 | 2. 单元测试代码放置于 `test/unit` 目录下,根据页面创建目录,所有测试代码以 `_test` 结尾,组件同理。 64 | 65 | # 0x6、vw-ui组件开发规范 66 | 67 | 1. 所有组件放置于 `vw-ui/components` 目录中,以组件名称为目录隔离 68 | 2. 组件不能有其他第三方依赖(不允许除weui之外的三方依赖) 69 | -------------------------------------------------------------------------------- /src/pages/my/MyCollection.vue: -------------------------------------------------------------------------------- 1 | 11 | 53 | 56 | -------------------------------------------------------------------------------- /src/pages/my/MyPage.vue: -------------------------------------------------------------------------------- 1 | 7 | 51 | 60 | -------------------------------------------------------------------------------- /src/pages/my/my-control.vue: -------------------------------------------------------------------------------- 1 | 13 | 23 | 59 | -------------------------------------------------------------------------------- /docs/VW-UI使用说明.md: -------------------------------------------------------------------------------- 1 | # Components 2 | 3 | ## Button 4 | 5 | ```html 6 | 7 | ``` 8 | **Props** 9 | 10 | |属性 | 类型 | 详情| 11 | |---|---|---| 12 | | type | String | 可选值:default, primary, warn | 13 | | disabled | Boolean | 是否被禁用,禁用时click无效 | 14 | | plain | Boolean | 是否是plain样式 | 15 | | mini | Boolean | 是否是小号按钮 | 16 | 17 | **Events** 18 | 19 | | 事件名 | 详情| 20 | |---|---| 21 | | click | 用户点击按钮事件 | 22 | 23 | ## Tabbar/TabbarItem 24 | 25 | ```html 26 | 27 | 28 | 29 | 30 | 31 | ``` 32 | 33 | **Tabbar Props** 34 | 35 | |属性 | 类型 | 详情| 36 | |---|---|---| 37 | | value | Any | 绑定当前选定tabbar-item的value属性 | 38 | 39 | **Tabbar Events** 40 | 41 | | 事件名 | 详情| 42 | |---|---| 43 | N/A 44 | 45 | **TabbarItem Props** 46 | 47 | |属性 | 类型 | 详情| 48 | |---|---|---| 49 | | label | String | 底部tab-item的标签文本 | 50 | | badge | Number\|Boolean | tab-item的badge标签(右上角小红点),默认false,为true显示小红点,为具体数字时,显示该数字| 51 | | value | Any | tab-item的值 | 52 | 53 | **TabbarItem Events** 54 | 55 | | 事件名 | 详情| 56 | |---|---| 57 | N/A 58 | 59 | ## Toast 60 | 61 | ```javascript 62 | // 也可使用 this.$toast 63 | Vue.$toast.success(message: string, options: { 64 | duration: number // 自动关闭时间(单位,毫秒) 65 | }, callback: Function); 66 | 67 | this.$toast.msg(message: string, options: { 68 | duration: number, // 自动关闭时间 69 | icon: enum{success, info, warn, error} // 显示的图标 70 | }, callback: Function); 71 | ``` 72 | -------------------------------------------------------------------------------- /src/vw-ui/components/button/Button.vue: -------------------------------------------------------------------------------- 1 | 4 | 56 | -------------------------------------------------------------------------------- /src/common/ajax.js: -------------------------------------------------------------------------------- 1 | const request = (method, url, data, config = {}) => { 2 | let options = Object.assign({}, config, { 3 | url, 4 | method, 5 | data 6 | // baseURL: window.AppConf.apiHost 7 | }); 8 | options.headers = options.headers || {}; 9 | return new Promise((resolve, reject) => { 10 | window.axios.request(options) 11 | .then(res => { 12 | let data = res.data; 13 | if (!data) { 14 | return resolve(data); 15 | } 16 | if (data.HasError) { 17 | if (!res.config.notNotifyError) { 18 | // toast.msg(data.ErrorMessage); 19 | } 20 | reject(res); 21 | } 22 | resolve(data); 23 | }).catch(res => { 24 | if (!res.config.notNotifyError) { 25 | // toast.msg(res.message); 26 | } 27 | reject(res); 28 | }); 29 | }); 30 | }; 31 | 32 | export const ajax = { 33 | get(url, config) { 34 | return request('get', url, null, config); 35 | }, 36 | delete(url, config) { 37 | return request('delete', url, null, config); 38 | }, 39 | head(url, config) { 40 | return request('head', url, null, config); 41 | }, 42 | post(url, data, config) { 43 | return request('post', url, data, config); 44 | }, 45 | put(url, data, config) { 46 | return request('put', url, data, config); 47 | }, 48 | patch(url, data, config) { 49 | return request('path', url, data, config); 50 | }, 51 | setCommonHeader(key, value) { 52 | window.axios.defaults.headers.common[key] = value; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 12345, 27 | autoOpenBrowser: true, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/vw-ui/components/tabbar/tab-item.vue: -------------------------------------------------------------------------------- 1 | 24 | 36 | 63 | -------------------------------------------------------------------------------- /src/pages/hr/SelectEle.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 43 | 44 | 63 | -------------------------------------------------------------------------------- /src/vw-ui/components/actionsheet/actionsheet.vue: -------------------------------------------------------------------------------- 1 | 17 | 25 | 64 | -------------------------------------------------------------------------------- /src/pages/hr/JobOpr.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 46 | 47 | 71 | -------------------------------------------------------------------------------- /src/router.config.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | 4 | import LayoutPage from './pages/LayoutPage'; 5 | // System 6 | import { NotFoundPage } from './pages/system'; 7 | // Home 8 | import { HomePage } from './pages/home'; 9 | // Search 10 | import { SearchPage, SearchDetail } from './pages/search'; 11 | // Message 12 | import { MessagePage } from './pages/message'; 13 | // My 14 | import { MyPage } from './pages/my'; 15 | // Job 16 | import { Job, JobPreview, JobMgnt } from './pages/hr'; 17 | // Test Page 18 | import TestPage from './pages/TestPage'; 19 | import TestResumeDetail from './pages/TestResumeDetail'; 20 | // 注册路由 21 | Vue.use(VueRouter); 22 | 23 | /* 路由配置 */ 24 | const routes = [ 25 | { 26 | path: '', 27 | component: LayoutPage, 28 | children: [ 29 | { path: '', component: HomePage }, 30 | { path: 'search', component: SearchPage }, 31 | { path: 'searchdetail', component: SearchDetail }, 32 | { path: 'message', component: MessagePage }, 33 | { path: 'my', component: MyPage }, 34 | { path: 'hr/job', component: Job }, 35 | { path: 'hr/job/mgnt', component: JobMgnt }, 36 | { path: 'hr/job/preview', component: JobPreview } 37 | ] 38 | }, 39 | { path: '/test', component: TestPage }, 40 | { path: '/testresume', component: TestResumeDetail }, 41 | { path: '*', component: NotFoundPage } 42 | ]; 43 | 44 | /* 注册路由 */ 45 | const router = new VueRouter({ 46 | mode: 'history', 47 | routes 48 | }); 49 | 50 | /* 路由 filter: todo 先开发功能 */ 51 | // router.beforeEach((to, from, next) => { 52 | // 如果有路由匹配到了auth属性 53 | // if (to.matched.some(record => record.meta.auth)) { 54 | // next(); 55 | // } else { 56 | // next(); 57 | // } 58 | // }); 59 | 60 | export default router; 61 | -------------------------------------------------------------------------------- /src/components/input-line.vue: -------------------------------------------------------------------------------- 1 | 15 | 51 | 79 | -------------------------------------------------------------------------------- /src/store/modules/job.js: -------------------------------------------------------------------------------- 1 | import { JOB } from '../constants'; 2 | import { ajax } from 'common'; 3 | 4 | /** 5 | * 存放数据 6 | */ 7 | const state = { 8 | jobs: [], 9 | cities: [], 10 | searchedJobs: [], 11 | jobTags: [] 12 | }; 13 | 14 | /** 15 | * 过滤数据 16 | */ 17 | const getters = { 18 | hotCities: state => state.cities.filter(city => city.hot), 19 | hotJobTags: state => state.jobTags.filter(tag => tag.hot) 20 | }; 21 | 22 | /** 23 | * 提交同步状态 24 | */ 25 | const mutations = { 26 | [JOB.GET_JOBS](state, data) { 27 | state.jobs = data; 28 | }, 29 | [JOB.GET_CITIES](state, data) { 30 | state.cities = data; 31 | }, 32 | [JOB.GET_SEARCHED_JOBS](state, data) { 33 | state.searchedJobs = data; 34 | }, 35 | [JOB.GET_JOB_TAGS](state, data) { 36 | state.jobTags = data; 37 | } 38 | }; 39 | 40 | /** 41 | * 提交异步请求 42 | */ 43 | const actions = { 44 | [JOB.GET_JOBS]({ commit }) { 45 | return ajax.get(`${window.AppConf.apiHost}/recommendation_list`) 46 | .then(res => { 47 | if (res.state === 1) { 48 | commit(JOB.GET_JOBS, res.data); 49 | } 50 | return res; 51 | }); 52 | }, 53 | [JOB.GET_CITIES]({ commit }) { 54 | return ajax.get(`${window.AppConf.apiHost}/city_list`) 55 | .then(res => { 56 | if (res.state === 1) { 57 | commit(JOB.GET_CITIES, res.data); 58 | } 59 | return res; 60 | }) 61 | }, 62 | [JOB.GET_JOB_TAGS]({ commit }) { 63 | return ajax.get(`${window.AppConf.apiHost}/jobTags`) 64 | .then(res => { 65 | if (res.state === 1) { 66 | commit(JOB.GET_JOB_TAGS, res.data) 67 | } 68 | return res; 69 | }) 70 | } 71 | }; 72 | 73 | export default { 74 | state, 75 | getters, 76 | mutations, 77 | actions 78 | } 79 | -------------------------------------------------------------------------------- /src/pages/search/search-needs.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 39 | 40 | 75 | -------------------------------------------------------------------------------- /src/vw-ui/components/toast/toast.vue: -------------------------------------------------------------------------------- 1 | 25 | 34 | 71 | -------------------------------------------------------------------------------- /src/components/job-navbar.vue: -------------------------------------------------------------------------------- 1 | n 17 | 18 | 68 | -------------------------------------------------------------------------------- /src/vw-ui/components/toptip/toptip.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | const ToptipConstructor = Vue.extend(require('./toptip.vue')); 4 | const toptipPool = []; 5 | 6 | const getAnInstance = () => { 7 | if (toptipPool.length > 0) { 8 | let instance = toptipPool[0]; 9 | toptipPool.splice(0, 1); 10 | return instance; 11 | } 12 | return new ToptipConstructor({ 13 | el: document.createElement('div') 14 | }); 15 | }; 16 | 17 | const returnAnInstance = instance => { 18 | if (instance) { 19 | toptipPool.push(instance); 20 | } 21 | }; 22 | 23 | const removeDom = event => { 24 | if (event.target.parentNode) { 25 | event.target.parentNode.removeChild(event.target); 26 | } 27 | }; 28 | 29 | ToptipConstructor.prototype.close = function () { 30 | this.$el.addEventListener('transitionend', removeDom); 31 | this.opacity = 0; 32 | this.closeCallback(); 33 | returnAnInstance(this); 34 | }; 35 | 36 | const showToptip = (options) => { 37 | let duration = options.duration || 3000; 38 | let instance = getAnInstance(); 39 | 40 | clearTimeout(instance.timer); 41 | instance.content = options.content; 42 | instance.closeCallback = options.callback; 43 | document.body.appendChild(instance.$el); 44 | 45 | Vue.nextTick(function () { 46 | instance.opacity = 1; 47 | instance.$el.removeEventListener('transitionend', removeDom); 48 | ~duration && (instance.timer = setTimeout(() => { 49 | instance.close(); 50 | }, duration)); 51 | }); 52 | 53 | return instance; 54 | }; 55 | 56 | const noop = function () { }; 57 | 58 | const Toptip = { 59 | name: '$toptip', 60 | tip(message, options, callback) { 61 | options = options || {}; 62 | showToptip({ 63 | content: message, 64 | duration: options.duration || 3000, 65 | callback: callback || noop 66 | }); 67 | } 68 | }; 69 | 70 | export default Toptip; 71 | -------------------------------------------------------------------------------- /src/pages/HR/JobMgnt.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 35 | 36 | 76 | -------------------------------------------------------------------------------- /src/pages/hr/VDialog.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 54 | 55 | 60 | -------------------------------------------------------------------------------- /src/vw-ui/utils/dom.js: -------------------------------------------------------------------------------- 1 | class LiteQuery { 2 | constructor(selector, doc = window.document) { 3 | this._nodeList = []; 4 | if (typeof selector === 'string') { 5 | this._nodeList = [].slice.call(doc.querySelectorAll(selector)); 6 | } else if (selector instanceof window.Node) { 7 | this._nodeList = [selector]; 8 | } else { 9 | throw new Error('arguments error'); 10 | } 11 | } 12 | 13 | on(eventName, eventHandler, eventPropagation = false) { 14 | this._nodeList.forEach(el => { 15 | el.addEventListener(eventName, eventHandler, eventPropagation); 16 | }); 17 | return this; 18 | } 19 | 20 | off(eventName, eventHandler = null) { 21 | this._nodeList.forEach(el => { 22 | el.removeEventListener(eventName, eventHandler); 23 | }); 24 | return this; 25 | } 26 | 27 | getStyle(key) { 28 | if (this._nodeList.length !== 1) { 29 | throw new Error('getStyle must be called by one element.'); 30 | } 31 | let el = this._nodeList[0]; 32 | let elStyleObj = window.getComputedStyle(el); 33 | if (key) { 34 | return elStyleObj[key]; 35 | } 36 | return elStyleObj; 37 | } 38 | 39 | addClass(className) { 40 | this._nodeList.forEach(el => { 41 | if (el.classList.indexOf(className) < 0) { 42 | el.classList.add(...className.split(' ')); 43 | } 44 | }); 45 | return this; 46 | } 47 | 48 | removeClass(className) { 49 | this._nodeList.forEach(el => { 50 | if (el.classList.indexOf(className) >= 0) { 51 | el.classList.remove(...className.split(' ')); 52 | } 53 | }); 54 | } 55 | 56 | css(key, value) { 57 | let styleObj; 58 | if (typeof key === 'string') { 59 | styleObj = { [key]: value }; 60 | } else { 61 | styleObj = key; 62 | } 63 | let keys = Object.keys(styleObj); 64 | this._nodeList.forEach(el => { 65 | keys.forEach(styleProp => { 66 | el.style[styleProp] = styleObj[styleProp]; 67 | }); 68 | }); 69 | return this; 70 | } 71 | } 72 | 73 | export const $$ = function (selector, doc) { 74 | return new LiteQuery(selector, doc); 75 | }; 76 | -------------------------------------------------------------------------------- /src/pages/my/my-info.vue: -------------------------------------------------------------------------------- 1 | 20 | 44 | 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cd-it-job 2 | 针对成都IT小伙伴们的工作机会(招聘,求职)交流的微信订阅号项目。 3 | 4 | ## Build Setup 5 | 6 | ``` bash 7 | # install dependencies 8 | npm install 9 | 10 | # serve with hot reload at localhost:8080 11 | npm run dev 12 | 13 | # build for production with minification 14 | npm run build 15 | 16 | # run unit tests 17 | npm run unit 18 | 19 | # run all tests 20 | npm test 21 | ``` 22 | 23 | ## 开发规范 24 | 25 | 1. 统一使用2个空格缩进,文件末尾空出一行。(项目已包含editorconfig配置文件,建议安装编辑器/IDE的editorconfig插件) 26 | 2. 使用常规的 `JavaScript` 编码规范 27 | 3. 使用ES6编码风格最佳 28 | 4. 请务必提交可运行的代码 29 | 5. 发起PR的时候,请务必注明编写的功能 30 | 6. 如果可以,请编写单元测试代码 31 | 7. Page命名,以大驼峰为准(驼峰,首字母大写,如:HomePage) 32 | 8. Component命名,全小写(中横线分割,如:job-item) 33 | 34 | ## 目录说明 35 | 36 | ``` 37 | build/ -- 构建目录 38 | config/ -- 构建配置目录 39 | docs/ -- 文档目录 40 | src/ -- 源代码目录(重点关注目录) 41 | assets/ -- 需要打包的资源目录 42 | common/ -- 公共服务 43 | ajax.js -- ajax封装 44 | eventBus.js -- 事件中心封装 45 | storage.js -- 存储封装(Local, Session, Memory) 46 | components/ -- 组件目录(此处用于放置公共组件) 47 | config/ -- 系统配置目录 48 | config.dev.js -- 开发时的配置 49 | config.prod.js -- 上线时的配置(保证和开发时具有相同的属性) 50 | pages/ -- 页面目录,具体的页面 51 | store/ -- Vuex相关目录 52 | vw-ui/ -- 组件目录,以后将会拆分到vw-ui项目中,放置对weui的包装组件 53 | App.vue 54 | main.js -- 程序入口文件 55 | router.config.js -- 全局路由配置文件 56 | static/ -- 第三方静态资源目录 57 | test/ -- 测试代码目录 58 | .babelrc -- babel配置文件 59 | .editorconfig -- 编辑器格式通用配置文件,建议安装EditorConfig插件 60 | index.html -- 入口HTML文件 61 | ... 62 | ``` 63 | 64 | ## 贡献者 65 | 66 | **注:排名不分先后** 67 | 68 | ![hstarorg](https://avatars3.githubusercontent.com/u/4043284?v=3&s=30) 69 | [hstarorg](https://github.com/hstarorg) 70 | 71 | ![mabelyong](https://avatars3.githubusercontent.com/u/15611759?v=3&s=30) 72 | [mabelyong](https://github.com/mabelyong) 73 | 74 | ![MrTreasure](https://avatars3.githubusercontent.com/u/22043285?v=3&s=30) 75 | [MrTreasure](https://github.com/MrTreasure) 76 | 77 | ![jikeytang](https://avatars3.githubusercontent.com/u/539745?v=3&s=30) 78 | [jikeytang](https://github.com/jikeytang) 79 | 80 | ![yelingfeng](https://avatars1.githubusercontent.com/u/1932350?v=3&s=30) 81 | [yelingfeng](https://github.com/yelingfeng) 82 | 83 | ![zerosrat](https://avatars3.githubusercontent.com/u/8179987?v=3&s=30) 84 | [zerosrat](https://github.com/zerosrat) 85 | -------------------------------------------------------------------------------- /src/components/job-item.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 38 | 39 | 93 | -------------------------------------------------------------------------------- /src/vw-ui/components/toast/toast.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | const ToastConstructor = Vue.extend(require('./toast.vue')); 4 | const toastPool = []; 5 | 6 | const getAnInstance = () => { 7 | if (toastPool.length > 0) { 8 | let instance = toastPool[0]; 9 | toastPool.splice(0, 1); 10 | return instance; 11 | } 12 | return new ToastConstructor({ 13 | el: document.createElement('div') 14 | }); 15 | }; 16 | 17 | const returnAnInstance = instance => { 18 | if (instance) { 19 | toastPool.push(instance); 20 | } 21 | }; 22 | 23 | const removeDom = event => { 24 | if (event.target.parentNode) { 25 | event.target.parentNode.removeChild(event.target); 26 | } 27 | }; 28 | 29 | ToastConstructor.prototype.close = function () { 30 | this.$el.addEventListener('transitionend', removeDom); 31 | this.opacity = 0; 32 | this.closeCallback(); 33 | returnAnInstance(this); 34 | }; 35 | 36 | const showToast = (options) => { 37 | let duration = options.duration || 3000; 38 | let instance = getAnInstance(); 39 | 40 | clearTimeout(instance.timer); 41 | instance.content = options.content; 42 | if (options.rootClass) { 43 | instance.rootClass = options.rootClass; 44 | } 45 | if (options.iconType) { 46 | instance.iconType = options.iconType; 47 | } 48 | instance.iconClass = options.iconClass; 49 | instance.closeCallback = options.callback; 50 | document.body.appendChild(instance.$el); 51 | 52 | Vue.nextTick(function () { 53 | instance.opacity = 1; 54 | instance.$el.removeEventListener('transitionend', removeDom); 55 | ~duration && (instance.timer = setTimeout(() => { 56 | instance.close(); 57 | }, duration)); 58 | }); 59 | 60 | return instance; 61 | }; 62 | 63 | const noop = function () { }; 64 | 65 | const Toast = { 66 | name: '$toast', 67 | success(message, options, callback) { 68 | options = options || {}; 69 | showToast({ 70 | content: message, 71 | duration: options.duration || 3000, 72 | iconClass: 'weui-icon-success-no-circle', 73 | callback: callback || noop 74 | }); 75 | }, 76 | msg(message, options, callback) { 77 | options = options || {}; 78 | showToast({ 79 | rootClass: 'vw-toast-small', 80 | content: message, 81 | duration: options.duration || 3000, 82 | iconType: options.icon, 83 | callback: callback || noop 84 | }); 85 | } 86 | }; 87 | 88 | export default Toast; 89 | -------------------------------------------------------------------------------- /src/components/filterSearch/filter-search.vue: -------------------------------------------------------------------------------- 1 | 6 | 64 | 101 | -------------------------------------------------------------------------------- /src/pages/home/HomeSearch.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 85 | 86 | 99 | -------------------------------------------------------------------------------- /src/vw-ui/components/slider/slider.vue: -------------------------------------------------------------------------------- 1 | 12 | 77 | -------------------------------------------------------------------------------- /src/vw-ui/components/swipe/swipe.vue: -------------------------------------------------------------------------------- 1 | 29 | 40 | 104 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cd-it-job", 3 | "version": "0.2.0", 4 | "description": "A Vue.js project", 5 | "author": "Jay.M.Hu ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", 11 | "test": "npm run unit", 12 | "lint": "eslint --ext .js,.vue src test/unit/specs" 13 | }, 14 | "dependencies": { 15 | "axios": "^0.15.3", 16 | "vue": "^2.2.2", 17 | "vue-router": "^2.2.0", 18 | "vuex": "^2.1.1" 19 | }, 20 | "peerDependencies": { 21 | "karma-phantomjs-launcher": "^1.0.2", 22 | "phantomjs-prebuilt": "^2.1.14" 23 | }, 24 | "devDependencies": { 25 | "autoprefixer": "^6.7.2", 26 | "babel-core": "^6.22.1", 27 | "babel-eslint": "^7.1.1", 28 | "babel-loader": "^6.2.10", 29 | "babel-plugin-istanbul": "^3.1.2", 30 | "babel-plugin-transform-runtime": "^6.22.0", 31 | "babel-preset-env": "^1.2.1", 32 | "babel-preset-stage-2": "^6.22.0", 33 | "babel-register": "^6.22.0", 34 | "chai": "^3.5.0", 35 | "chalk": "^1.1.3", 36 | "connect-history-api-fallback": "^1.3.0", 37 | "copy-webpack-plugin": "^4.0.1", 38 | "cross-env": "^3.1.4", 39 | "css-loader": "^0.26.1", 40 | "eslint": "^3.14.1", 41 | "eslint-config-standard": "^6.2.1", 42 | "eslint-friendly-formatter": "^2.0.7", 43 | "eslint-loader": "^1.6.1", 44 | "eslint-plugin-html": "^2.0.0", 45 | "eslint-plugin-promise": "^3.4.0", 46 | "eslint-plugin-standard": "^2.0.1", 47 | "eventsource-polyfill": "^0.9.6", 48 | "express": "^4.14.1", 49 | "extract-text-webpack-plugin": "^2.0.0", 50 | "file-loader": "^0.10.0", 51 | "friendly-errors-webpack-plugin": "^1.1.3", 52 | "function-bind": "^1.1.0", 53 | "html-webpack-plugin": "^2.28.0", 54 | "http-proxy-middleware": "^0.17.3", 55 | "inject-loader": "^2.0.1", 56 | "karma": "^1.4.1", 57 | "karma-coverage": "^1.1.1", 58 | "karma-mocha": "^1.3.0", 59 | "karma-sinon-chai": "^1.2.4", 60 | "karma-sourcemap-loader": "^0.3.7", 61 | "karma-spec-reporter": "0.0.26", 62 | "karma-webpack": "^2.0.2", 63 | "lolex": "^1.5.2", 64 | "mocha": "^3.2.0", 65 | "node-sass": "^4.5.0", 66 | "opn": "^4.0.2", 67 | "optimize-css-assets-webpack-plugin": "^1.3.0", 68 | "ora": "^1.1.0", 69 | "rimraf": "^2.6.0", 70 | "sass-loader": "^6.0.3", 71 | "semver": "^5.3.0", 72 | "sinon": "^1.17.7", 73 | "sinon-chai": "^2.8.0", 74 | "url-loader": "^0.5.7", 75 | "vue-loader": "^11.1.4", 76 | "vue-style-loader": "^2.0.0", 77 | "vue-template-compiler": "^2.2.4", 78 | "webpack": "^2.2.1", 79 | "webpack-bundle-analyzer": "^2.2.1", 80 | "webpack-dev-middleware": "^1.10.0", 81 | "webpack-hot-middleware": "^2.16.1", 82 | "webpack-merge": "^2.6.1" 83 | }, 84 | "engines": { 85 | "node": ">= 4.0.0", 86 | "npm": ">= 3.0.0" 87 | }, 88 | "browserslist": [ 89 | "> 1%", 90 | "last 2 versions", 91 | "not ie <= 8" 92 | ] 93 | } 94 | -------------------------------------------------------------------------------- /src/pages/TestPage.vue: -------------------------------------------------------------------------------- 1 | 85 | 111 | -------------------------------------------------------------------------------- /src/pages/my/collected-job.vue: -------------------------------------------------------------------------------- 1 | 32 | 56 | 135 | -------------------------------------------------------------------------------- /docs/DbDesign.md: -------------------------------------------------------------------------------- 1 | # IT-JOB数据表设计(MongoDB) 2 | 3 | ## 用户信息表(users ) 4 | 5 | ``` 6 | { 7 | _id: ObjectId, // 主键 8 | username: string, // 用户名 9 | password: string, // 密码 10 | sex: string, // 性别 11 | city: string, // 城市 12 | province: string, // 省份 13 | country: string, // 国家 14 | avatarUrl: string, // 头像 15 | nickname: string // 昵称 16 | openId: string, // 微信OpenId 17 | unionId: string, // 微信UnionId 18 | createDate: long, // 注册时间 19 | lastUpdateDate: long, //最后更新时间 20 | // 以上为基本信息,接着是基本用户的附加信息 21 | favoriteJob: Array, // 收藏的职位(Id) 22 | favoriteCompany: Array, // 收藏的公司(Id) 23 | // 以下是HR的附加信息 24 | isJobPoster: boolean, // 是否是职位发布者 25 | applyStatus: string, // 申请为HR,状态('待申请', '审核中', '通过') 26 | applyInfo: { // 申请时填写的相关信息 27 | componyName: string, // 公司名称 28 | componyPhone: string, // 公司电话 29 | fullName: string, // 姓名 30 | phoneNumber: string // 个人电话 31 | } 32 | } 33 | ``` 34 | 35 | **注:该表大部分属性和微信一致,方便接入微信登录,另外username+password为扩展,方便以后自有账号登录。** 36 | 37 | ## 职位表(jobs) 38 | 39 | ``` 40 | { 41 | _id: ObjectId(), // 主键 42 | name: string, // 职位名称 43 | salary: string, // 薪资范围 44 | city: string, //工作地点 45 | workExperience: string, //工作经验 46 | education: string, // 学历要求 47 | jobTemptation: string, // 职位诱惑 48 | jobDescription: string, // 职位描述 49 | workArea: string, // 工作地址(可以选的那部分) 50 | workAddress: string, // 工作地址(手动输入的那部分) 51 | createDate: long, // 发布时间 52 | createBy: ObjectId, // 发布者 53 | lastUpdateDate: long, // 最后更新时间 54 | lastUpdateBy: ObjectId, // 最后更新人 55 | // 以上为基本信息 56 | interviewEvaluation: Array<{ 57 | userId: ObjectId, 58 | evaluationContent: string, // 评价内容 59 | descScore: number, // 描述符合度评分(星级) 60 | interviewerScore: number, // 面试官评分 61 | environmentScore: number, // 公司环境评分 62 | tags: Array, // 标签 63 | stars: Array, // 点赞人员 64 | createDate: long // 评价时间 65 | }> //面试评价 66 | } 67 | ``` 68 | 69 | ## 公司表(company) 70 | 71 | ``` 72 | { 73 | _id: ObjectId(), // 主键 74 | name: string, //公司名称 75 | logoUrl: string, // logo地址 76 | city: string, // 所在城市 77 | financingStage: string, // 融资阶段 78 | industry: string, // 行业领域 79 | staffTotalNumber: string, // 员工总数 80 | address: string, // 办公地址 81 | description: string, // 公司介绍 82 | createDate: long, // 创建该记录的时间(非公司创建时间) 83 | createBy: ObjectId, // 创建人(非公司创建人) 84 | lastUpdateDate: long, // 最后更新时间 85 | lastUpdateBy: ObjectId, // 最后更新人 86 | // 以上为基本信息 87 | 88 | } 89 | ``` 90 | 91 | ## 简历信息表(resume) 92 | 93 | ``` 94 | { 95 | _id: ObjectId, // 主键 96 | userId: ObjectId, 97 | resumeName: string, // 简历名称 98 | // 基本信息 99 | name: string, 100 | sex: string, 101 | birthday: long, 102 | education: string, 103 | workYears: string, // 工作年限 104 | city: string, 105 | phoneNumber: string, 106 | emailAddress: string, 107 | selfIntro: string, // 自我介绍 108 | // 社交链接 109 | socialLinks: Array<{ 110 | name: string, // 名称,如QQ,weibo 111 | linkAddress: string, // 主页地址 112 | createDate: long 113 | }>, 114 | // 工作经历 115 | workExperience: Array<{ 116 | companyName: string, // 公司名称 117 | jobTitle: string, // 职位 118 | startDate: string, // 在职时间(开始) 119 | endDate: string, // 离职时间(结束) 120 | workContent: string, // 工作内容 121 | createDate: long // 创建日期 122 | }>, 123 | // 教育经历 124 | educationExperience: Array<{ 125 | schoolName: string, 126 | majorName: string, // 专业名称 127 | education: string, // 最高学历 128 | graduationYear: number, // 毕业年份 129 | createDate: long 130 | }>, 131 | // 项目经验 132 | projectExperience: Array<{ 133 | projectName: string, // 项目名称 134 | workContent: string, // 职责(工作内容) 135 | startDate: string, // 开始时间(起) 136 | endDate: string, // 结束时间(止) 137 | projectDesc: string, 138 | projectLink: string, 139 | createDate: long 140 | }>, 141 | // 作品 142 | products: Array<{ 143 | name: string, // 作品名称 144 | linkAddress: string, // 作品链接 145 | imageAddress: string, // 作品图片地址 146 | description: string, // 作品描述 147 | createDate: long // 创建时间 148 | }>, 149 | // 期望工作 150 | wishWork: { 151 | jobTitle: string, 152 | jobType: string, // 全职,兼职,实习 153 | city: string, 154 | salary: string, // 薪水范围 155 | description: string, // 补充说明 156 | createDate: long 157 | } 158 | } 159 | ``` 160 | -------------------------------------------------------------------------------- /src/pages/home/HomePage.vue: -------------------------------------------------------------------------------- 1 | 46 | 103 | 173 | -------------------------------------------------------------------------------- /src/pages/HR/ComInfoAdd.vue: -------------------------------------------------------------------------------- 1 | 41 | 133 | 164 | -------------------------------------------------------------------------------- /src/components/job-info.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 73 | 74 | 189 | -------------------------------------------------------------------------------- /src/pages/HR/ComInfoEdit.vue: -------------------------------------------------------------------------------- 1 | 41 | 143 | 174 | -------------------------------------------------------------------------------- /src/pages/hr/Job.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 153 | 154 | 198 | -------------------------------------------------------------------------------- /src/pages/my/MySetting.vue: -------------------------------------------------------------------------------- 1 | /** 1.组件上传未完成,头像暂留空;2.MyPage未设置router-view,因此使用fixed样式进行覆盖;3.未添加表单验证**/ 2 | 60 | 61 | 180 | 181 | 278 | -------------------------------------------------------------------------------- /src/pages/search/SearchDetail.vue: -------------------------------------------------------------------------------- 1 | /* author:成都-Treasure email:treasurewmj@foxmail.com version:0.0.1 bug:1.还是没有解决ajax获取的数据无法访问二级对象,把部分内容做成子组件后可以响应 2.没有设计图的图例,因此找不到部分图标,自己选了,也没有字体大小,padding等设置 2 | 3.预留了路由接口,方便后期整合后台 4.文字内容没有设置转换器,用了computed,后期可以直接修改 5.mock数据结构在mock部分 6.组件padding 12px 16px */ 3 | 4 | 5 | 6 | 7 | 57 | 58 | 154 | 155 | 272 | -------------------------------------------------------------------------------- /src/pages/testResumeDetail.vue: -------------------------------------------------------------------------------- 1 | /* author: fridolph email:249121486@qq.com version:0.0.2 2 | bug: 3 | 1. my-control 没有预留接口 就新增一个路由来展示该页 4 | ( localhost:12345/testresume ) 5 | src/router.config.js 完成该页后会去掉 /testresume 6 | 2. mock数据结构在 static/mock/myresumeDetail.json 7 | (由于没加入group,请原谅我在anymock擅自定义数据来测试…) 8 | 3. src/config/config.dev.js 添加了testApiHost,交接好后删掉该项 9 | */ 10 | 11 | 121 | 122 | 198 | 199 | 317 | -------------------------------------------------------------------------------- /src/pages/search/SearchPage.vue: -------------------------------------------------------------------------------- 1 | 60 | 176 | 367 | -------------------------------------------------------------------------------- /static/weui/weui.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * WeUI v1.1.0 (https://github.com/weui/weui) 3 | * Copyright 2016 Tencent, Inc. 4 | * Licensed under the MIT license 5 | */html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{line-height:1.6;font-family:-apple-system-font,Helvetica Neue,sans-serif}*{margin:0;padding:0}a img{border:0}a{text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}@font-face{font-weight:400;font-style:normal;font-family:weui;src:url('data:application/octet-stream;base64,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') format('truetype')}[class*=" weui-icon-"],[class^=weui-icon-]{display:inline-block;vertical-align:middle;font:normal normal normal 14px/1 weui;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}[class*=" weui-icon-"]:before,[class^=weui-icon-]:before{display:inline-block;margin-left:.2em;margin-right:.2em}.weui-icon-circle:before{content:"\EA01"}.weui-icon-download:before{content:"\EA02"}.weui-icon-info:before{content:"\EA03"}.weui-icon-safe_success:before{content:"\EA04"}.weui-icon-safe_warn:before{content:"\EA05"}.weui-icon-success:before{content:"\EA06"}.weui-icon-success-circle:before{content:"\EA07"}.weui-icon-success-no-circle:before{content:"\EA08"}.weui-icon-waiting:before{content:"\EA09"}.weui-icon-waiting-circle:before{content:"\EA0A"}.weui-icon-warn:before{content:"\EA0B"}.weui-icon-info-circle:before{content:"\EA0C"}.weui-icon-cancel:before{content:"\EA0D"}.weui-icon-search:before{content:"\EA0E"}.weui-icon-clear:before{content:"\EA0F"}.weui-icon-back:before{content:"\EA10"}.weui-icon-delete:before{content:"\EA11"}[class*=" weui-icon_"]:before,[class^=weui-icon_]:before{margin:0}.weui-icon-success{font-size:23px;color:#09bb07}.weui-icon-waiting{font-size:23px;color:#10aeff}.weui-icon-warn{font-size:23px;color:#f43530}.weui-icon-info{font-size:23px;color:#10aeff}.weui-icon-success-circle,.weui-icon-success-no-circle{font-size:23px;color:#09bb07}.weui-icon-waiting-circle{font-size:23px;color:#10aeff}.weui-icon-circle{font-size:23px;color:#c9c9c9}.weui-icon-download,.weui-icon-info-circle{font-size:23px;color:#09bb07}.weui-icon-safe-success{color:#09bb07}.weui-icon-safe-warn{color:#ffbe00}.weui-icon-cancel{color:#f43530;font-size:22px}.weui-icon-clear,.weui-icon-search{color:#b2b2b2;font-size:14px}.weui-icon-delete.weui-icon_gallery-delete{color:#fff;font-size:22px}.weui-icon_msg{font-size:93px}.weui-icon_msg.weui-icon-warn{color:#f76260}.weui-icon_msg-primary{font-size:93px}.weui-icon_msg-primary.weui-icon-warn{color:#c9c9c9}.weui-btn{position:relative;display:block;margin-left:auto;margin-right:auto;padding-left:14px;padding-right:14px;box-sizing:border-box;font-size:18px;text-align:center;text-decoration:none;color:#fff;line-height:2.55555556;border-radius:5px;-webkit-tap-highlight-color:rgba(0,0,0,0);overflow:hidden}.weui-btn:after{content:" ";width:200%;height:200%;position:absolute;top:0;left:0;border:1px solid rgba(0,0,0,.2);-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;box-sizing:border-box;border-radius:10px}.weui-btn_inline{display:inline-block}.weui-btn_default{color:#000;background-color:#f8f8f8}.weui-btn_default:not(.weui-btn_disabled):visited{color:#000}.weui-btn_default:not(.weui-btn_disabled):active{color:rgba(0,0,0,.6);background-color:#dedede}.weui-btn_primary{background-color:#1aad19}.weui-btn_primary:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_primary:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#179b16}.weui-btn_warn{background-color:#e64340}.weui-btn_warn:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_warn:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#ce3c39}.weui-btn_disabled{color:hsla(0,0%,100%,.6)}.weui-btn_disabled.weui-btn_default{color:rgba(0,0,0,.3);background-color:#f7f7f7}.weui-btn_disabled.weui-btn_primary{background-color:#9ed99d}.weui-btn_disabled.weui-btn_warn{background-color:#ec8b89}.weui-btn_plain-primary{color:#1aad19;border:1px solid #1aad19}.weui-btn_plain-primary:not(.weui-btn_plain-disabled):active{color:rgba(26,173,25,.6);border-color:rgba(26,173,25,.6)}.weui-btn_plain-primary:after{border-width:0}.weui-btn_plain-default{color:#353535;border:1px solid #353535}.weui-btn_plain-default:not(.weui-btn_plain-disabled):active{color:rgba(53,53,53,.6);border-color:rgba(53,53,53,.6)}.weui-btn_plain-default:after{border-width:0}.weui-btn_plain-disabled{color:rgba(0,0,0,.2);border-color:rgba(0,0,0,.2)}button.weui-btn,input.weui-btn{width:100%;border-width:0;outline:0;-webkit-appearance:none}button.weui-btn:focus,input.weui-btn:focus{outline:0}button.weui-btn_inline,button.weui-btn_mini,input.weui-btn_inline,input.weui-btn_mini{width:auto}button.weui-btn_plain-default,button.weui-btn_plain-primary,input.weui-btn_plain-default,input.weui-btn_plain-primary{border-width:1px;background-color:transparent}.weui-btn_mini{display:inline-block;padding:0 1.32em;line-height:2.3;font-size:13px}.weui-btn+.weui-btn{margin-top:15px}.weui-btn.weui-btn_inline+.weui-btn.weui-btn_inline{margin-top:auto;margin-left:15px}.weui-btn-area{margin:1.17647059em 15px .3em}.weui-btn-area_inline{display:-webkit-box;display:-webkit-flex;display:flex}.weui-btn-area_inline .weui-btn{margin-top:auto;margin-right:15px;width:100%;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-btn-area_inline .weui-btn:last-child{margin-right:0}.weui-cells{margin-top:1.17647059em;background-color:#fff;line-height:1.41176471;font-size:17px;overflow:hidden;position:relative}.weui-cells:before{top:0;border-top:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells:after,.weui-cells:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d9d9d9}.weui-cells:after{bottom:0;border-bottom:1px solid #d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells__title{margin-top:.77em;margin-bottom:.3em;padding-left:15px;padding-right:15px;color:#999;font-size:14px}.weui-cells__title+.weui-cells{margin-top:0}.weui-cells__tips{margin-top:.3em;color:#999;padding-left:15px;padding-right:15px;font-size:14px}.weui-cell{padding:10px 15px;position:relative;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d9d9d9;color:#d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-cell:first-child:before{display:none}.weui-cell_primary{-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start}.weui-cell__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-cell__ft{text-align:right;color:#999}.weui-cell_access{-webkit-tap-highlight-color:rgba(0,0,0,0);color:inherit}.weui-cell_access:active{background-color:#ececec}.weui-cell_access .weui-cell__ft{padding-right:13px;position:relative}.weui-cell_access .weui-cell__ft:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;margin-top:-4px;right:2px}.weui-cell_link{color:#586c94;font-size:14px}.weui-cell_link:first-child:before{display:block}.weui-check__label{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-check__label:active{background-color:#ececec}.weui-check{position:absolute;left:-9999em}.weui-cells_radio .weui-cell__ft{padding-left:.35em}.weui-cells_radio .weui-check:checked+.weui-icon-checked:before{display:block;content:'\EA08';color:#09bb07;font-size:16px}.weui-cells_checkbox .weui-cell__hd{padding-right:.35em}.weui-cells_checkbox .weui-icon-checked:before{content:'\EA01';color:#c9c9c9;font-size:23px;display:block}.weui-cells_checkbox .weui-check:checked+.weui-icon-checked:before{content:'\EA06';color:#09bb07}.weui-label{display:block;width:105px;word-wrap:break-word;word-break:break-all}.weui-input{width:100%;border:0;outline:0;-webkit-appearance:none;background-color:transparent;font-size:inherit;color:inherit;height:1.41176471em;line-height:1.41176471}.weui-input::-webkit-inner-spin-button,.weui-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.weui-textarea{display:block;border:0;resize:none;width:100%;color:inherit;font-size:1em;line-height:inherit;outline:0}.weui-textarea-counter{color:#b2b2b2;text-align:right}.weui-cell_warn .weui-textarea-counter{color:#e64340}.weui-toptips{display:none;position:fixed;-webkit-transform:translateZ(0);transform:translateZ(0);top:0;left:0;right:0;padding:5px;font-size:14px;text-align:center;color:#fff;z-index:5000;word-wrap:break-word;word-break:break-all}.weui-toptips_warn{background-color:#e64340}.weui-cells_form .weui-cell__ft{font-size:0}.weui-cells_form .weui-icon-warn{display:none}.weui-cells_form input,.weui-cells_form label[for],.weui-cells_form textarea{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-cell_warn{color:#e64340}.weui-cell_warn .weui-icon-warn{display:inline-block}.weui-form-preview{position:relative;background-color:#fff}.weui-form-preview:before{top:0;border-top:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview:after,.weui-form-preview:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d9d9d9}.weui-form-preview:after{bottom:0;border-bottom:1px solid #d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__hd{position:relative;padding:10px 15px;text-align:right;line-height:2.5em}.weui-form-preview__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #d9d9d9;color:#d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-form-preview__hd .weui-form-preview__value{font-style:normal;font-size:1.6em}.weui-form-preview__bd{padding:10px 15px;font-size:.9em;text-align:right;color:#999;line-height:2}.weui-form-preview__ft{position:relative;line-height:50px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-form-preview__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__item{overflow:hidden}.weui-form-preview__label{float:left;margin-right:1em;min-width:4em;color:#999;text-align:justify;text-align-last:justify}.weui-form-preview__value{display:block;overflow:hidden;word-break:normal;word-wrap:break-word}.weui-form-preview__btn{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}button.weui-form-preview__btn{background-color:transparent;border:0;outline:0;line-height:inherit;font-size:inherit}.weui-form-preview__btn:active{background-color:#eee}.weui-form-preview__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-form-preview__btn:first-child:after{display:none}.weui-form-preview__btn_default{color:#999}.weui-form-preview__btn_primary{color:#0bb20c}.weui-cell_select{padding:0}.weui-cell_select .weui-select{padding-right:30px}.weui-cell_select .weui-cell__bd:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-select{-webkit-appearance:none;border:0;outline:0;background-color:transparent;width:100%;font-size:inherit;height:44px;line-height:44px;position:relative;z-index:1;padding-left:15px}.weui-cell_select-before{padding-right:15px}.weui-cell_select-before .weui-select{width:105px;box-sizing:border-box}.weui-cell_select-before .weui-cell__hd{position:relative}.weui-cell_select-before .weui-cell__hd:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #d9d9d9;color:#d9d9d9;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-cell_select-before .weui-cell__hd:before{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-cell_select-before .weui-cell__bd{padding-left:15px}.weui-cell_select-before .weui-cell__bd:after{display:none}.weui-cell_select-after{padding-left:15px}.weui-cell_select-after .weui-select{padding-left:0}.weui-cell_vcode{padding-top:0;padding-right:0;padding-bottom:0}.weui-vcode-btn,.weui-vcode-img{margin-left:5px;height:44px;vertical-align:middle}.weui-vcode-btn{display:inline-block;padding:0 .6em 0 .7em;border-left:1px solid #e5e5e5;line-height:44px;font-size:17px;color:#3cc51f}button.weui-vcode-btn{background-color:transparent;border-top:0;border-right:0;border-bottom:0;outline:0}.weui-vcode-btn:active{color:#52a341}.weui-gallery{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000;z-index:1000}.weui-gallery__img{position:absolute;top:0;right:0;bottom:60px;left:0;background:50% no-repeat;background-size:contain}.weui-gallery__opr{position:absolute;right:0;bottom:0;left:0;background-color:#0d0d0d;color:#fff;line-height:60px;text-align:center}.weui-gallery__del{display:block}.weui-cell_switch{padding-top:6px;padding-bottom:6px}.weui-switch{-webkit-appearance:none;appearance:none}.weui-switch,.weui-switch-cp__box{position:relative;width:52px;height:32px;border:1px solid #dfdfdf;outline:0;border-radius:16px;box-sizing:border-box;background-color:#dfdfdf;-webkit-transition:background-color .1s,border .1s;transition:background-color .1s,border .1s}.weui-switch-cp__box:before,.weui-switch:before{content:" ";position:absolute;top:0;left:0;width:50px;height:30px;border-radius:15px;background-color:#fdfdfd;-webkit-transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1),-webkit-transform .35s cubic-bezier(.45,1,.4,1)}.weui-switch-cp__box:after,.weui-switch:after{content:" ";position:absolute;top:0;left:0;width:30px;height:30px;border-radius:15px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);-webkit-transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35),-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35)}.weui-switch-cp__input:checked~.weui-switch-cp__box,.weui-switch:checked{border-color:#04be02;background-color:#04be02}.weui-switch-cp__input:checked~.weui-switch-cp__box:before,.weui-switch:checked:before{-webkit-transform:scale(0);transform:scale(0)}.weui-switch-cp__input:checked~.weui-switch-cp__box:after,.weui-switch:checked:after{-webkit-transform:translateX(20px);transform:translateX(20px)}.weui-switch-cp__input{position:absolute;left:-9999px}.weui-switch-cp__box{display:block}.weui-uploader__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding-bottom:10px;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-uploader__title{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-uploader__info{color:#b2b2b2}.weui-uploader__bd{margin-bottom:-4px;margin-right:-9px;overflow:hidden}.weui-uploader__files{list-style:none}.weui-uploader__file{float:left;margin-right:9px;margin-bottom:9px;width:79px;height:79px;background:no-repeat 50%;background-size:cover}.weui-uploader__file_status{position:relative}.weui-uploader__file_status:before{content:" ";position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.5)}.weui-uploader__file_status .weui-uploader__file-content{display:block}.weui-uploader__file-content{display:none;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff}.weui-uploader__file-content .weui-icon-warn{display:inline-block}.weui-uploader__input-box{float:left;position:relative;margin-right:9px;margin-bottom:9px;width:77px;height:77px;border:1px solid #d9d9d9}.weui-uploader__input-box:after,.weui-uploader__input-box:before{content:" ";position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#d9d9d9}.weui-uploader__input-box:before{width:2px;height:39.5px}.weui-uploader__input-box:after{width:39.5px;height:2px}.weui-uploader__input-box:active{border-color:#999}.weui-uploader__input-box:active:after,.weui-uploader__input-box:active:before{background-color:#999}.weui-uploader__input{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;opacity:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-msg{padding-top:36px;text-align:center}.weui-msg__icon-area{margin-bottom:30px}.weui-msg__text-area{margin-bottom:25px;padding:0 20px}.weui-msg__text-area a{color:#586c94}.weui-msg__title{margin-bottom:5px;font-weight:400;font-size:20px}.weui-msg__desc{font-size:14px;color:#999}.weui-msg__opr-area{margin-bottom:25px}.weui-msg__extra-area{margin-bottom:15px;font-size:14px;color:#999}.weui-msg__extra-area a{color:#586c94}@media screen and (min-height:438px){.weui-msg__extra-area{position:fixed;left:0;bottom:0;width:100%;text-align:center}}.weui-article{padding:20px 15px;font-size:15px}.weui-article section{margin-bottom:1.5em}.weui-article h1{font-size:18px;font-weight:400;margin-bottom:.9em}.weui-article h2{font-size:16px}.weui-article h2,.weui-article h3{font-weight:400;margin-bottom:.34em}.weui-article h3{font-size:15px}.weui-article *{max-width:100%;box-sizing:border-box;word-wrap:break-word}.weui-article p{margin:0 0 .8em}.weui-tabbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;bottom:0;width:100%;background-color:#f7f7fa}.weui-tabbar:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #c0bfc4;color:#c0bfc4;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-tabbar__item{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:5px 0 0;font-size:0;color:#999;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon>i,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__label{color:#09bb07}.weui-tabbar__icon{display:inline-block;width:27px;height:27px}.weui-tabbar__icon>i,i.weui-tabbar__icon{font-size:24px;color:#999}.weui-tabbar__icon img{width:100%;height:100%}.weui-tabbar__label{text-align:center;color:#999;font-size:10px;line-height:1.8}.weui-navbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;top:0;width:100%;background-color:#fafafa}.weui-navbar:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #ccc;color:#ccc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-navbar+.weui-tab__panel{padding-top:50px;padding-bottom:0}.weui-navbar__item{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:13px 0;text-align:center;font-size:15px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-navbar__item:active{background-color:#ededed}.weui-navbar__item.weui-bar__item_on{background-color:#eaeaea}.weui-navbar__item:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #ccc;color:#ccc;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-navbar__item:last-child:after{display:none}.weui-tab{position:relative;height:100%}.weui-tab__panel{box-sizing:border-box;height:100%;padding-bottom:50px;overflow:auto;-webkit-overflow-scrolling:touch}.weui-tab__content{display:none}.weui-progress{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-progress__bar{background-color:#ebebeb;height:3px;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-progress__inner-bar{width:0;height:100%;background-color:#09bb07}.weui-progress__opr{display:block;margin-left:15px;font-size:0}.weui-panel{background-color:#fff;margin-top:10px;position:relative;overflow:hidden}.weui-panel:first-child{margin-top:0}.weui-panel:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel:after,.weui-panel:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-panel:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel__hd{padding:14px 15px 10px;color:#999;font-size:13px;position:relative}.weui-panel__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box{padding:15px;position:relative}.weui-media-box:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box:first-child:before{display:none}a.weui-media-box{color:#000;-webkit-tap-highlight-color:rgba(0,0,0,0)}a.weui-media-box:active{background-color:#ececec}.weui-media-box__title{font-weight:400;font-size:17px;width:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;word-wrap:break-word;word-break:break-all}.weui-media-box__desc{color:#999;font-size:13px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-media-box__info{margin-top:15px;padding-bottom:5px;font-size:13px;color:#cecece;line-height:1em;list-style:none;overflow:hidden}.weui-media-box__info__meta{float:left;padding-right:1em}.weui-media-box__info__meta_extra{padding-left:1em;border-left:1px solid #cecece}.weui-media-box_text .weui-media-box__title{margin-bottom:8px}.weui-media-box_appmsg{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-media-box_appmsg .weui-media-box__hd{margin-right:.8em;width:60px;height:60px;line-height:60px;text-align:center}.weui-media-box_appmsg .weui-media-box__thumb{width:100%;max-height:100%;vertical-align:top}.weui-media-box_appmsg .weui-media-box__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1;min-width:0}.weui-media-box_small-appmsg{padding:0}.weui-media-box_small-appmsg .weui-cells{margin-top:0}.weui-media-box_small-appmsg .weui-cells:before{display:none}.weui-grids{position:relative;overflow:hidden}.weui-grids:before{right:0;height:1px;border-top:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grids:after,.weui-grids:before{content:" ";position:absolute;left:0;top:0;color:#d9d9d9}.weui-grids:after{width:1px;bottom:0;border-left:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid{position:relative;float:left;padding:20px 10px;width:33.33333333%;box-sizing:border-box}.weui-grid:before{top:0;width:1px;border-right:1px solid #d9d9d9;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid:after,.weui-grid:before{content:" ";position:absolute;right:0;bottom:0;color:#d9d9d9}.weui-grid:after{left:0;height:1px;border-bottom:1px solid #d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grid:active{background-color:#ececec}.weui-grid__icon{width:28px;height:28px;margin:0 auto}.weui-grid__icon img{display:block;width:100%;height:100%}.weui-grid__icon+.weui-grid__label{margin-top:5px}.weui-grid__label{display:block;color:#000;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.weui-footer,.weui-grid__label{text-align:center;font-size:14px}.weui-footer{color:#999}.weui-footer a{color:#586c94}.weui-footer_fixed-bottom{position:fixed;bottom:.52em;left:0;right:0}.weui-footer__links{font-size:0}.weui-footer__link{display:inline-block;vertical-align:top;margin:0 .62em;position:relative;font-size:14px}.weui-footer__link:before{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #c7c7c7;color:#c7c7c7;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5);left:-.65em;top:.36em;bottom:.36em}.weui-footer__link:first-child:before{display:none}.weui-footer__text{padding:0 .34em;font-size:12px}.weui-flex{display:-webkit-box;display:-webkit-flex;display:flex}.weui-flex__item{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-dialog{position:fixed;z-index:5000;width:80%;max-width:300px;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#fff;text-align:center;border-radius:3px;overflow:hidden}.weui-dialog__hd{padding:1.3em 1.6em .5em}.weui-dialog__title{font-weight:400;font-size:18px}.weui-dialog__bd{padding:0 1.6em .8em;min-height:40px;font-size:15px;line-height:1.3;word-wrap:break-word;word-break:break-all;color:#999}.weui-dialog__bd:first-child{padding:2.7em 20px 1.7em;color:#353535}.weui-dialog__ft{position:relative;line-height:48px;font-size:18px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-dialog__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-dialog__btn{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0);position:relative}.weui-dialog__btn:active{background-color:#eee}.weui-dialog__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-dialog__btn:first-child:after{display:none}.weui-dialog__btn_default{color:#353535}.weui-dialog__btn_primary{color:#0bb20c}.weui-skin_android .weui-dialog{text-align:left;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-dialog__title{font-size:21px}.weui-skin_android .weui-dialog__hd{text-align:left}.weui-skin_android .weui-dialog__bd{color:#999;padding:.25em 1.6em 2em;font-size:17px;text-align:left}.weui-skin_android .weui-dialog__bd:first-child{padding:1.6em 1.6em 2em;color:#353535}.weui-skin_android .weui-dialog__ft{display:block;text-align:right;line-height:42px;font-size:16px;padding:0 1.6em .7em}.weui-skin_android .weui-dialog__ft:after{display:none}.weui-skin_android .weui-dialog__btn{display:inline-block;vertical-align:top;padding:0 .8em}.weui-skin_android .weui-dialog__btn:after{display:none}.weui-skin_android .weui-dialog__btn:active,.weui-skin_android .weui-dialog__btn:visited{background-color:rgba(0,0,0,.06)}.weui-skin_android .weui-dialog__btn:last-child{margin-right:-.8em}.weui-skin_android .weui-dialog__btn_default{color:gray}@media screen and (min-width:1024px){.weui-dialog{width:35%}}.weui-toast{position:fixed;z-index:5000;width:7.6em;min-height:7.6em;top:180px;left:50%;margin-left:-3.8em;background:rgba(40,40,40,.75);text-align:center;border-radius:5px;color:#fff}.weui-icon_toast{margin:22px 0 0;display:block}.weui-icon_toast.weui-icon-success-no-circle:before{color:#fff;font-size:55px}.weui-icon_toast.weui-loading{margin:30px 0 0;width:38px;height:38px;vertical-align:baseline}.weui-toast__content{margin:0 0 15px}.weui-mask{background:rgba(0,0,0,.6)}.weui-mask,.weui-mask_transparent{position:fixed;z-index:1000;top:0;right:0;left:0;bottom:0}.weui-actionsheet{position:fixed;left:0;bottom:0;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:5000;width:100%;background-color:#efeff4;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-actionsheet__menu{background-color:#fff}.weui-actionsheet__action{margin-top:6px;background-color:#fff}.weui-actionsheet__cell{position:relative;padding:10px 0;text-align:center;font-size:18px}.weui-actionsheet__cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d9d9d9;color:#d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-actionsheet__cell:active{background-color:#ececec}.weui-actionsheet__cell:first-child:before{display:none}.weui-skin_android .weui-actionsheet{position:fixed;left:50%;top:50%;bottom:auto;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:274px;box-sizing:border-box;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:transparent;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-skin_android .weui-actionsheet__action{display:none}.weui-skin_android .weui-actionsheet__menu{border-radius:2px;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-actionsheet__cell{padding:13px 24px;font-size:16px;line-height:1.4;text-align:left}.weui-skin_android .weui-actionsheet__cell:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.weui-skin_android .weui-actionsheet__cell:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.weui-actionsheet_toggle{-webkit-transform:translate(0);transform:translate(0)}.weui-loadmore{width:65%;margin:1.5em auto;line-height:1.6em;font-size:14px;text-align:center}.weui-loadmore__tips{display:inline-block;vertical-align:middle}.weui-loadmore_line{border-top:1px solid #e5e5e5;margin-top:2.4em}.weui-loadmore_line .weui-loadmore__tips{position:relative;top:-.9em;padding:0 .55em;background-color:#fff;color:#999}.weui-loadmore_dot .weui-loadmore__tips{padding:0 .16em}.weui-loadmore_dot .weui-loadmore__tips:before{content:" ";width:4px;height:4px;border-radius:50%;background-color:#e5e5e5;display:inline-block;position:relative;vertical-align:0;top:-.16em}.weui-badge{display:inline-block;padding:.15em .4em;min-width:8px;border-radius:18px;background-color:#e64340;color:#fff;line-height:1.2;text-align:center;font-size:12px;vertical-align:middle}.weui-badge_dot{padding:.4em;min-width:0}.weui-search-bar{position:relative;padding:8px 10px;display:-webkit-box;display:-webkit-flex;display:flex;box-sizing:border-box;background-color:#efeff4}.weui-search-bar:before{top:0;border-top:1px solid #d7d6dc;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar:after,.weui-search-bar:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d7d6dc}.weui-search-bar:after{bottom:0;border-bottom:1px solid #d7d6dc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__cancel-btn{display:block}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__label{display:none}.weui-search-bar__form{position:relative;-webkit-box-flex:1;-webkit-flex:auto;flex:auto;background-color:#efeff4}.weui-search-bar__form:after{content:'';position:absolute;left:0;top:0;width:200%;height:200%;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;border-radius:10px;border:1px solid #e6e6ea;box-sizing:border-box;background:#fff}.weui-search-bar__box{position:relative;padding-left:30px;padding-right:30px;height:100%;width:100%;box-sizing:border-box;z-index:1}.weui-search-bar__box .weui-search-bar__input{padding:4px 0;width:100%;height:1.42857143em;border:0;font-size:14px;line-height:1.42857143em;box-sizing:content-box;background:transparent}.weui-search-bar__box .weui-search-bar__input:focus{outline:none}.weui-search-bar__box .weui-icon-search{position:absolute;left:10px;top:0;line-height:28px}.weui-search-bar__box .weui-icon-clear{position:absolute;top:0;right:0;padding:0 10px;line-height:28px}.weui-search-bar__label{position:absolute;top:1px;right:1px;bottom:1px;left:1px;z-index:2;border-radius:3px;text-align:center;color:#9b9b9b;background:#fff}.weui-search-bar__label span{display:inline-block;font-size:14px;vertical-align:middle}.weui-search-bar__label .weui-icon-search{margin-right:5px}.weui-search-bar__cancel-btn{display:none;margin-left:10px;line-height:28px;color:#09bb07;white-space:nowrap}.weui-search-bar__input:not(:valid)~.weui-icon-clear{display:none}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none}.weui-picker{position:fixed;width:100%;left:0;bottom:0;z-index:5000;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-picker__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding:10px 15px;background-color:#fbf9fe;position:relative;text-align:center}.weui-picker__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__action{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#586c94}.weui-picker__action:first-child{text-align:left}.weui-picker__action:last-child{text-align:right}.weui-picker__bd{display:-webkit-box;display:-webkit-flex;display:flex;position:relative;background-color:#fff;height:238px;overflow:hidden}.weui-picker__group{-webkit-box-flex:1;-webkit-flex:1;flex:1;position:relative;height:100%}.weui-picker__mask{top:0;height:100%;margin:0 auto;background:-webkit-linear-gradient(top,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),-webkit-linear-gradient(bottom,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background:linear-gradient(180deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),linear-gradient(0deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background-position:top,bottom;background-size:100% 102px;background-repeat:no-repeat;-webkit-transform:translateZ(0);transform:translateZ(0)}.weui-picker__indicator,.weui-picker__mask{position:absolute;left:0;width:100%;z-index:3}.weui-picker__indicator{height:34px;top:102px}.weui-picker__indicator:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__indicator:after,.weui-picker__indicator:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-picker__indicator:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__content{position:absolute;top:0;left:0;width:100%}.weui-picker__item{padding:5px 0 4px;text-align:center;color:#000;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.weui-picker__item_disabled{color:#999}@-webkit-keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.weui-animate-slide-up{-webkit-animation:a ease .3s forwards;animation:a ease .3s forwards}@-webkit-keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.weui-animate-slide-down{-webkit-animation:b ease .3s forwards;animation:b ease .3s forwards}@-webkit-keyframes c{0%{opacity:0}to{opacity:1}}@keyframes c{0%{opacity:0}to{opacity:1}}.weui-animate-fade-in{-webkit-animation:c ease .3s forwards;animation:c ease .3s forwards}@-webkit-keyframes d{0%{opacity:1}to{opacity:0}}@keyframes d{0%{opacity:1}to{opacity:0}}.weui-animate-fade-out{-webkit-animation:d ease .3s forwards;animation:d ease .3s forwards}.weui-agree{display:block;padding:.5em 15px;font-size:13px}.weui-agree a{color:#586c94}.weui-agree__text{color:#999}.weui-agree__checkbox{-webkit-appearance:none;appearance:none;outline:0;font-size:0;border:1px solid #d1d1d1;background-color:#fff;border-radius:3px;width:13px;height:13px;position:relative;vertical-align:0;top:2px}.weui-agree__checkbox:checked:before{font-family:weui;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-align:center;speak:none;display:inline-block;vertical-align:middle;text-decoration:inherit;content:"\EA08";color:#09bb07;font-size:13px;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-48%) scale(.73);transform:translate(-50%,-48%) scale(.73)}.weui-agree__checkbox:disabled{background-color:#e1e1e1}.weui-agree__checkbox:disabled:before{color:#adadad}.weui-loading{width:20px;height:20px;display:inline-block;vertical-align:middle;-webkit-animation:e 1s steps(12) infinite;animation:e 1s steps(12) infinite;background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;background-size:100%}@-webkit-keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.weui-slider{padding:15px 18px;-webkit-user-select:none;user-select:none}.weui-slider__inner{position:relative;height:2px;background-color:#e9e9e9}.weui-slider__track{height:2px;background-color:#1aad19;width:0}.weui-slider__handler{position:absolute;left:0;top:50%;width:28px;height:28px;margin-left:-14px;margin-top:-14px;border-radius:50%;background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.2)}.weui-slider-box{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-slider-box .weui-slider{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-slider-box__value{margin-left:.5em;min-width:24px;color:#888;text-align:center;font-size:14px} --------------------------------------------------------------------------------