├── 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 |
2 | 404
3 |
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 |
8 |
9 |
10 |
11 |
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 |
2 |
3 |
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 |
2 |
3 |
4 |
5 |
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 |
2 |
3 |
Message
4 |
5 |
6 |
7 |
18 |
--------------------------------------------------------------------------------
/src/pages/search/SearchFilter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
搜索
4 |
5 |
6 |
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 |
9 | {{content}}
10 |
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 |
17 |
18 |
19 |
20 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
36 |
--------------------------------------------------------------------------------
/src/pages/search/company-detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{companyModel[0]}}
6 |
7 |
{{companyModel[1]}}
8 |
9 |
10 |
11 |
24 |
25 |
45 |
--------------------------------------------------------------------------------
/src/components/filterSearch/filter-item.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
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 |
2 |
3 |
{{ input.title }}
4 |
12 |
13 |
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 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
46 |
47 |
52 |
--------------------------------------------------------------------------------
/src/pages/LayoutPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
9 |
10 |
12 |
14 |
15 |
17 |
19 |
20 |
22 |
24 |
25 |
26 |
27 |
28 |
51 |
--------------------------------------------------------------------------------
/docs/开发规范汇总.md:
--------------------------------------------------------------------------------
1 | # 0x0、版本描述
2 |
3 | ### 版本发布记录
4 |
5 | v0.0.1 2017-1-22 13:30 初稿,根据现有代码进行归类,综合
6 |
7 | ### 开发规范贡献者
8 |
9 |
10 |
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 |
2 |
10 |
11 |
53 |
56 |
--------------------------------------------------------------------------------
/src/pages/my/MyPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
51 |
60 |
--------------------------------------------------------------------------------
/src/pages/my/my-control.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
12 |
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 |
2 |
3 |
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 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{badgeText}}
32 |
33 | {{label}}
34 |
35 |
36 |
63 |
--------------------------------------------------------------------------------
/src/pages/hr/SelectEle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
43 |
44 |
63 |
--------------------------------------------------------------------------------
/src/vw-ui/components/actionsheet/actionsheet.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
25 |
64 |
--------------------------------------------------------------------------------
/src/pages/hr/JobOpr.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
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 |
2 |
3 |
6 |
13 |
14 |
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 |
2 |
3 |
4 |
5 |
工作地点
6 |
{{address}}
7 |
8 |
9 |
职位描述
10 |
{{editText}}
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
75 |
--------------------------------------------------------------------------------
/src/vw-ui/components/toast/toast.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
30 |
{{content}}
31 |
32 |
33 |
34 |
71 |
--------------------------------------------------------------------------------
/src/components/job-navbar.vue:
--------------------------------------------------------------------------------
1 | n
2 |
3 |
4 |
5 | 热招中
6 |
7 |
8 | 已下线
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
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 |
14 |
34 |
35 |
36 |
76 |
--------------------------------------------------------------------------------
/src/pages/hr/VDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ dialog.title }}
7 |
{{ dialog.content }}
8 |
11 |
12 |
13 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
{{ myInfoData.title }}
8 |
{{ myInfoData.experience }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
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 | 
69 | [hstarorg](https://github.com/hstarorg)
70 |
71 | 
72 | [mabelyong](https://github.com/mabelyong)
73 |
74 | 
75 | [MrTreasure](https://github.com/MrTreasure)
76 |
77 | 
78 | [jikeytang](https://github.com/jikeytang)
79 |
80 | 
81 | [yelingfeng](https://github.com/yelingfeng)
82 |
83 | 
84 | [zerosrat](https://github.com/zerosrat)
85 |
--------------------------------------------------------------------------------
/src/components/job-item.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
{{item.name}}
7 |
{{item.company.name}}
8 |
{{item.position}}/{{item.year}}/{{item.education}}
9 |
10 |
11 |
12 | {{item.money}}
13 | {{item.company.lastUpdateDate | dateTime}}
14 |
15 |
16 |
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 |
2 |
3 |
4 |
5 |
6 |
64 |
101 |
--------------------------------------------------------------------------------
/src/pages/home/HomeSearch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 当前搜索:
5 | {{info[0]}}/
6 | {{info[1]}}/
7 | {{info[2]}}
8 |
9 |
15 |
16 | 返回
17 |
18 |
19 |
20 |
21 |
22 |
23 |
85 |
86 |
99 |
--------------------------------------------------------------------------------
/src/vw-ui/components/slider/slider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
{{innerValue}}
10 |
11 |
12 |
77 |
--------------------------------------------------------------------------------
/src/vw-ui/components/swipe/swipe.vue:
--------------------------------------------------------------------------------
1 |
29 |
30 |
39 |
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 |
2 |
3 | Type:
4 |
9 |
14 |
19 |
Disabled:
20 |
22 |
Plain:
23 |
25 |
Mini:
26 |
28 |
页面操作
33 |
34 |
Toast
35 |
{{sv}}
36 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 |
55 |
56 |
58 |
59 |
60 |
61 |
62 |
64 |
66 |
67 |
69 |
71 |
72 |
74 |
76 |
77 |
79 |
81 |
82 |
83 |
84 |
85 |
111 |
--------------------------------------------------------------------------------
/src/pages/my/collected-job.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{job.name}}
10 |
11 |
12 | {{job.city}}
13 |
14 |
15 | {{job.comName}}
16 |
17 |
18 |
19 | {{job.salary}}
20 |
21 |
22 |
23 |
24 | 取消收藏
25 |
26 |
27 | 发送简历
28 |
29 |
30 |
31 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
44 |
45 |
46 |
103 |
173 |
--------------------------------------------------------------------------------
/src/pages/HR/ComInfoAdd.vue:
--------------------------------------------------------------------------------
1 |
2 |
40 |
41 |
133 |
164 |
--------------------------------------------------------------------------------
/src/components/job-info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
LOGO
5 |
6 |
7 | {{ job.jobName }}
8 |
11 | {{ infoType }}
12 |
13 |
14 |
{{ job.jobInfo.date | format }}
15 |
16 |
17 |
{{ job.jobAddress }}
18 |
{{ job.jobCompensation }}
19 |
20 |
21 |
22 | 要求{{ job.jobExperience }}年工作经验
23 | {{ job.companyName }}
24 |
25 |
26 |
27 |
28 |
73 |
74 |
189 |
--------------------------------------------------------------------------------
/src/pages/HR/ComInfoEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
40 |
41 |
143 |
174 |
--------------------------------------------------------------------------------
/src/pages/hr/Job.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
153 |
154 |
198 |
--------------------------------------------------------------------------------
/src/pages/my/MySetting.vue:
--------------------------------------------------------------------------------
1 | /** 1.组件上传未完成,头像暂留空;2.MyPage未设置router-view,因此使用fixed样式进行覆盖;3.未添加表单验证**/
2 |
3 |
4 |
5 |
6 |
7 | 用户头像
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 昵称
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 性别
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 职业身份
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 手机号码修改
49 |
50 |
51 |
52 |
53 |
54 |
55 | 保存
56 | 取消
57 |
58 |
59 |
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 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
{{comDetail.name}}
15 |
16 |
17 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 投简历
50 |
51 |
52 |
53 |
54 |
55 |
56 |
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 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
{{name}}
19 |
{{subtitle}}
20 |
21 |
22 |
23 |
24 |
25 | 基本信息
26 |
27 |
28 |
期望职位
29 |
{{baseInfo.expectJob}}
30 |
31 |
32 |
工作年限
33 |
{{baseInfo.careerYear}}
34 |
35 |
36 |
出生年月
37 |
{{baseInfo.birthDate}}
38 |
39 |
40 |
所在城市
41 |
{{baseInfo.presentAddress}}
42 |
43 |
44 |
联系电话
45 |
{{baseInfo.phone}}
46 |
47 |
48 |
联系邮箱
49 |
{{baseInfo.email}}
50 |
51 |
52 |
53 |
54 |
55 | 期望工作
56 |
57 |
58 |
期望职位
59 |
{{expectJob.post}}
60 |
61 |
62 |
工作性质
63 |
{{expectJob.category}}
64 |
65 |
66 |
期望城市
67 |
{{expectJob.city}}
68 |
69 |
70 |
71 |
72 |
73 |
74 | 职业技能
75 |
76 |
77 | {{jobDetail}}
78 |
79 |
80 |
81 |
82 |
83 |
84 | 工作经历
85 |
86 |
87 | {{workExperience}}
88 |
89 |
90 |
91 |
92 |
93 | 作品展示
94 |
95 |
96 | {{worksShow}}
97 |
98 |
99 |
100 |
101 |
102 | 擅长技术
103 |
104 |
105 |
{{skill.skill}}
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | 修改简历
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
198 |
199 |
317 |
--------------------------------------------------------------------------------
/src/pages/search/SearchPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ selectedCity }}
7 |
8 |
9 |
11 |
12 |
13 |
取消
14 |
15 |
21 |
58 |
59 |
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}
--------------------------------------------------------------------------------