Browse Source

项目建立

guhongwei 5 years ago
commit
930f4823a9

+ 5 - 0
.env

@@ -0,0 +1,5 @@
+VUE_APP_AXIOS_BASE_URL = ''
+VUE_APP_ROOT_URL=/admin/
+VUE_APP_MODULE='student'
+VUE_APP_USER_TYPE = '4'
+VUE_APP_LIMIT = 10

+ 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 @@
+# finance-cms
+
+## 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
+ 12097 - 0
package-lock.json


+ 56 - 0
package.json

@@ -0,0 +1,56 @@
+{
+  "name": "finance-cms",
+  "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.2",
+    "core-js": "^3.6.4",
+    "element-ui": "^2.13.0",
+    "eslint-config-prettier": "^6.10.0",
+    "loadsh": "0.0.4",
+    "naf-core": "^0.1.2",
+    "vue": "^2.6.11",
+    "vue-meta": "^2.3.3",
+    "vue-router": "^3.1.5",
+    "vuex": "^3.1.2",
+    "wangeditor": "^3.1.1"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.2.0",
+    "@vue/cli-plugin-eslint": "^4.2.0",
+    "@vue/cli-service": "^4.2.0",
+    "@vue/eslint-config-prettier": "^6.0.0",
+    "babel-eslint": "^10.0.3",
+    "eslint": "^6.7.2",
+    "eslint-plugin-prettier": "^3.1.1",
+    "eslint-plugin-vue": "^6.1.2",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "prettier": "^1.19.1",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended",
+      "@vue/prettier"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    },
+    "rules": {}
+  },
+  "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><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> 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>

+ 30 - 0
src/App.vue

@@ -0,0 +1,30 @@
+<template>
+  <div id="app">
+    <main-layout></main-layout>
+  </div>
+</template>
+<script>
+import mainLayout from '@/layout/main-layout.vue';
+export default {
+  name: 'app',
+  components: {
+    mainLayout,
+  },
+};
+</script>
+
+<style lang="less">
+html {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+body {
+  margin: 0;
+  overflow-x: hidden;
+}
+.textOver {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+</style>

BIN
src/assets/back.png


BIN
src/assets/logo.png


BIN
src/assets/框.png


+ 114 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,114 @@
+<template>
+  <div class="hello">
+    <h1>{{ msg }}</h1>
+    <p>
+      For a guide and recipes on how to configure / customize this project,<br />
+      check out the
+      <a href="https://cli.vuejs.org" target="_blank" rel="noopener"
+        >vue-cli documentation</a
+      >.
+    </p>
+    <h3>Installed CLI Plugins</h3>
+    <ul>
+      <li>
+        <a
+          href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
+          target="_blank"
+          rel="noopener"
+          >babel</a
+        >
+      </li>
+      <li>
+        <a
+          href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
+          target="_blank"
+          rel="noopener"
+          >eslint</a
+        >
+      </li>
+    </ul>
+    <h3>Essential Links</h3>
+    <ul>
+      <li>
+        <a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
+      </li>
+      <li>
+        <a href="https://forum.vuejs.org" target="_blank" rel="noopener"
+          >Forum</a
+        >
+      </li>
+      <li>
+        <a href="https://chat.vuejs.org" target="_blank" rel="noopener"
+          >Community Chat</a
+        >
+      </li>
+      <li>
+        <a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
+          >Twitter</a
+        >
+      </li>
+      <li>
+        <a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
+      </li>
+    </ul>
+    <h3>Ecosystem</h3>
+    <ul>
+      <li>
+        <a href="https://router.vuejs.org" target="_blank" rel="noopener"
+          >vue-router</a
+        >
+      </li>
+      <li>
+        <a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
+      </li>
+      <li>
+        <a
+          href="https://github.com/vuejs/vue-devtools#vue-devtools"
+          target="_blank"
+          rel="noopener"
+          >vue-devtools</a
+        >
+      </li>
+      <li>
+        <a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
+          >vue-loader</a
+        >
+      </li>
+      <li>
+        <a
+          href="https://github.com/vuejs/awesome-vue"
+          target="_blank"
+          rel="noopener"
+          >awesome-vue</a
+        >
+      </li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "HelloWorld",
+  props: {
+    msg: String
+  }
+};
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped lang="less">
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 50 - 0
src/components/test/detailTopInfo.vue

@@ -0,0 +1,50 @@
+<template>
+  <div id="detailTopInfo">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="20" class="menu">
+          <el-breadcrumb separator-class="el-icon-arrow-right">
+            <el-breadcrumb-item>所在位置:</el-breadcrumb-item>
+            <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+            <el-breadcrumb-item>{{ topTitle }}</el-breadcrumb-item>
+          </el-breadcrumb>
+        </el-col>
+        <span v-if="display === 'block'">
+          <el-col :span="4" class="btn">
+            <el-button>操作按钮</el-button>
+          </el-col>
+        </span>
+        <span v-else> </span>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'detailTopInfo',
+  props: {
+    topTitle: null,
+    display: null,
+  },
+  components: {},
+  data: () => ({}),
+  created() {},
+  computed: {},
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.menu {
+  padding: 14px 0;
+}
+.btn {
+  padding: 5px 0;
+  text-align: right;
+}
+/deep/.btn .el-button {
+  background: red;
+  color: #fff;
+}
+</style>

+ 112 - 0
src/components/test/list.vue

@@ -0,0 +1,112 @@
+<template>
+  <div id="list">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="24">
+          <el-table
+            ref="multipleTable"
+            :data="tableData"
+            tooltip-effect="dark"
+            :default-sort="{ prop: 'date', order: 'descending' }"
+            style="width: 100%"
+            @selection-change="handleSelectionChange"
+          >
+            <el-table-column type="selection" align="center"> </el-table-column>
+            <el-table-column prop="list" label="列表" align="center"> </el-table-column>
+            <el-table-column prop="list" label="列表" align="center"> </el-table-column>
+            <el-table-column prop="list" label="列表" align="center"> </el-table-column>
+            <el-table-column prop="status" label="状态" align="center"> </el-table-column>
+            <el-table-column prop="list" label="列表" align="center"> </el-table-column>
+            <el-table-column prop="list" label="列表" align="center"> </el-table-column>
+            <el-table-column prop="date" label="时间排序" sortable align="center"> </el-table-column>
+            <el-table-column label="操作" align="center" width="300px">
+              <template slot-scope="">
+                <el-button size="mini" type="text" class="other">其他操作</el-button>
+                <el-button size="mini" type="text" class="other">其他操作</el-button>
+                <el-button size="mini" type="text" class="view" icon="el-icon-view"></el-button>
+                <el-button size="mini" type="text" class="edit" icon="el-icon-edit"></el-button>
+                <el-button size="mini" type="text" class="delete" icon="el-icon-delete"></el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <el-row>
+            <el-pagination
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+              :current-page="currentPage"
+              :page-sizes="[10, 20, 30, 40]"
+              :page-size="10"
+              background
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+            >
+            </el-pagination>
+          </el-row>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'list',
+  props: {
+    tableData: null,
+    total: null,
+  },
+  components: {},
+  data: () => ({
+    currentPage: 0,
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    handleSizeChange(val) {
+      console.log(`每页 ${val} 条`);
+    },
+    handleCurrentChange(val) {
+      console.log(`当前页: ${val}`);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+/deep/.el-checkbox__input.is-checked .el-checkbox__inner {
+  background-color: red;
+  border-color: red;
+}
+/deep/.el-checkbox__input.is-indeterminate .el-checkbox__inner {
+  background-color: red;
+  border-color: red;
+}
+/deep/.el-table th {
+  background-color: #f5f6fa;
+  padding: 8px 0;
+}
+/deep/.el-table td {
+  padding: 11px 0;
+}
+.other {
+  color: #f36302;
+}
+.view {
+  color: #f36302;
+}
+.edit {
+  color: #2ccc02;
+}
+.delete {
+  color: #e9021d;
+}
+/deep/.el-pagination {
+  padding: 26px 20px;
+}
+/deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
+  background-color: red;
+}
+</style>

+ 307 - 0
src/components/test/mainForm.vue

@@ -0,0 +1,307 @@
+<template>
+  <div id="mainForm">
+    <el-row>
+      <el-col :span="24" class="mainForm">
+        <el-col :span="24" class="top">
+          <span class="shu"></span><span class="title">{{ formTitle }}</span>
+        </el-col>
+        <el-col :span="24" class="form">
+          <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
+            <el-col :span="12">
+              <el-form-item label="名称名称:" prop="name1">
+                <el-input v-model="ruleForm.name1" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="禁止输入:" prop="name2">
+                <el-input v-model="ruleForm.name2" placeholder="请输入" disabled></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="名称名称:" prop="name3">
+                <el-input v-model="ruleForm.name3" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="名称名称:" prop="name4">
+                <el-input v-model="ruleForm.name4" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="文本框:" prop="textarea">
+                <el-input v-model="ruleForm.textarea" type="textarea" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="选择" prop="change">
+                <el-select class="select" v-model="ruleForm.change" placeholder="请选择">
+                  <el-option label="选择一" value="0"></el-option>
+                  <el-option label="选择二" value="1"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="选择" prop="change1">
+                <el-select class="select" v-model="ruleForm.change1" placeholder="请选择">
+                  <el-option label="选择一" value="0"></el-option>
+                  <el-option label="选择二" value="1"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="多选联动:">
+                <el-select class="selects" v-model="ruleForm.profession_one" placeholder="请选择" @change="changeyi">
+                  <el-option v-for="item in yiji" :key="item.value" :label="item.name" :value="item.code"> </el-option>
+                </el-select>
+                <el-select class="selects" v-model="ruleForm.profession_two" placeholder="请选择" @change="changeer">
+                  <el-option v-for="item in erji" :key="item.value" :label="item.name" :value="item.code"> </el-option>
+                </el-select>
+                <el-select class="selects" v-model="ruleForm.profession_three" placeholder="请选择" @change="changesan">
+                  <el-option v-for="item in sanji" :key="item.value" :label="item.name" :value="item.code"> </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="单选" prop="radio">
+                <el-radio-group v-model="ruleForm.radio">
+                  <el-radio label="选择1"></el-radio>
+                  <el-radio label="选择2"></el-radio>
+                  <el-radio label="选择3"></el-radio>
+                  <el-radio label="选择4"></el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="多选" prop="checkbox">
+                <el-checkbox-group v-model="ruleForm.checkbox">
+                  <el-checkbox label="选择1" name="checkbox"></el-checkbox>
+                  <el-checkbox label="选择2" name="checkbox"></el-checkbox>
+                  <el-checkbox label="选择3" name="checkbox"></el-checkbox>
+                  <el-checkbox label="选择4" name="checkbox"></el-checkbox>
+                </el-checkbox-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="条件" prop="term">
+                <el-checkbox-group v-model="ruleForm.term">
+                  <el-checkbox-button v-for="termName in termList" :label="termName" :key="termName">{{ termName }}</el-checkbox-button>
+                </el-checkbox-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="开关" prop="onDown">
+                <el-switch v-model="ruleForm.onDown"></el-switch>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="上传文件" prop="file">
+                <upload
+                  :limit="1"
+                  :data="ruleForm.file"
+                  type="file"
+                  :isBtn="true"
+                  tip="上传说明上传说明上传说明"
+                  list-type="text"
+                  :url="`/files/test/upload`"
+                  @upload="uploadSuccess"
+                ></upload>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="上传文件" prop="file1">
+                <upload
+                  :limit="1"
+                  :data="ruleForm.file1"
+                  type="file1"
+                  :isBtn="true"
+                  :downBtn="true"
+                  @clickDown="clickDown"
+                  list-type="text"
+                  :url="`/files/test/upload`"
+                  @upload="uploadSuccess"
+                ></upload>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="上传图片" prop="file2">
+                <upload
+                  :limit="1"
+                  :data="ruleForm.file2"
+                  type="file2"
+                  tip="请上传500×500px的图片,大小不超过2M"
+                  :url="`/files/test/upload`"
+                  @upload="uploadSuccess"
+                ></upload>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24" class="clickBtn">
+              <el-button>确定</el-button>
+              <el-button>取消</el-button>
+            </el-col>
+          </el-form>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import upload from '@/components/upload.vue';
+export default {
+  name: 'mainForm',
+  props: {
+    formTitle: null,
+    ruleForm: null,
+    yiji: null,
+    erji: null,
+    sanji: null,
+    siji: null,
+  },
+  components: {
+    upload, //图片上传
+  },
+  data: () => ({
+    rules: {
+      name1: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+      name2: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+      textarea: [{ required: true, message: '请输入文本框', trigger: 'blur' }],
+      change: [{ required: true, message: '请选择', trigger: 'blur' }],
+      radio: [{ required: true, message: '请选择', trigger: 'blur' }],
+      checkbox: [{ required: true, message: '请选择', trigger: 'blur' }],
+      term: [{ required: true, message: '请选择', trigger: 'blur' }],
+      onDown: [{ required: true, message: '请选择', trigger: 'blur' }],
+      file: [{ required: true, message: '请选择', trigger: 'blur' }],
+      file1: [{ required: true, message: '请选择', trigger: 'blur' }],
+      file2: [{ required: true, message: '请选择', trigger: 'blur' }],
+    },
+    termList: ['条件1', '条件2', '条件3', '条件4'],
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    changeyi(code) {
+      console.log(code);
+      this.$emit('yi', code);
+    },
+
+    changeer(code) {
+      console.log(code);
+      this.$emit('er', code);
+    },
+    changesan(code) {
+      this.$emit('san', code);
+    },
+
+    uploadSuccess({ type, data }) {
+      if (type !== 'file') {
+        let arr = _.get(this.ruleForm, type);
+        if (arr !== undefined) {
+          this.ruleForm[type].push({ name: data.name, uri: data.uri });
+        } else {
+          let newArr = [{ name: data.name, uri: data.uri }];
+          this.$set(this.ruleForm, `${type}`, newArr);
+        }
+      } else {
+        this.$set(this.ruleForm, `${type}`, data.uri);
+      }
+    },
+    clickDown() {
+      console.log('山川');
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+p {
+  padding: 0;
+  margin: 0;
+}
+.top .shu {
+  float: left;
+  width: 4px;
+  height: 20px;
+  background: rgba(233, 2, 29, 1);
+}
+.top .title {
+  float: left;
+  padding: 0 10px;
+  font-size: 16px;
+  font-family: Source Han Sans SC;
+  font-weight: bold;
+  color: rgba(40, 40, 40, 1);
+}
+/deep/.el-textarea__inner {
+  min-height: 100px !important;
+}
+/deep/.select {
+  width: 632px;
+}
+.selects {
+  width: 473px;
+  margin: 0 15px 0 0;
+}
+/deep/.el-radio__input.is-checked + .el-radio__label {
+  color: #e9021d;
+}
+/deep/.el-radio__input.is-checked .el-radio__inner {
+  border-color: #e9021d;
+  background: #e9021d;
+}
+/deep/.el-checkbox__input.is-checked + .el-checkbox__label {
+  color: #e9021d;
+}
+/deep/.el-checkbox__input.is-checked .el-checkbox__inner,
+.el-checkbox__input.is-indeterminate .el-checkbox__inner {
+  background-color: #e9021d;
+  border-color: #e9021d;
+}
+/deep/.el-checkbox-button,
+.el-checkbox-button__inner {
+  margin: 0 15px 0 0;
+}
+/deep/.el-checkbox-button__inner {
+  padding: 7px 5px;
+  border: 1px solid #ccc;
+  border-radius: 5px;
+}
+/deep/.el-checkbox-button__inner:hover {
+  color: #e9021d;
+}
+/deep/.el-checkbox-button:first-child .el-checkbox-button__inner {
+  border-left: 1px solid #ccc;
+  border-radius: 5px;
+}
+/deep/.el-checkbox-button:last-child .el-checkbox-button__inner {
+  border-radius: 5px;
+}
+/deep/.el-checkbox-button.is-checked .el-checkbox-button__inner {
+  color: #e9021d;
+  background-color: #ffffff;
+  border-color: #e9021d;
+}
+/deep/.el-checkbox-button.is-checked .el-checkbox-button__inner {
+  box-shadow: none;
+}
+/deep/.el-switch.is-checked .el-switch__core {
+  border-color: #e9021d;
+  background-color: #e9021d;
+}
+.clickBtn .el-button {
+  width: 100px;
+  height: 40px;
+  padding: 0;
+  color: #ffffff;
+  background: #b9b9b9;
+  border-radius: 4px;
+  margin: 40px;
+}
+.clickBtn {
+  text-align: center;
+  margin: 40px 0;
+  border-top: 1px solid #ccc;
+}
+.clickBtn .el-button:first-child {
+  background-color: #e9021d;
+}
+</style>

+ 62 - 0
src/components/test/searchInfo.vue

@@ -0,0 +1,62 @@
+<template>
+  <div id="searchInfo">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="5">
+          <span>筛选条件:</span>
+          <el-select v-model="search.region" placeholder="请选择">
+            <el-option label="类型一" value="0"></el-option>
+            <el-option label="类型二" value="1"></el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <span>输入条件:</span>
+          <el-input v-model="search.input" placeholder="请输入" class="input"></el-input>
+        </el-col>
+        <el-col :span="7">
+          <span>时间选择:</span>
+          <el-date-picker v-model="search.date" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker>
+        </el-col>
+        <el-col :span="8">
+          <el-button class="btnSearch">查询</el-button>
+          <el-button class="btnSearch qing">清空</el-button>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'searchInfo',
+  props: {},
+  components: {},
+  data: () => ({
+    search: {},
+  }),
+  created() {},
+  computed: {},
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.input {
+  width: 150px;
+}
+/deep/.el-input__inner {
+  height: 35px;
+  line-height: 35px;
+}
+.btnSearch {
+  width: 80px;
+  height: 34px;
+  background: rgba(233, 2, 29, 1);
+  border-radius: 4px;
+  padding: 0;
+  color: #fff;
+}
+.qing {
+  background: rgba(185, 185, 185, 1);
+}
+</style>

+ 55 - 0
src/components/test/topInfo.vue

@@ -0,0 +1,55 @@
+<template>
+  <div id="topInfo">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="20" class="menu">
+          <el-breadcrumb separator-class="el-icon-arrow-right">
+            <el-breadcrumb-item>所在位置:</el-breadcrumb-item>
+            <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+            <el-breadcrumb-item>{{ topTitle }}</el-breadcrumb-item>
+          </el-breadcrumb>
+        </el-col>
+        <span v-if="display === 'block'">
+          <el-col :span="4" class="btn">
+            <el-button>批量导出</el-button>
+            <el-button @click="add">创建任务</el-button>
+          </el-col>
+        </span>
+        <span v-else> </span>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'topInfo',
+  props: {
+    topTitle: null,
+    display: null,
+  },
+  components: {},
+  data: () => ({}),
+  created() {},
+  computed: {},
+  methods: {
+    add() {
+      this.$emit('add');
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.menu {
+  padding: 14px 0;
+}
+.btn {
+  padding: 5px 0;
+  text-align: right;
+}
+/deep/.btn .el-button {
+  background: red;
+  color: #fff;
+}
+</style>

+ 123 - 0
src/components/upload.vue

@@ -0,0 +1,123 @@
+<template>
+  <div id="upload">
+    <el-upload
+      v-if="url"
+      ref="upload"
+      :action="url"
+      :list-type="listType"
+      :file-list="fileList"
+      :limit="limit"
+      :on-exceed="outLimit"
+      :on-preview="handlePictureCardPreview"
+      :before-remove="handleRemove"
+      :on-success="onSuccess"
+      :show-file-list="showList"
+      :accept="accept"
+    >
+      <el-button size="small" class="isBtn" v-if="isBtn">点击上传文件</el-button>
+      <template v-else>
+        <i class="el-icon-plus"></i>
+      </template>
+      <template #tip v-if="tip">
+        <span class="tip">{{ tip }}</span>
+      </template>
+      <template v-if="downBtn">
+        <el-link :underline="false" @click="clickDown" class="links">下载模板</el-link>
+      </template>
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <img width="100%" :src="dialogImageUrl" alt="" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'upload',
+  props: {
+    url: { type: null },
+    limit: { type: Number },
+    data: { type: null },
+    type: { type: String },
+    isBtn: { type: Boolean, default: false },
+    downBtn: { type: Boolean, default: false },
+    showList: { type: Boolean, default: true },
+    accept: { type: String },
+    tip: { type: String, default: undefined },
+    listType: { type: String, default: 'picture-card' },
+  },
+  components: {},
+  data: () => ({
+    dialogVisible: false,
+    dialogImageUrl: '',
+    fileList: [],
+  }),
+  created() {
+    if (this.data) {
+      this.defalutProcess(this.data);
+    }
+  },
+  watch: {
+    data: {
+      handler(val) {
+        this.defalutProcess(val);
+      },
+    },
+  },
+  computed: {},
+  methods: {
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    handleRemove(file) {
+      return true;
+    },
+    outLimit() {
+      this.$message.error('只允许上传1个文件');
+    },
+    onSuccess(response, file, fileList) {
+      //将文件整理好传回父组件
+      this.$emit('upload', { type: this.type, data: response });
+    },
+    defalutProcess(val) {
+      if (typeof val === 'object' && _.get(val, length) !== undefined && val.length > 0) {
+        let newArr = [];
+        val.map(item => {
+          let object = {};
+          object.name = item.name;
+          object.url = `${item.uri}`;
+          newArr.push(object);
+        });
+        this.$set(this, `fileList`, newArr);
+      } else if (typeof val === 'object' && _.get(val, length) === undefined) {
+        let object = {};
+        object.name = val.name;
+        object.url = `${val.uri}`;
+        this.$set(this, `fileList`, [object]);
+      } else if (typeof val === 'string') {
+        this.$set(this, `fileList`, [{ name: '附件', url: val }]);
+      }
+    },
+    clickDown() {
+      this.$emit('clickDown');
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.isBtn {
+  background-color: #e9021d;
+  color: #ffffff;
+}
+.links {
+  margin: 0 0 0 15px;
+}
+.tip {
+  padding: 0 10px;
+  display: inline-block;
+  color: #999999;
+}
+</style>

+ 77 - 0
src/components/wang-editor.vue

@@ -0,0 +1,77 @@
+<template>
+  <div ref="editor" style="text-align:left"></div>
+</template>
+<script>
+import E from 'wangeditor';
+
+const menus = [
+  'head', // 标题
+  'bold', // 粗体
+  'fontSize', // 字号
+  'fontName', // 字体
+  'italic', // 斜体
+  'underline', // 下划线
+  'strikeThrough', // 删除线
+  'foreColor', // 文字颜色
+  'backColor', // 背景颜色
+  'link', // 插入链接
+  'list', // 列表
+  'justify', // 对齐方式
+  'quote', // 引用
+  // 'emoticon', // 表情
+  'table', // 表格
+  // 'video', // 插入视频
+  // 'code', // 插入代码
+  'undo', // 撤销
+  'redo', // 重复
+];
+
+export default {
+  name: 'wang-editor',
+  model: {
+    prop: 'value',
+    event: 'change', // 默认为input时间,此处改为change
+  },
+  props: {
+    value: { type: String, required: false, default: '' },
+  },
+  data() {
+    return {
+      editorContent: this.value,
+    };
+  },
+  mounted() {
+    var editor = new E(this.$refs.editor);
+    editor.customConfig.onchange = html => {
+      this.editorContent = html;
+      this.$emit('change', html);
+    };
+    // 自定义菜单配置
+    editor.customConfig.menus = menus;
+    editor.customConfig.zIndex = 0;
+    editor.customConfig.uploadImgServer = '/files/cms/images/upload';
+    editor.customConfig.uploadImgMaxLength = 1;
+    editor.customConfig.uploadImgHooks = {
+      // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
+      // (但是,服务器端返回的必须是一个 JSON 格式字符串!!!否则会报错)
+      customInsert: function(insertImg, result, editor) {
+        // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+        // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+
+        // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+        var url = result.uri;
+        insertImg(url);
+
+        // result 必须是一个 JSON 格式字符串!!!否则报错
+      },
+    };
+    editor.create();
+    editor.txt.html(this.value);
+  },
+  methods: {
+    getContent: function() {
+      return this.editorContent;
+    },
+  },
+};
+</script>

+ 66 - 0
src/layout/layout-part/heads.vue

@@ -0,0 +1,66 @@
+<template>
+  <div id="heads">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="18" class="title">
+          吉林省小微企业金融管理后台
+        </el-col>
+        <el-col :span="6" class="admin">
+          <i class="el-icon-user icon"></i>
+          <span class="name">管理员:admin</span>
+          <span class="shu">|</span>
+          <el-link :underline="false" class="out">退出</el-link>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapActions, mapState, mapMutations } from 'vuex';
+
+export default {
+  name: 'heads',
+  props: {},
+  components: {},
+  data: () => ({}),
+  created() {},
+  watch: {},
+  computed: {},
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.title {
+  font-size: 18px;
+  font-family: Source Han Sans SC;
+  font-weight: bold;
+  color: #ffffff;
+  padding: 23px 29px;
+}
+.admin {
+  text-align: right;
+  padding: 24px 30px;
+}
+.admin .icon {
+  color: #fff;
+  padding: 0 5px;
+}
+.admin .name {
+  font-size: 14px;
+  font-family: Source Han Sans SC;
+  font-weight: 400;
+  color: rgba(255, 255, 255, 1);
+}
+.admin .shu {
+  padding: 0 10px;
+  color: rgba(255, 255, 255, 1);
+}
+.admin .out {
+  font-size: 14px;
+  font-family: Source Han Sans SC;
+  font-weight: 400;
+  color: rgba(233, 2, 29, 1);
+}
+</style>

+ 53 - 0
src/layout/layout-part/menus.vue

@@ -0,0 +1,53 @@
+<template>
+  <div id="menus">
+    <el-menu :default-active="thisRouter()" class="el-menu-vertical-demo" :router="false" :default-openeds="defalutMenu" @select="to">
+      <el-menu-item index="/"> <i class="el-icon-s-home"></i>首页 </el-menu-item>
+      <el-submenu index="1">
+        <template v-slot:title>
+          <i class="el-icon-s-home"></i>
+          <span>测试菜单</span>
+        </template>
+        <el-menu-item-group>
+          <el-menu-item index="/test/index">二级菜单</el-menu-item>
+        </el-menu-item-group>
+      </el-submenu>
+    </el-menu>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'menus',
+  props: {},
+  components: {},
+  data: () => ({
+    // defalutMenu: ['1', '2', '3'],
+    defalutMenu: [],
+    defalutPage: '',
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    thisRouter() {
+      console.log(this.$route.path);
+    },
+    to(index) {
+      this.$router.push({ path: index });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+/deep/.el-menu {
+  border-right: none;
+}
+/deep/.el-menu-item,
+.el-submenu__title {
+  height: 45px;
+  line-height: 45px;
+}
+/deep/.el-menu-item.is-active {
+  color: #e9021d;
+}
+</style>

+ 68 - 0
src/layout/main-layout.vue

@@ -0,0 +1,68 @@
+<template>
+  <div id="main-layout">
+    <div v-if="!toLogin()">
+      <el-container>
+        <el-header height="70px" class="head">
+          <heads></heads>
+        </el-header>
+        <el-container class="contain">
+          <el-aside class="side">
+            <menus></menus>
+          </el-aside>
+          <el-main class="main">
+            <router-view />
+          </el-main>
+        </el-container>
+      </el-container>
+    </div>
+    <div v-else>
+      <router-view />
+    </div>
+  </div>
+</template>
+
+<script>
+import heads from '@/layout/layout-part/heads.vue';
+import menus from '@/layout/layout-part/menus.vue';
+import { mapActions, mapState } from 'vuex';
+export default {
+  name: 'main-layout',
+  props: {},
+  components: {
+    menus,
+    heads,
+  },
+  data: () => ({}),
+  created() {},
+  computed: {},
+  methods: {
+    toLogin() {
+      let route = window.location.pathname;
+      return route.includes('login');
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.head {
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  background: #2a2e43;
+}
+.contain {
+  height: 100%;
+  background: #eeeeee;
+}
+.side {
+  width: 220px !important;
+  min-height: 867px;
+  background: #ffffff;
+}
+.main {
+  margin: 0;
+  padding: 20px;
+  min-height: 550px;
+}
+</style>

+ 19 - 0
src/main.js

@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store';
+import '@/plugins/element';
+import '@/plugins/axios';
+import '@/plugins/check-res';
+import '@/plugins/meta';
+import '@/plugins/filters';
+import '@/plugins/loading';
+import '@/plugins/setting';
+
+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 });

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

@@ -0,0 +1,41 @@
+/* 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);
+          Notify({ type: 'success', message: _okText });
+        }
+        return true;
+      }
+      if (_.isFunction(_errText)) {
+        return _errText();
+      }
+      // Message.error(_errText || errmsg);
+      Notify({ type: 'danger', message: _okText });
+      // 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);

+ 20 - 0
src/plugins/setting.js

@@ -0,0 +1,20 @@
+import Vue from 'vue';
+Vue.config.weixin = {
+  // baseUrl: process.env.BASE_URL + 'weixin',
+  baseUrl: 'http://free.liaoningdoupo.com',
+  target: process.env.NODE_ENV === 'development' ? 'http://10.16.10.7:8001' : 'http://free.liaoningdoupo.com/mobile',
+};
+
+Vue.config.stomp = {
+  // brokerURL: 'ws://192.168.1.190:15674/ws',
+  brokerURL: '/ws', // ws://${location.host}/ws
+  connectHeaders: {
+    host: 'train',
+    login: 'visit',
+    passcode: 'visit',
+  },
+  // debug: true,
+  reconnectDelay: 5000,
+  heartbeatIncoming: 4000,
+  heartbeatOutgoing: 4000,
+};

+ 29 - 0
src/router/index.js

@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import Router from 'vue-router';
+Vue.use(Router);
+
+export default new Router({
+  mode: 'history',
+  base: process.env.NODE_ENV === 'development' ? '' : process.env.VUE_APP_ROUTER,
+  routes: [
+    {
+      path: '/',
+      component: () => import('../views/home/index.vue'),
+    },
+    // 测试菜单+列表
+    {
+      path: '/test/index',
+      component: () => import('../views/test/index.vue'),
+    },
+    // 测试菜单+添加
+    {
+      path: '/test/detail',
+      component: () => import('../views/test/detail.vue'),
+    },
+    // 登录
+    {
+      path: '/login',
+      component: () => import('../views/login.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: {},
+});

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

@@ -0,0 +1,116 @@
+/* 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);
+  }
+  $delete(uri, data = {}, router, query, options = {}) {
+    options = { ...options, method: 'delete' };
+    return this.$request(uri, data, query, options, router);
+  }
+  async $request(uri, data, 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, ['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/home/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="less" scoped></style>

+ 19 - 0
src/views/login.vue

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

+ 104 - 0
src/views/test/detail.vue

@@ -0,0 +1,104 @@
+<template>
+  <div id="detail">
+    <el-row>
+      <el-col :span="24">
+        <el-col :span="24" class="top">
+          <detailTopInfo :topTitle="topTitle" :display="display"></detailTopInfo>
+        </el-col>
+        <el-col :span="24" class="main">
+          <mainForm
+            :formTitle="formTitle"
+            :ruleForm="ruleForm"
+            @yi="syi"
+            :yiji="yiji"
+            :erji="erji"
+            :sanji="sanji"
+            :siji="siji"
+            @er="ser"
+            @san="ssan"
+          ></mainForm>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import detailTopInfo from '@/components/test/detailTopInfo.vue';
+import mainForm from '@/components/test/mainForm.vue';
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    detailTopInfo, //表单头部按钮
+    mainForm, //表单内容
+  },
+  data: () => ({
+    topTitle: '二级菜单',
+    display: 'block',
+    formTitle: '头部标题',
+    ruleForm: {
+      checkbox: [],
+      term: [],
+    },
+    yiji: [
+      { code: '1', name: '1' },
+      { code: '2', name: '2' },
+    ],
+
+    erji: [
+      { pcode: '1', code: '3', name: '2.2' },
+      { pcode: '2', code: '4', name: '2.2' },
+    ],
+    sanji: [
+      { pcode: '3', code: '5', name: '3.1' },
+      { pcode: '4', code: '6', name: '3.2' },
+    ],
+    siji: [
+      { pcode: '5', code: '7', name: '4.1' },
+      { pcode: '6', code: '8', name: '4.2' },
+    ],
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    async syi(code) {
+      let pcode = code;
+      console.log(pcode);
+
+      // const ess = await this.query({ pcode });
+      // console.log(ess.data);
+
+      // this.$set(this, `erji`, ess.data);
+    },
+    async ser(code) {
+      let pcode = code;
+
+      const ess = await this.query({ pcode });
+      console.log(ess.data);
+
+      this.$set(this, `sanji`, ess.data);
+    },
+    async ssan(code) {
+      let pcode = code;
+
+      const ess = await this.query({ pcode });
+      console.log(ess.data);
+
+      this.$set(this, `siji`, ess.data);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.top {
+  height: 50px;
+  margin: 0 0 10px 0;
+}
+.main {
+  min-height: 765px;
+  background: #ffffff;
+  padding: 20px;
+}
+</style>

+ 115 - 0
src/views/test/index.vue

@@ -0,0 +1,115 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="top">
+        <topInfo :topTitle="topTitle" :display="display" @add="add"></topInfo>
+      </el-col>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="search">
+          <searchInfo></searchInfo>
+        </el-col>
+        <el-col :span="24" class="list">
+          <list :tableData="tableData" :total="total"></list>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import topInfo from '@/components/test/topInfo.vue';
+import searchInfo from '@/components/test/searchInfo.vue';
+import list from '@/components/test/list.vue';
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    topInfo, //头部导航
+    searchInfo, //搜索
+    list, //列表
+  },
+  data: () => ({
+    topTitle: '二级菜单',
+    display: 'block',
+    tableData: [
+      {
+        list: '列表',
+        status: '进行中',
+        date: '2020-3-18',
+      },
+      {
+        list: '列表',
+        status: '已禁止',
+        date: '2020-3-19',
+      },
+      {
+        list: '列表',
+        status: '已完成',
+        date: '2020-3-20',
+      },
+      {
+        list: '列表',
+        status: '进行中',
+        date: '2020-3-18',
+      },
+      {
+        list: '列表',
+        status: '已禁止',
+        date: '2020-3-19',
+      },
+      {
+        list: '列表',
+        status: '已完成',
+        date: '2020-3-20',
+      },
+      {
+        list: '列表',
+        status: '进行中',
+        date: '2020-3-18',
+      },
+      {
+        list: '列表',
+        status: '已禁止',
+        date: '2020-3-19',
+      },
+      {
+        list: '列表',
+        status: '已完成',
+        date: '2020-3-20',
+      },
+      {
+        list: '列表',
+        status: '进行中',
+        date: '2020-3-18',
+      },
+    ],
+    total: 10,
+  }),
+  created() {},
+  computed: {},
+  methods: {
+    add() {
+      this.$router.push({ path: '/test/detail' });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.top {
+  height: 50px;
+  margin: 0 0 10px 0;
+}
+.main {
+  height: 765px;
+  background: #ffffff;
+}
+.search {
+  width: 97%;
+  height: 35px;
+  margin: 20px;
+}
+.list {
+  padding: 0 20px;
+}
+</style>

+ 43 - 0
vue.config.js

@@ -0,0 +1,43 @@
+const path = require('path');
+
+module.exports = {
+  publicPath: process.env.NODE_ENV === 'development' ? '/' : process.env.VUE_APP_ROOT_URL + 'teacher',
+
+  configureWebpack: config => {
+    Object.assign(config, {
+      // 开发生产共同配置
+      resolve: {
+        alias: {
+          '@': path.resolve(__dirname, './src'),
+          '@c': path.resolve(__dirname, './src/components'),
+          '@a': path.resolve(__dirname, './src/assets'),
+        },
+      },
+    });
+  },
+  devServer: {
+    port: '8001',
+    //api地址前缀
+    proxy: {
+      '/files': {
+        target: 'http://smart.cc-lotus.info',
+        changeOrigin: true,
+        ws: true,
+      },
+      '/ws': {
+        target: 'http://smart.cc-lotus.info',
+        ws: true,
+      },
+      '/weixin': {
+        target: 'http://smart.cc-lotus.info',
+        changeOrigin: true,
+        ws: true,
+      },
+      '/api': {
+        target: 'http://10.16.9.108:9001',
+        changeOrigin: true,
+        ws: true,
+      },
+    },
+  },
+};