xiejiacheng 5 years ago
commit
448c27b878

+ 0 - 0
.env


+ 33 - 0
.eslintrc.js

@@ -0,0 +1,33 @@
+// https://eslint.org/docs/user-guide/configuring
+
+module.exports = {
+  root: true,
+  env: {
+    node: true,
+  },
+  extends: ['plugin:vue/essential', '@vue/prettier'],
+  plugins: ['vue'],
+  rules: {
+    'max-len': [
+      'warn',
+      {
+        code: 250,
+      },
+    ],
+    'no-unused-vars': 'off',
+    'no-console': 'off',
+    'prettier/prettier': [
+      'warn',
+      {
+        singleQuote: true,
+        trailingComma: 'es5',
+        bracketSpacing: true,
+        jsxBracketSameLine: true,
+        printWidth: 160,
+      },
+    ],
+  },
+  parserOptions: {
+    parser: 'babel-eslint',
+  },
+};

+ 21 - 0
.gitignore

@@ -0,0 +1,21 @@
+.DS_Store
+node_modules
+/dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 29 - 0
README.md

@@ -0,0 +1,29 @@
+# web-moban
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Run your tests
+```
+npm run test
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 3 - 0
babel.config.js

@@ -0,0 +1,3 @@
+module.exports = {
+  presets: ["@vue/cli-plugin-babel/preset"]
+};

File diff suppressed because it is too large
+ 11661 - 0
package-lock.json


+ 58 - 0
package.json

@@ -0,0 +1,58 @@
+{
+  "name": "web-moban",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.19.0",
+    "core-js": "^3.3.2",
+    "element-ui": "^2.12.0",
+    "lodash": "^4.17.15",
+    "naf-core": "^0.1.2",
+    "vue": "^2.6.10",
+    "vue-meta": "^2.3.1",
+    "vue-router": "^3.1.3",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.0.0",
+    "@vue/cli-plugin-eslint": "^4.0.0",
+    "@vue/cli-service": "^4.0.0",
+    "@vue/eslint-config-prettier": "^5.0.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^5.16.0",
+    "eslint-plugin-prettier": "^3.1.1",
+    "eslint-plugin-vue": "^5.0.0",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "prettier": "^1.18.2",
+    "vue-template-compiler": "^2.6.10"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "@vue/prettier"
+    ],
+    "rules": {},
+    "parserOptions": {
+      "parser": "babel-eslint"
+    }
+  },
+  "postcss": {
+    "plugins": {
+      "autoprefixer": {}
+    }
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}

BIN
public/favicon.ico


+ 17 - 0
public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title>web-moban</title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but web-moban doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 12 - 0
src/App.vue

@@ -0,0 +1,12 @@
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+
+<style lang="less">
+body {
+  margin: 0;
+  padding: 0;
+}
+</style>

BIN
src/assets/logo.png


+ 18 - 0
src/main.js

@@ -0,0 +1,18 @@
+import Vue from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store';
+import '@/plugins/element.js';
+import '@/plugins/axios';
+import '@/plugins/check-res';
+import '@/plugins/meta';
+import '@/plugins/filters';
+import '@/plugins/loading';
+
+Vue.config.productionTip = false;
+
+new Vue({
+  router,
+  store,
+  render: h => h(App),
+}).$mount('#app');

+ 19 - 0
src/plugins/axios.js

@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import AxiosWrapper from '@/util/axios-wrapper';
+
+const Plugin = {
+  install(vue, options) {
+    // 3. 注入组件
+    vue.mixin({
+      created() {
+        if (this.$store && !this.$store.$axios) {
+          this.$store.$axios = this.$axios;
+        }
+      },
+    });
+    // 4. 添加实例方法
+    vue.prototype.$axios = new AxiosWrapper(options);
+  },
+};
+
+Vue.use(Plugin, { baseUrl: process.env.VUE_APP_AXIOS_BASE_URL });

+ 39 - 0
src/plugins/check-res.js

@@ -0,0 +1,39 @@
+/* eslint-disable no-underscore-dangle */
+/* eslint-disable no-param-reassign */
+/* eslint-disable no-unused-vars */
+/* eslint-disable no-shadow */
+import Vue from 'vue';
+import _ from 'lodash';
+import { Message } from 'element-ui';
+
+const vm = new Vue({});
+const Plugin = {
+  install(Vue, options) {
+    // 4. 添加实例方法
+    Vue.prototype.$checkRes = (res, okText, errText) => {
+      let _okText = okText;
+      let _errText = errText;
+      if (!_.isFunction(okText) && _.isObject(okText) && okText != null) {
+        ({ okText: _okText, errText: _errText } = okText);
+      }
+      const { errcode = 0, errmsg } = res || {};
+      if (errcode === 0) {
+        if (_.isFunction(_okText)) {
+          return _okText();
+        }
+        if (_okText) {
+          Message.success(_okText);
+        }
+        return true;
+      }
+      if (_.isFunction(_errText)) {
+        return _errText();
+      }
+      Message.error(_errText || errmsg);
+      // Message({ message: _errText || errmsg, duration: 60000 });
+      return false;
+    };
+  },
+};
+
+Vue.use(Plugin);

+ 5 - 0
src/plugins/element.js

@@ -0,0 +1,5 @@
+import Vue from 'vue';
+import Element from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+
+Vue.use(Element);

+ 6 - 0
src/plugins/filters.js

@@ -0,0 +1,6 @@
+import Vue from 'vue';
+import filters from '@/util/filters';
+
+for (const method in filters) {
+  Vue.filter(method, filters[method]);
+}

+ 27 - 0
src/plugins/loading.js

@@ -0,0 +1,27 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import Vue from 'vue';
+
+const Plugin = {
+  // eslint-disable-next-line no-unused-vars
+  install(vue, options) {
+    // 3. 注入组件
+    vue.mixin({
+      created() {
+        // eslint-disable-next-line no-underscore-dangle
+        const isRoot = this.constructor === Vue;
+        // console.log(`rootId:${rootVue_uid}; thisId:${this._uid}`);
+        // if (rootVue_uid !== 3) {
+        //   console.log(this);
+        // }
+        if (isRoot) {
+          const el = document.getElementById('loading');
+          if (el) el.style.display = 'none';
+        }
+      },
+    });
+  },
+};
+
+Vue.use(Plugin, { baseUrl: process.env.VUE_APP_AXIOS_BASE_URL });

+ 4 - 0
src/plugins/meta.js

@@ -0,0 +1,4 @@
+import Vue from 'vue';
+import Meta from 'vue-meta';
+
+Vue.use(Meta);

+ 65 - 0
src/plugins/stomp.js

@@ -0,0 +1,65 @@
+/**
+ * 基于WebStomp的消息处理插件
+ */
+
+import Vue from 'vue';
+import _ from 'lodash';
+import assert from 'assert';
+import { Client } from '@stomp/stompjs/esm5/client';
+
+const Plugin = {
+  install(Vue, options) {
+    assert(_.isObject(options));
+    if (options.debug && !_.isFunction(options.debug)) {
+      options.debug = str => {
+        console.log(str);
+      };
+    }
+    assert(_.isString(options.brokerURL));
+    if (!options.brokerURL.startsWith('ws://')) {
+      options.brokerURL = `ws://${location.host}${options.brokerURL}`;
+    }
+
+    // 3. 注入组件
+    Vue.mixin({
+      beforeDestroy: function() {
+        if (this.$stompClient) {
+          this.$stompClient.deactivate();
+          delete this.$stompClient;
+        }
+      },
+    });
+
+    // 4. 添加实例方法
+    Vue.prototype.$stomp = function(subscribes = {}) {
+      // connect to mq
+      const client = new Client(options);
+      client.onConnect = frame => {
+        // Do something, all subscribes must be done is this callback
+        // This is needed because this will be executed after a (re)connect
+        console.log('[stomp] connected');
+        Object.keys(subscribes)
+          .filter(p => _.isFunction(subscribes[p]))
+          .forEach(key => {
+            client.subscribe(key, subscribes[key]);
+          });
+      };
+
+      client.onStompError = frame => {
+        // Will be invoked in case of error encountered at Broker
+        // Bad login/passcode typically will cause an error
+        // Complaint brokers will set `message` header with a brief message. Body may contain details.
+        // Compliant brokers will terminate the connection after any error
+        console.log('Broker reported error: ' + frame.headers['message']);
+        console.log('Additional details: ' + frame.body);
+      };
+
+      client.activate();
+
+      this.$stompClient = client;
+    };
+  },
+};
+export default () => {
+  Vue.use(Plugin, Vue.config.stomp);
+};

+ 14 - 0
src/router/index.js

@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import Router from 'vue-router';
+
+Vue.use(Router);
+
+export default new Router({
+  routes: [
+    {
+      path: '/',
+      name: 'index',
+      component: () => import('../views/index.vue'),
+    },
+  ],
+});

+ 11 - 0
src/store/index.js

@@ -0,0 +1,11 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+  state: {},
+  mutations: {},
+  actions: {},
+  modules: {},
+});

+ 114 - 0
src/util/axios-wrapper.js

@@ -0,0 +1,114 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import _ from 'lodash';
+import Axios from 'axios';
+import { Util, Error } from 'naf-core';
+// import { Indicator } from 'mint-ui';
+import util from './user-util';
+
+const { trimData, isNullOrUndefined } = Util;
+const { ErrorCode } = Error;
+
+let currentRequests = 0;
+
+export default class AxiosWrapper {
+  constructor({ baseUrl = '', unwrap = true } = {}) {
+    this.baseUrl = baseUrl;
+    this.unwrap = unwrap;
+  }
+
+  // 替换uri中的参数变量
+  static merge(uri, query = {}) {
+    if (!uri.includes(':')) {
+      return uri;
+    }
+    const keys = [];
+    const regexp = /\/:([a-z0-9_]+)/gi;
+    let res;
+    // eslint-disable-next-line no-cond-assign
+    while ((res = regexp.exec(uri)) != null) {
+      keys.push(res[1]);
+    }
+    keys.forEach(key => {
+      if (!isNullOrUndefined(query[key])) {
+        uri = uri.replace(`:${key}`, query[key]);
+      }
+    });
+    return uri;
+  }
+
+  $get(uri, query, options) {
+    return this.$request(uri, null, query, options);
+  }
+
+  $post(uri, data = {}, query, options) {
+    return this.$request(uri, data, query, options);
+  }
+
+  async $request(uri, data, query, options) {
+    // TODO: 合并query和options
+    if (_.isObject(query) && _.isObject(options)) {
+      options = { ...options, params: query, method: 'get' };
+    } else if (_.isObject(query) && !query.params) {
+      options = { params: query };
+    } else if (_.isObject(query) && query.params) {
+      options = query;
+    }
+    if (!options) options = {};
+    if (options.params) options.params = trimData(options.params);
+    const url = AxiosWrapper.merge(uri, options.params);
+    currentRequests += 1;
+    // Indicator.open({
+    //   spinnerType: 'fading-circle',
+    // });
+
+    try {
+      const axios = Axios.create({
+        baseURL: this.baseUrl,
+      });
+      axios.defaults.headers.common.Authorization = util.token;
+      let res = await axios.request({
+        method: isNullOrUndefined(data) ? 'get' : 'post',
+        url,
+        data,
+        responseType: 'json',
+        ...options,
+      });
+      res = res.data;
+      const { errcode, errmsg, details } = res;
+      if (errcode) {
+        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`);
+        return res;
+      }
+      // unwrap data
+      if (this.unwrap) {
+        res = _.omit(res, ['errcode', 'errmsg', 'details']);
+        const keys = Object.keys(res);
+        if (keys.length === 1 && keys.includes('data')) {
+          res = res.data;
+        }
+      }
+      return res;
+    } catch (err) {
+      let errmsg = '接口请求失败,请稍后重试';
+      if (err.response) {
+        const { status } = err.response;
+        if (status === 401) errmsg = '用户认证失败,请重新登录';
+        if (status === 403) errmsg = '当前用户不允许执行该操作';
+      }
+      console.error(
+        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
+        ${err.message}`
+      );
+      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message };
+    } finally {
+    /* eslint-disable */
+      currentRequests -= 1;
+      if (currentRequests <= 0) {
+        currentRequests = 0;
+        // Indicator.close();
+      }
+    }
+  }
+}

+ 10 - 0
src/util/filters.js

@@ -0,0 +1,10 @@
+import _ from 'lodash';
+
+const filters = {
+  getName(object) {
+    const { data, searchItem } = object;
+    return _.get(data, searchItem) === undefined ? '' : _.get(data, searchItem);
+  },
+};
+
+export default filters;

+ 50 - 0
src/util/methods-util.js

@@ -0,0 +1,50 @@
+import { Util } from 'naf-core';
+
+const { isNullOrUndefined } = Util;
+
+export default {
+  //判断信息是否过期
+  isDateOff(dataDate) {
+    const now = new Date(new Date().getTime() - 24 * 60 * 60 * 1000);
+    dataDate = new Date(dataDate);
+    return now.getTime() <= dataDate.getTime();
+  },
+  //判断企业是否可以执行此动作/显示
+  checkCorp(data) {
+    const { role, unit, selfUnit, status, displayType, userid } = data;
+    if (!isNullOrUndefined(selfUnit) && !isNullOrUndefined(status)) {
+      return role === 'corp' && selfUnit === unit && status === '0';
+    } else if (!isNullOrUndefined(displayType)) {
+      if (role === 'corp') {
+        return role === displayType;
+      } else {
+        return role === displayType && !isNullOrUndefined(userid);
+      }
+    }
+  },
+  //获取url的参数params
+  getParams() {
+    let str = location.href;
+    let num = str.indexOf('?');
+    const param = {};
+    str = str.substr(num + 1);
+    let num2 = str.indexOf('#');
+    let str2 = '';
+    if (num2 > 0) {
+      str2 = str.substr(0, num2);
+    } else {
+      num2 = str.indexOf('/');
+      str2 = str.substr(0, num2);
+    }
+    const arr = str2.split('&');
+    for (let i = 0; i < arr.length; i++) {
+      num = arr[i].indexOf('=');
+      if (num > 0) {
+        const name = arr[i].substring(0, num);
+        const value = arr[i].substr(num + 1);
+        param[name] = decodeURI(value);
+      }
+    }
+    return param;
+  },
+};

+ 47 - 0
src/util/optionTitles.js

@@ -0,0 +1,47 @@
+export const JOBFAIR_TITLE = [
+  { prop: 'subject', label: '' },
+  { prop: 'address', label: '举办地址' },
+  { prop: 'date', label: '举办日期' },
+  { prop: 'unit', label: '分站信息' },
+];
+
+export const CAMPUS_TITLE = [
+  { prop: 'subject', label: '' },
+  { prop: 'address', label: '举办地址' },
+  { prop: 'status', label: '审核状态' },
+  { prop: 'date', label: '举办日期' },
+  { prop: 'unit', label: '分站信息' },
+];
+
+export const JOBINFO_TITLE = [
+  { prop: 'title', label: '' },
+  { prop: 'count', label: '需求人数' },
+  { prop: 'nature.name', label: '工作性质' },
+  { prop: 'salary.name', label: '薪资待遇' },
+  { prop: 'xlreqs.name', label: '最低学历' },
+  { prop: 'city.name', label: '所在城市' },
+  // { prop: 'expired', label: '状态' },
+];
+
+export const RESUME_TITLE = [{ prop: 'title', label: '' }];
+
+export const LETTER_TITLE = [
+  { prop: 'title', label: '' },
+  { prop: 'corpname', label: '企业名称' },
+  { prop: 'type', label: '类型' },
+  { prop: 'status', label: '状态' },
+];
+
+export const TICKET_TITLE = [
+  { prop: 'subject', label: '' },
+  { prop: 'type', label: '门票类型' },
+  { prop: 'origin', label: '' },
+  { prop: 'date', label: '举办日期' },
+];
+
+export const CORP_JOBFAIR = [
+  { prop: 'subject', label: '' },
+  { prop: 'time', label: '举办时间' },
+  { prop: 'date', label: '举办日期' },
+  { prop: 'unit', label: '分站信息' },
+];

+ 69 - 0
src/util/user-util.js

@@ -0,0 +1,69 @@
+/* eslint-disable no-console */
+export default {
+  get user() {
+    const val = sessionStorage.getItem('user');
+    try {
+      if (val) return JSON.parse(val);
+    } catch (err) {
+      console.error(err);
+    }
+    return null;
+  },
+  set user(userinfo) {
+    sessionStorage.setItem('user', JSON.stringify(userinfo));
+  },
+  get token() {
+    return sessionStorage.getItem('token');
+  },
+  set token(token) {
+    sessionStorage.setItem('token', token);
+  },
+  get openid() {
+    return sessionStorage.getItem('openid');
+  },
+  set openid(openid) {
+    sessionStorage.setItem('openid', openid);
+  },
+  get isGuest() {
+    return !this.user || this.user.role === 'guest';
+  },
+  save({ userinfo, token }) {
+    sessionStorage.setItem('user', JSON.stringify(userinfo));
+    sessionStorage.setItem('token', token);
+  },
+
+  get corpInfo() {
+    const val = sessionStorage.getItem('corpInfo');
+    if (val) return JSON.parse(val);
+    return null;
+  },
+  set corpInfo(corpInfo) {
+    sessionStorage.setItem('corpInfo', JSON.stringify(corpInfo));
+  },
+  saveCorpInfo(corpInfo) {
+    sessionStorage.setItem('corpInfo', JSON.stringify(corpInfo));
+  },
+
+  get unit() {
+    const val = sessionStorage.getItem('unit');
+    if (val) return JSON.parse(val);
+    return null;
+  },
+  set unit(unitList) {
+    sessionStorage.setItem('unit', JSON.stringify(unitList));
+  },
+  saveUnit(unitList) {
+    sessionStorage.setItem('unit', JSON.stringify(unitList));
+  },
+  get userInfo() {
+    const val = sessionStorage.getItem('userInfo');
+    if (val) return JSON.parse(val);
+    return null;
+  },
+  set userInfo(userInfo) {
+    sessionStorage.setItem('userInfo', JSON.stringify(userInfo));
+  },
+  saveUserInfo(userInfo) {
+    sessionStorage.setItem('userInfo', JSON.stringify(userInfo));
+  },
+};

+ 19 - 0
src/views/index.vue

@@ -0,0 +1,19 @@
+<template>
+  <div id="index">
+    <p>index</p>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'index',
+  props: {},
+  components: {},
+  data: () => ({}),
+  created() {},
+  computed: {},
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 22 - 0
src/views/index/App.vue

@@ -0,0 +1,22 @@
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+<script>
+export default {
+  name: 'app',
+  components: {},
+};
+</script>
+
+<style lang="scss">
+html {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+body {
+  margin: 0;
+  overflow-x: hidden;
+}
+</style>

+ 18 - 0
src/views/index/main.js

@@ -0,0 +1,18 @@
+import Vue from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store/store';
+import '@/plugins/element.js';
+import '@/plugins/axios';
+import '@/plugins/check-res';
+import '@/plugins/meta';
+import '@/plugins/filters';
+import '@/plugins/loading';
+
+Vue.config.productionTip = false;
+
+new Vue({
+  router,
+  store,
+  render: h => h(App),
+}).$mount('#app');

+ 16 - 0
src/views/index/router.js

@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import Router from 'vue-router';
+
+Vue.use(Router);
+
+export default new Router({
+  mode: 'history',
+  base: process.env.BASE_URL,
+  routes: [
+    {
+      path: '/index',
+      name: 'index',
+      component: () => import('@/views/index/views/index.vue'),
+    },
+  ],
+});

+ 10 - 0
src/views/index/store/store.js

@@ -0,0 +1,10 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+  state: {},
+  mutations: {},
+  actions: {},
+});

+ 513 - 0
src/views/index/views/index.vue

@@ -0,0 +1,513 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="top">
+        <div class="w_1200">
+          <el-col :span="17" class="topLeft">
+            <el-image style="width: 440px; height: 70px" :src="urllogo"></el-image>
+            <el-image style="width: 70px; height: 70px;margin:0 0 0 30px;" :src="urlerweima"></el-image>
+          </el-col>
+          <el-col :span="7" class="topRight">
+            <el-col :span="8">
+              <el-link :underline="false">
+                <i class="el-icon-user"></i>
+                <p>学生登录</p>
+              </el-link>
+            </el-col>
+            <el-col :span="8">
+              <el-link :underline="false">
+                <i class="el-icon-user"></i>
+                <p>单位登录/注册</p>
+              </el-link>
+            </el-col>
+            <el-col :span="8">
+              <el-link :underline="false">
+                <i class="el-icon-user"></i>
+                <p>企业登录</p>
+              </el-link>
+            </el-col>
+          </el-col>
+        </div>
+      </el-col>
+      <el-col :span="24">
+        <div class="w_1200">
+          <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" text-color="#333">
+            <el-submenu index="1">
+              <template slot="title">
+                新闻公告
+              </template>
+              <el-menu-item index="1-1">通知公告</el-menu-item>
+              <el-menu-item index="1-2">就业快讯</el-menu-item>
+            </el-submenu>
+            <el-submenu index="2">
+              <template slot="title">
+                学生导航
+              </template>
+              <el-menu-item index="2-1">毕业生签约流程</el-menu-item>
+              <el-menu-item index="2-2">三方协议违约说明</el-menu-item>
+            </el-submenu>
+            <el-submenu index="3">
+              <template slot="title">
+                学子风采
+              </template>
+              <el-menu-item index="3-1">学子风采</el-menu-item>
+            </el-submenu>
+            <el-submenu index="4">
+              <template slot="title">
+                企业服务
+              </template>
+              <el-menu-item index="4-1">院系公告</el-menu-item>
+              <el-menu-item index="4-2">生源信息</el-menu-item>
+              <el-menu-item index="4-3">入校招聘流程</el-menu-item>
+              <el-menu-item index="4-4">宣讲会预约</el-menu-item>
+              <el-menu-item index="4-5">双选会预约</el-menu-item>
+              <el-menu-item index="4-6">校园地图</el-menu-item>
+            </el-submenu>
+            <el-submenu index="5">
+              <template slot="title">
+                就业服务
+              </template>
+              <el-menu-item index="5-1">求职之路</el-menu-item>
+              <el-menu-item index="5-2">国内求学</el-menu-item>
+              <el-menu-item index="5-3">出国留学</el-menu-item>
+              <el-menu-item index="5-4">创新创业</el-menu-item>
+              <el-menu-item index="5-5">留言咨询</el-menu-item>
+              <el-menu-item index="5-6">预约指导</el-menu-item>
+            </el-submenu>
+            <el-menu-item index="6">联系我们</el-menu-item>
+          </el-menu>
+        </div>
+      </el-col>
+      <el-col :span="24">
+        <div class="w_1200">
+          <div class="block">
+            <el-carousel :autoplay="true">
+              <el-carousel-item v-for="(item, index) in imgList" :key="index">
+                <img :src="item.url" class="imgList" />
+              </el-carousel-item>
+            </el-carousel>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="24" class="main">
+        <div class="w_1200">
+          <el-col :span="6" class="mainLeft">
+            <el-calendar v-model="value"> </el-calendar>
+          </el-col>
+          <el-col :span="18" class="mainRight">
+            <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
+              <el-tab-pane label="宣讲会" name="first">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in talk" :key="index">
+                    <el-col :span="4" class="date">
+                      <span>
+                        {{ item.date }}
+                      </span>
+                    </el-col>
+                    <el-col :span="17" class="text">
+                      <el-col :span="24" class="title overText">{{ item.title }}</el-col>
+                      <el-col :span="24" class="textInfo overText">主办方:{{ item.organizer }}</el-col>
+                      <el-col :span="24" class="textInfo overText">地址:{{ item.address }}</el-col>
+                      <el-col :span="24" class="textInfo overText">时间:{{ item.time }}</el-col>
+                    </el-col>
+                    <el-col :span="3" class="num"> <i class="el-icon-view"></i>{{ item.num }} </el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="双选会" name="second">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in fair" :key="index">
+                    <el-col :span="4" class="date">
+                      <span style="background:#F78D37;">
+                        {{ item.date }}
+                      </span>
+                    </el-col>
+                    <el-col :span="17" class="text">
+                      <el-col :span="24" class="title overText">{{ item.title }}</el-col>
+                      <el-col :span="24" class="textInfo overText">主办方:{{ item.organizer }}</el-col>
+                      <el-col :span="24" class="textInfo overText">地址:{{ item.address }}</el-col>
+                      <el-col :span="24" class="textInfo overText">时间:{{ item.time }}</el-col>
+                    </el-col>
+                    <el-col :span="3" class="num"> <i class="el-icon-view"></i>{{ item.num }} </el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="就业活动" name="third">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in huodong" :key="index">
+                    <el-col :span="4" class="date">
+                      <span style="background:#7030B0;">
+                        {{ item.date }}
+                      </span>
+                    </el-col>
+                    <el-col :span="17" class="text">
+                      <el-col :span="24" class="title overText">{{ item.title }}</el-col>
+                      <el-col :span="24" class="textInfo overText">主办方:{{ item.organizer }}</el-col>
+                      <el-col :span="24" class="textInfo overText">地址:{{ item.address }}</el-col>
+                      <el-col :span="24" class="textInfo overText">时间:{{ item.time }}</el-col>
+                    </el-col>
+                    <el-col :span="3" class="num"> <i class="el-icon-view"></i>{{ item.num }} </el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="在线招聘" name="fourth">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in info" :key="index">
+                    <el-col :span="4" class="date">
+                      <span style="background:#f6c808;">
+                        {{ item.date }}
+                      </span>
+                    </el-col>
+                    <el-col :span="17" class="text">
+                      <el-col :span="24" class="title overText">{{ item.title }}</el-col>
+                      <el-col :span="24" class="textInfo overText">主办方:{{ item.organizer }}</el-col>
+                      <el-col :span="24" class="textInfo overText">地址:{{ item.address }}</el-col>
+                      <el-col :span="24" class="textInfo overText">时间:{{ item.time }}</el-col>
+                    </el-col>
+                    <el-col :span="3" class="num"> <i class="el-icon-view"></i>{{ item.num }} </el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="招聘信息" name="fifth">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in infos" :key="index">
+                    <el-col :span="4" class="new"><span>new</span></el-col>
+                    <el-col :span="20" class="overText">{{ item.title }}</el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="国际组织/联合国" name="sixth">
+                <el-row>
+                  <el-col class="job" :span="12" v-for="(item, index) in internal" :key="index">
+                    <el-col :span="24" class="titleEng overText">{{ item.title }}</el-col>
+                  </el-col>
+                </el-row>
+              </el-tab-pane>
+            </el-tabs>
+            <a href="" class="tabsMore" target="_blank" title="更多">MORE</a>
+          </el-col>
+        </div>
+      </el-col>
+      <el-col :span="24">
+        <div class="w_1200">
+          <h3 style="color: #333;font-size: 16px;font-weight: normal;">
+            专题网站
+          </h3>
+          <el-col :span="24">
+            <el-col class="listImg" :span="4" v-for="(item, index) in listZhuan" :key="index">
+              <el-image style="width: 100%; height: 60px" :src="item.url"></el-image>
+              <p class="imgText overText">{{ item.name }}</p>
+            </el-col>
+          </el-col>
+        </div>
+      </el-col>
+      <el-col :span="24">
+        <div class="w_1200">
+          <h3 style="color: #333;font-size: 16px;font-weight: normal;">
+            友情链接
+          </h3>
+          <el-col :span="24" class="link">
+            <el-link :underline="false" target="_blank">中华人民共和国教育部</el-link>
+            <el-link :underline="false" target="_blank">人力资源和社会保障部</el-link>
+            <el-link :underline="false" target="_blank">深圳市人力资源和社会保障局</el-link>
+            <el-link :underline="false" target="_blank">广东省人力资源和社会保障厅</el-link>
+            <el-link :underline="false" target="_blank">广州市人事网</el-link>
+            <el-link :underline="false" target="_blank">中国留学网</el-link>
+            <el-link :underline="false" target="_blank">创业教育网</el-link>
+            <el-link :underline="false" target="_blank">深圳人才网</el-link>
+            <el-link :underline="false" target="_blank">中华英才网</el-link>
+            <el-link :underline="false" target="_blank">前程无忧</el-link>
+          </el-col>
+        </div>
+      </el-col>
+      <el-col :span="24" class="down">
+        <el-col :span="24" class="downBei">
+          <div class="w_1200">
+            <el-col :span="24" class="downText">
+              <el-col :span="6" style="padding:50px 0;"><el-image style="width: 290px; height: 70px" :src="downLogo"></el-image></el-col>
+              <el-col :span="12" class="address">
+                <p class="overText">办公地址:广东省深圳市南山区学苑大道1088号南方科技大学</p>
+                <p class="overText">就业邮箱:jobs@sustech.edu.cn</p>
+                <p class="overText">开放时间(节假日除外):</p>
+                <p class="overText">上午:8:30—12:00</p>
+                <p class="overText">下午:14:00—17:30</p>
+              </el-col>
+              <el-col :span="6" style="text-align:center;padding:10px 0;"><el-image style="width: 120px; height: 120px" :src="urlerweima"></el-image></el-col>
+            </el-col>
+            <el-col :span="24" class="downTit">
+              <el-col :span="24"><span>南方科技大学版权所有</span><span>|</span><span>域名备案信息:粤ICP备14051456号</span></el-col>
+              <el-col :span="24">
+                <span class="footer-label">可信网站验证</span>
+                <span class="footer-label">安全联盟</span>
+                <span class="footer-label">可信网站验证</span>
+                <span class="footer-label">浏览量:今日851 / 共计583307</span>
+                <span class="footer-label">技术支持:云研科技</span>
+              </el-col>
+            </el-col>
+          </div>
+        </el-col>
+      </el-col>
+    </el-row>
+    <el-backtop target=""><i class="el-icon-upload2"></i></el-backtop>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'index',
+  props: {},
+  components: {},
+  data: () => ({
+    urllogo: require('@/assets/logo.png'),
+    urlerweima: require('@/assets/erweima.png'),
+    downLogo: require('@/assets/downlogo.png'),
+    activeIndex: '1',
+    imgList: [
+      { url: require('@/assets/lun1.jpg') },
+      { url: require('@/assets/lun2.jpg') },
+      { url: require('@/assets/lun3.jpg') },
+      { url: require('@/assets/lun4.jpg') },
+      { url: require('@/assets/lun5.jpg') },
+      { url: require('@/assets/lun6.jpg') },
+    ],
+    value: new Date(),
+    activeName: 'first',
+    listZhuan: [
+      { url: require('@/assets/zhuanti1.jpg'), name: '国际组织实习任职服务平台' },
+      { url: require('@/assets/zhuanti2.jpg'), name: '新职业网' },
+      { url: require('@/assets/zhuanti3.jpg'), name: '学信网' },
+      { url: require('@/assets/zhuanti4.jpg'), name: '中国留学网' },
+      { url: require('@/assets/zhuanti5.jpg'), name: '全国大学生就业一站式服务系统' },
+      { url: require('@/assets/zhuanti6.jpg'), name: '广东省就业指导中心' },
+    ],
+    talk: [
+      { date: '09月03日', title: '宣讲会', organizer: '南方科技大学', address: '力旺广场B座16楼会议室', time: '13:00', num: '1200' },
+      { date: '09月03日', title: '宣讲会', organizer: '南方科技大学', address: '力旺广场B座16楼会议室', time: '13:00', num: '1200' },
+    ],
+    fair: [{ date: '09月03日', title: '双选会', organizer: '南方科技大学', address: '力旺广场B座16楼会议室', time: '13:00', num: '1200' }],
+    huodong: [{ date: '09月03日', title: '就业活动', organizer: '南方科技大学', address: '力旺广场B座16楼会议室', time: '13:00', num: '1200' }],
+    info: [{ date: '09月03日', title: '在线招聘', organizer: '南方科技大学', address: '力旺广场B座16楼会议室', time: '13:00', num: '1200' }],
+    infos: [
+      { title: '2019广东广州市白云区直属机关单位第一次招聘政府雇员公告(42人)' },
+      { title: '2019广东广州市白云区直属机关单位第一次招聘政府雇员公告(42人)' },
+    ],
+    internal: [{ title: 'Intern - Environment Affairs, I (Temporary Job Ope' }, { title: 'Intern - Environment Affairs, I (Temporary Job Ope' }],
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    handleSelect(key, keyPath) {
+      console.log(key, keyPath);
+    },
+    handleClick(tab, event) {
+      console.log(tab, event);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.w_1200 {
+  margin: 0 auto;
+  width: 1200px;
+}
+p {
+  margin: 0;
+  padding: 0;
+}
+.overText {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.top {
+  background-color: #008bd5;
+  padding: 40px 0;
+}
+.topRight {
+  text-align: center;
+  color: #fff;
+}
+/deep/.topRight .el-link {
+  color: #fff;
+  font-size: 15px;
+}
+/deep/.topRight i {
+  font-size: 24px;
+}
+/deep/.el-menu.el-menu--horizontal {
+  border-bottom: none;
+}
+/deep/.el-submenu__title {
+  padding: 0 59px;
+}
+/deep/.el-menu-item {
+  padding: 0 59px;
+}
+/deep/.el-carousel__container {
+  height: 350px;
+}
+.imgList {
+  width: 100%;
+  height: 100%;
+}
+.main {
+  height: 397px;
+  margin-top: 20px;
+}
+.mainLeft {
+  background: #e5e5e5;
+  height: 397px;
+}
+/deep/.el-calendar {
+  background-color: #e5e5e5;
+}
+/deep/.el-calendar__body {
+  padding: 0;
+}
+/deep/.el-calendar-table .el-calendar-day {
+  height: 49px;
+}
+/deep/.el-button--mini {
+  padding: 7px 9px;
+}
+.mainRight {
+  position: relative;
+  background: url(../../../assets/c_bj4.png) repeat;
+  height: 397px;
+}
+/deep/.el-tabs__item {
+  padding: 0 35px;
+  font-size: 15px;
+}
+/deep/.el-tabs__header {
+  margin: 0;
+}
+.tabsMore {
+  position: absolute;
+  top: 12px;
+  float: right;
+  right: 10px;
+  color: #858585;
+  font-size: 12px;
+  text-decoration: none;
+}
+.job {
+  padding: 10px;
+  border-bottom: 1px dashed #ddd;
+  box-sizing: border-box;
+}
+.job:hover {
+  cursor: pointer;
+}
+.job:hover .text .title {
+  color: #09aaff;
+}
+.job:hover .text .textInfo {
+  color: #09aaff;
+}
+.job:hover .num {
+  color: #09aaff;
+}
+.job .date {
+  text-align: center;
+  padding: 15px 0;
+}
+.job .date span {
+  display: inline-block;
+  width: 55px;
+  height: 55px;
+  text-align: center;
+  border: 1px solid #ccc;
+  background: #0070c0;
+  color: #fff;
+}
+.job .text {
+  color: #333;
+}
+.job .text .title {
+  padding: 5px 0 5px 0;
+  font-size: 16px;
+}
+.job .text .textInfo {
+  font-size: 13px;
+  color: #858585;
+}
+.job .num {
+  text-align: right;
+  font-size: 15px;
+  color: #333;
+}
+.job .new {
+  text-align: center;
+  color: #fff;
+}
+.job .new span {
+  display: inline-block;
+  padding: 0px 5px;
+  background: #ff4400;
+  border-radius: 4px;
+}
+.job .titleEng {
+  padding: 0 20px;
+}
+.listImg {
+  width: 178px;
+  margin: 0 22px 0 0;
+  border: 1px solid #ccc;
+}
+.imgText {
+  font-size: 14px;
+  text-align: center;
+  color: #858585;
+  border-top: 1px solid #ccc;
+}
+.down {
+  height: 326px;
+  position: relative;
+  background: url(../../../assets/downImg.png) center no-repeat;
+  opacity: 0.9;
+  background-size: cover;
+}
+.downBei {
+  content: '';
+  z-index: -1;
+  width: 100%;
+  height: 326px;
+  position: absolute;
+  left: 0;
+  top: 0;
+  background-color: #008bd5;
+  opacity: 0.8;
+}
+.link {
+  margin: 0 0 15px 0;
+}
+.link .el-link {
+  margin: 0 15px 15px 0;
+  padding: 0 18px 0 0;
+}
+.downText {
+  padding: 45px 0;
+  border-bottom: 1px solid #fff;
+}
+.downTit {
+  text-align: center;
+}
+.downTit .el-col {
+  margin: 0 0 5px 0;
+}
+.downTit span {
+  color: #f6f6f6;
+  font-size: 14px;
+}
+.address {
+  border-right: 1px solid #fff;
+  border-left: 1px solid #fff;
+}
+.address p {
+  padding: 8px 30px;
+  color: #f6f6f6;
+  font-size: 14px;
+}
+</style>

+ 33 - 0
vue.config.js

@@ -0,0 +1,33 @@
+const path = require('path');
+const publics = path.resolve(__dirname, '../web-common');
+module.exports = {
+  publicPath: '/',
+  // 双页面配置
+  // pages: {
+  //   index: 'src/views/index/main.js',
+  // },
+  configureWebpack: config => {
+    Object.assign(config, {
+      // 开发生产共同配置
+      resolve: {
+        alias: {
+          '@': path.resolve(__dirname, './src'),
+          '@c': path.resolve(__dirname, './src/components'),
+          '@a': path.resolve(__dirname, './src/assets'),
+          '@publics': publics,
+        },
+      },
+    });
+  },
+  devServer: {
+    port: '8001',
+    //api地址前缀
+    proxy: {
+      '/weixin': {
+        target: 'http://smart.cc-lotus.info',
+        changeOrigin: true,
+        ws: true,
+      },
+    },
+  },
+};