魏志佳 hace 4 años
commit
1f400792a8

+ 3 - 0
.browserslistrc

@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead

+ 22 - 0
.gitignore

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

+ 19 - 0
README.md

@@ -0,0 +1,19 @@
+# adsp-okr
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
babel.config.js

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

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 11177 - 0
package-lock.json


+ 31 - 0
package.json

@@ -0,0 +1,31 @@
+{
+  "name": "adsp-okr",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve --open",
+    "build": "vue-cli-service build"
+  },
+  "dependencies": {
+    "core-js": "^3.6.5",
+    "element-ui": "^2.3.6",
+    "register-service-worker": "^1.7.1",
+    "vue": "^2.6.11",
+    "vue-ls": "^3.2.1",
+    "vue-router": "^3.2.0",
+    "vuex": "^3.4.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.4.0",
+    "@vue/cli-plugin-pwa": "~4.4.0",
+    "@vue/cli-plugin-router": "~4.4.0",
+    "@vue/cli-plugin-vuex": "~4.4.0",
+    "@vue/cli-service": "~4.4.0",
+    "axios": "^0.18.0",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "vue-cli-plugin-axios": "0.0.4",
+    "vue-cli-plugin-element-ui": "~1.1.4",
+    "vue-template-compiler": "^2.6.11"
+  }
+}

+ 3 - 0
public/img/icons/safari-pinned-tab.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.00251 14.9297L0 1.07422H6.14651L8.00251 4.27503L9.84583 1.07422H16L8.00251 14.9297Z" fill="black"/>
+</svg>

+ 19 - 0
public/index.html

@@ -0,0 +1,19 @@
+<!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 -->
+    <script src="http://rescdn.qqmail.com/node/ww/wwopenmng/js/sso/wwLogin-1.0.0.js"></script>
+  </body>
+
+</html>

+ 2 - 0
public/robots.txt

@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:

+ 33 - 0
src/App.vue

@@ -0,0 +1,33 @@
+<template>
+  <div id="app">
+      <router-view></router-view>
+  </div>
+</template>
+<script>
+
+
+
+export default {
+  
+}
+</script>
+<style lang="less">
+body,html{
+  height: 100% ;
+  width: 100%;
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+#app {
+  font-family: Avenir, Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-align: center;
+  color: #2c3e50;
+  height: 100%;
+  box-sizing: border-box;
+}
+
+
+</style>

+ 151 - 0
src/Layout.vue

@@ -0,0 +1,151 @@
+<template>
+    <div class="layout">
+        <div class="topNav">
+        <el-row class="topNavBar">
+            <el-col :span="3">
+            <div class="logoBar">
+              <img src="./assets/image/logo.9578b50f.png" alt="" class="logo">
+            </div>
+            
+            </el-col>
+            <div class="login">   
+                <!-- <el-button @click="logOut"></el-button>           -->
+                <!-- <el-avatar style="width:30px;height:30px;margin-top:5px" :src="img"  ></el-avatar> -->
+                <el-dropdown class="btn"  @command="handleCommand">
+                  <!-- <span class="el-dropdown-link ">
+                    {{userName}}<i class="el-icon-arrow-down el-icon--right"></i>
+                  </span> -->
+                  <el-avatar style="width:30px;height:30px;margin-top:5px" :src="img" ></el-avatar>
+                  <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item  command='username'>{{userName}}</el-dropdown-item>
+                    <el-dropdown-item  command='logout'>退出登录</el-dropdown-item>
+                  </el-dropdown-menu>
+                </el-dropdown>
+                <!-- <el-button type="text" class="">{{userName}}</el-button> -->
+            </div>
+        </el-row>
+        </div>
+       
+        <el-row class="tac">
+        <el-col :span="3">
+            <Nav />
+        </el-col>
+        <!-- <router-link to="/">Home</router-link> |
+        <router-link to="/about">About</router-link> -->
+        <el-col :span="21">
+            <router-view />
+        </el-col>
+        </el-row>
+        
+    </div>
+</template>
+
+<script>
+import Nav from './components/Nav.vue';
+import { postAction } from '@/utils/api/http'
+import { mapActions } from 'vuex'
+import { Notification } from 'element-ui';
+// import { timeFix } from '@/utils/util'
+import qs from 'qs'
+import Vue from 'vue'
+    export default {
+        components:{
+            Nav
+        },
+        data() {
+          return {
+              userName:'',
+              img:''
+          }
+        },
+        methods: {
+           ...mapActions(['Login', 'Logout', 'PhoneLogin', 'wxLogin']),
+          logOut(){
+              // console.log(1)
+              localStorage.removeItem('Login_Userinfo');
+              localStorage.removeItem('Access-Token');
+              this.Logout();
+              this.$router.replace({path:'/login'})
+          },
+          handleCommand(command) {
+            if(command=='username'){
+              this.$message({
+                message:'你好啊,'+this.userName,
+                type: 'warning'
+                
+              })
+            }
+            if(command=='logout'){              
+                localStorage.removeItem('Login_Userinfo');
+                localStorage.removeItem('Access-Token');
+                this.Logout();
+                this.$router.replace({path:'/login'})
+            }
+          }
+        },
+        mounted() {
+          let userInfo=JSON.parse(localStorage.getItem('Login_Userinfo'))
+          if(userInfo){
+            this.userName=userInfo.value.name
+            this.img=userInfo.value.thumbAvatar
+          }
+        },
+    }
+</script>
+
+<style lang="less" >
+.layout{
+    width: 100%;
+    height:100%;
+    min-height: 720px;
+    box-sizing: border-box;
+}
+.tac{
+  height:100%;
+  padding-top: 41px;
+  box-sizing: border-box;
+}
+.el-col,.el-menu{
+  height: 100%;
+  overflow: hidden;
+}
+.topNav{
+  background: fff;
+  height: 20px;
+  width: 100%;
+  color:#333;
+  padding:10px 0px;
+  position: fixed;
+  top: 0;
+  background-color: #fff;
+  border-bottom: 1px solid #E4EBF0;
+  font-family: "Helvetica Neue",Tahoma,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",STHeitiSC,sans-serif;
+  box-shadow: 1px 3px 11px rgba(0,0,0,.2);
+  -moz-box-shadow: 1px 3px 11px rgba(0,0,0,.2);
+  -webkit-box-shadow: 1px 3px 11px rgba(0,0,0,.2);
+  z-index: 100;
+ 
+  .login{
+    width: 150px;
+    display: inline-block;
+    position:absolute;
+    right: 20px;
+    top: -10px;
+    box-sizing: border-box;
+    
+    .btn{
+      position: absolute;
+      top: 0;
+      right: 10px;
+    }
+  }
+}
+.el-submenu,.el-menu-item{
+  text-align: left;
+}
+
+.logo{
+  height: 24px;
+  margin:0 auto
+}
+</style>

BIN
src/assets/image/logo.9578b50f.png


BIN
src/assets/image/nodata.png


BIN
src/assets/image/shili.png


+ 32 - 0
src/components/HelloWorld.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="hello">
+   66
+  </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>

+ 86 - 0
src/components/Nav.vue

@@ -0,0 +1,86 @@
+<template>
+    <div class="nav">
+        <el-menu
+        default-active="1-1"
+        class="el-menu-vertical-demo"
+        @open="handleOpen"
+        @close="handleClose"
+        background-color="#545c64"
+        text-color="#fff"
+        active-text-color="#ffd04b">
+        <el-submenu index="1">
+          <template slot="title">
+            <i class="el-icon-location"></i>
+            <span>OKR管理</span>
+          </template>
+          <el-menu-item-group>   
+            <router-link to="/OKRpage">       
+                <el-menu-item index="1-1">
+                    我的OKR
+                </el-menu-item>
+            </router-link>
+            <router-link to="/OKRList">
+                <el-menu-item index="1-2">
+                    我可见的
+                </el-menu-item>
+            </router-link>
+          </el-menu-item-group>
+          <!-- <el-submenu index="1-4">
+            <template slot="title">选项4</template>
+            <el-menu-item index="1-4-1">选项1</el-menu-item>
+          </el-submenu> -->
+        </el-submenu>
+        <!-- <router-link to="/OKRpage">
+            <el-menu-item index="2">
+                <i class="el-icon-menu"></i>
+                <span slot="title"> 我的OKR</span>
+            </el-menu-item>
+        </router-link>
+        <router-link to="/OKRList">
+            <el-menu-item index="3">
+                <i class="el-icon-menu"></i>
+                <span slot="title">我可见的</span>
+            </el-menu-item>
+        </router-link> -->
+        
+        <!-- <el-menu-item index="3" disabled>
+          <i class="el-icon-document"></i>
+          <span slot="title">导航三</span>
+        </el-menu-item>
+        <el-menu-item index="4">
+          <i class="el-icon-setting"></i>
+          <span slot="title">导航四</span>
+        </el-menu-item> -->
+      </el-menu>
+    </div>
+</template>
+
+<script>
+    export default {
+        methods: {
+            handleOpen(key, keyPath) {
+                console.log(key, keyPath);
+            },
+            handleClose(key, keyPath) {
+                console.log(key, keyPath);
+            }
+        },
+    }
+</script>
+
+<style lang="less" scoped>
+.nav{
+    width: 100%;
+    height: 100%;
+    
+    a{
+        color:#fff;
+        text-decoration: none;
+    }
+    
+   
+    
+    
+}
+
+</style>

+ 19 - 0
src/main.js

@@ -0,0 +1,19 @@
+import Vue from 'vue'
+import './plugins/axios'
+import App from './App.vue'
+import './registerServiceWorker'
+import router from './router'
+import store from './store'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import Storage from 'vue-ls'
+
+Vue.use(ElementUI)
+Vue.use(Storage)
+Vue.config.productionTip = false
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 61 - 0
src/plugins/axios.js

@@ -0,0 +1,61 @@
+"use strict";
+
+import Vue from 'vue';
+import axios from "axios";
+
+// Full config:  https://github.com/axios/axios#request-config
+// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
+// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
+// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
+
+let config = {
+  // baseURL: process.env.baseURL || process.env.apiUrl || ""
+  // timeout: 60 * 1000, // Timeout
+  // withCredentials: true, // Check cross-site Access-Control
+};
+
+const _axios = axios.create(config);
+
+_axios.interceptors.request.use(
+  function(config) {
+    // Do something before request is sent
+    return config;
+  },
+  function(error) {
+    // Do something with request error
+    return Promise.reject(error);
+  }
+);
+
+// Add a response interceptor
+_axios.interceptors.response.use(
+  function(response) {
+    // Do something with response data
+    return response;
+  },
+  function(error) {
+    // Do something with response error
+    return Promise.reject(error);
+  }
+);
+
+Plugin.install = function(Vue, options) {
+  Vue.axios = _axios;
+  window.axios = _axios;
+  Object.defineProperties(Vue.prototype, {
+    axios: {
+      get() {
+        return _axios;
+      }
+    },
+    $axios: {
+      get() {
+        return _axios;
+      }
+    },
+  });
+};
+
+Vue.use(Plugin)
+
+export default Plugin ;

+ 32 - 0
src/registerServiceWorker.js

@@ -0,0 +1,32 @@
+/* eslint-disable no-console */
+
+import { register } from 'register-service-worker'
+
+if (process.env.NODE_ENV === 'production') {
+  register(`${process.env.BASE_URL}service-worker.js`, {
+    ready () {
+      console.log(
+        'App is being served from cache by a service worker.\n' +
+        'For more details, visit https://goo.gl/AFskqB'
+      )
+    },
+    registered () {
+      console.log('Service worker has been registered.')
+    },
+    cached () {
+      console.log('Content has been cached for offline use.')
+    },
+    updatefound () {
+      console.log('New content is downloading.')
+    },
+    updated () {
+      console.log('New content is available; please refresh.')
+    },
+    offline () {
+      console.log('No internet connection found. App is running in offline mode.')
+    },
+    error (error) {
+      console.error('Error during service worker registration:', error)
+    }
+  })
+}

+ 104 - 0
src/router/index.js

@@ -0,0 +1,104 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import store from '../store'
+
+
+
+Vue.use(VueRouter)
+
+const routes = [
+    {
+      path: '/',
+      name: 'Layout',
+      redirect:'/OKRpage',
+      component: () => import(/* webpackChunkName: "about" */ '../Layout.vue'),
+      children:[
+        // {
+        //   path: 'home',
+        //   name: 'Home',
+        //   component: Home
+        // },
+        {
+          path: 'okrlist',
+          name: 'OKRlist',
+          // route level code-splitting
+          // this generates a separate chunk (about.[hash].js) for this route
+          // which is lazy-loaded when the route is visited.
+          component: () => import(/* webpackChunkName: "about" */ '../views/OKRList.vue'),
+          meta:{
+            isLogin:true
+          }
+        },
+        {
+          path: 'OKRpage',
+          name: 'OKRpage',
+          // route level code-splitting
+          // this generates a separate chunk (about.[hash].js) for this route
+          // which is lazy-loaded when the route is visited.
+          component: () => import(/* webpackChunkName: "about" */ '../views/OKRpage.vue'),
+          meta:{
+            isLogin:true
+          }
+        },
+        {
+          path: 'Feedback',
+          name: 'Feedback',
+          // route level code-splitting
+          // this generates a separate chunk (about.[hash].js) for this route
+          // which is lazy-loaded when the route is visited.
+          component: () => import(/* webpackChunkName: "about" */ '../views/Feedback.vue'),
+          meta:{
+            isLogin:true
+          }
+        },
+      ]
+    },
+    {
+        path: '/login',
+        name: 'Login',       
+        component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue')
+     },
+      {
+        path: '/transfer-local',
+        name: 'transferLocal',       
+        component: () => import(/* webpackChunkName: "about" */ '../views/TransferLocal.vue')
+     }
+  // {
+  //   path: '/about',
+  //   name: 'About',
+  //   // route level code-splitting
+  //   // this generates a separate chunk (about.[hash].js) for this route
+  //   // which is lazy-loaded when the route is visited.
+  //   component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
+  // }
+]
+
+const router = new VueRouter({
+  mode: 'history',
+  base: process.env.BASE_URL,
+  routes,
+  linkActiveClass:'isActive'
+})
+
+router.beforeEach((to,from,next)=>{
+  let userInfo=JSON.parse(localStorage.getItem('Login_Userinfo'))
+  console.log(to,from,userInfo)
+  if(to.matched.some(res=>res.meta.isLogin)){//判断是否需要登录
+      if (userInfo) {
+        console.log('登陆跳转---tolist')
+          next();
+      }else{
+          next({
+              path:"/login",
+              // query:{
+              //     redirect:to.fullPath
+              // }
+          });
+      }
+
+  }else{
+      next()
+  }
+});
+
+export default router

+ 22 - 0
src/store/getter.js

@@ -0,0 +1,22 @@
+import Vue from 'vue'
+import {USER_INFO} from "@/store/mutation-types"
+
+const getters = {
+
+  token: state => state.user.token,
+  
+  username: state => state.user.username,
+  nickname: state => {
+    state.user.realname = Vue.ls.get(USER_INFO).realname;
+    return state.user.realname
+  },
+  welcome: state => state.user.welcome,
+  // permissionList: state => state.user.permissionList,
+  userInfo: state => {
+    state.user.info = Vue.ls.get(USER_INFO);
+    return state.user.info
+  },
+  
+}
+
+export default getters

+ 22 - 0
src/store/index.js

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

+ 20 - 0
src/store/mutation-types.js

@@ -0,0 +1,20 @@
+export const ACCESS_TOKEN = 'Access-Token'
+export const SIDEBAR_TYPE = 'SIDEBAR_TYPE'
+export const DEFAULT_THEME = 'DEFAULT_THEME'
+export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE'
+export const DEFAULT_COLOR = 'DEFAULT_COLOR'
+export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
+export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER'
+export const DEFAULT_FIXED_SIDEMENU = 'DEFAULT_FIXED_SIDEMENU'
+export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN'
+export const DEFAULT_CONTENT_WIDTH_TYPE = 'DEFAULT_CONTENT_WIDTH_TYPE'
+export const DEFAULT_MULTI_PAGE = 'DEFAULT_MULTI_PAGE'
+export const USER_NAME = 'Login_Username'
+export const USER_INFO = 'Login_Userinfo'
+export const USER_AUTH = 'LOGIN_USER_BUTTON_AUTH'
+export const SYS_BUTTON_AUTH = 'SYS_BUTTON_AUTH'
+
+export const CONTENT_WIDTH_TYPE = {
+  Fluid: 'Fluid',
+  Fixed: 'Fixed'
+}

+ 139 - 0
src/store/user.js

@@ -0,0 +1,139 @@
+import Vue from 'vue'
+import {login, logout, phoneLogin} from "@/utils/api/login"
+import {ACCESS_TOKEN, USER_NAME, USER_INFO, USER_AUTH, SYS_BUTTON_AUTH} from "./mutation-types"
+import {welcome} from "@/utils/util"
+import {queryPermissionsByUser} from '@/utils/api/login'
+
+const user = {
+  state: {
+    token: '',
+    username: '',
+    realname: '',
+    welcome: '',
+    avatar: '',
+    orgcode : '',
+    permissionList: [],
+    info: {}
+  },
+
+  mutations: {
+    SET_TOKEN: (state, token) => {
+      state.token = token
+    },
+    SET_NAME: (state, {username, realname, welcome}) => {
+      state.username = username
+      state.realname = realname
+      state.welcome = welcome
+    },
+    SET_AVATAR: (state, avatar) => {
+      state.avatar = avatar
+    },
+    SET_PERMISSIONLIST: (state, permissionList) => {
+      state.permissionList = permissionList
+    },
+    SET_INFO: (state, info) => {
+      state.info = info
+    },
+  },
+
+  actions: {
+    // 登录
+    Login({commit}, userInfo) {
+      return new Promise((resolve, reject) => {
+        login(userInfo).then(response => {
+          if (response.code == '200') {
+            const result = response.result
+            const userInfo = result.userInfo
+            Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
+            Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
+            Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
+            commit('SET_TOKEN', result.token)
+            commit('SET_INFO', userInfo)
+            commit('SET_NAME', {username: userInfo.username, realname: userInfo.realname, welcome: welcome()})
+            commit('SET_AVATAR', userInfo.avatar)           
+            resolve(response)
+          } else {
+            reject(response)
+          }
+        })
+      })
+    },
+    //企业微信登录
+    wxLogin({commit}, userInfos) {
+        console.log(userInfos)
+        const result = userInfos.result
+        const userInfo = result.userInfo
+        Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
+        Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
+        Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
+        commit('SET_TOKEN', result.token)
+        commit('SET_INFO', userInfo)
+        commit('SET_NAME', {username: userInfo.username, realname: userInfo.realname, welcome: welcome()})
+        commit('SET_AVATAR', userInfo.avatar)
+      },
+    //手机号登录
+    PhoneLogin({commit}, userInfo) {
+      return new Promise((resolve, reject) => {
+        phoneLogin(userInfo).then(response => {
+          if (response.code == '200') {
+            const result = response.result
+            const userInfo = result.userInfo
+            Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
+            Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
+            Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
+            commit('SET_TOKEN', result.token)
+            commit('SET_INFO', userInfo)
+            commit('SET_NAME', {username: userInfo.username, realname: userInfo.realname, welcome: welcome()})
+            commit('SET_AVATAR', userInfo.avatar)
+            resolve(response)
+          } else {
+            reject(response)
+          }
+        })
+      })
+    },
+    // 获取用户信息
+    GetPermissionList({commit}) {
+      return new Promise((resolve, reject) => {
+        let v_token = Vue.ls.get(ACCESS_TOKEN);
+        let params = {token: v_token};
+        queryPermissionsByUser(params).then(response => {
+          const menuData = response.result.menu;
+          const authData = response.result.auth;
+          const allAuthData = response.result.allAuth;
+          //Vue.ls.set(USER_AUTH,authData);
+          sessionStorage.setItem(USER_AUTH, JSON.stringify(authData));
+          sessionStorage.setItem(SYS_BUTTON_AUTH, JSON.stringify(allAuthData));
+          if (menuData && menuData.length > 0) {
+            commit('SET_PERMISSIONLIST', menuData)
+          } else {
+            reject('getPermissionList: permissions must be a non-null array !')
+          }
+          resolve(response)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 登出
+    Logout({commit, state}) {
+      return new Promise((resolve) => {
+        let logoutToken = state.token;
+        commit('SET_TOKEN', '')
+        commit('SET_PERMISSIONLIST', [])
+        Vue.ls.remove(ACCESS_TOKEN)
+        localStorage.removeItem("roleCode")
+        //console.log('logoutToken: '+ logoutToken)
+        logout(logoutToken).then(() => {
+          resolve()
+        }).catch(() => {
+          resolve()
+        })
+      })
+    },
+
+  }
+}
+
+export default user

+ 38 - 0
src/utils/api/http.js

@@ -0,0 +1,38 @@
+import {axios} from '@/utils/api/request'
+
+//post
+export function postAction(url, parameter) {
+    return axios({
+      url: url,
+      method: 'post',
+      data: parameter
+    })
+  }
+  
+  //post method= {post | put}
+  export function httpAction(url, parameter, method) {
+    return axios({
+      url: url,
+      method: method,
+      data: parameter
+    })
+  }
+  
+  //put
+  export function putAction(url, parameter) {
+    return axios({
+      url: url,
+      method: 'put',
+      data: parameter
+    })
+  }
+  
+  //get
+  export function getAction(url, parameter) {
+    return axios({
+      url: url,
+      method: 'get',
+      params: parameter
+    })
+  }
+  

+ 59 - 0
src/utils/api/login.js

@@ -0,0 +1,59 @@
+// import api from './index'
+import {axios} from '@/utils/api/request'
+import {getAction } from './http'
+/**
+ * login func
+ * parameter: {
+ *     username: '',
+ *     password: '',
+ *     remember_me: true,
+ *     captcha: '12345'
+ * }
+ * @param parameter
+ * @returns {*}
+ */
+export const queryPermissionsByUser = (params) => getAction("/sys/permission/getUserPermissionByToken", params);
+export function login(parameter) {
+  return axios({
+    url: '/sys/login',
+    method: 'post',
+    data: parameter
+  })
+}
+
+export function phoneLogin(parameter) {
+  return axios({
+    url: '/sys/phoneLogin',
+    method: 'post',
+    data: parameter
+  })
+}
+
+export function getSmsCaptcha(parameter) {
+  return axios({
+    url: api.SendSms,
+    method: 'post',
+    data: parameter
+  })
+}
+
+export function getInfo() {
+  return axios({
+    url: '/api/user/info',
+    method: 'get',
+    headers: {
+      'Content-Type': 'application/json;charset=UTF-8'
+    }
+  })
+}
+
+export function logout(logoutToken) {
+  return axios({
+    url: '/api/okr/sys/logout',
+    method: 'post',
+    headers: {
+      'Content-Type': 'application/json;charset=UTF-8',
+      'X-Access-Token': logoutToken
+    }
+  })
+}

+ 129 - 0
src/utils/api/request.js

@@ -0,0 +1,129 @@
+import Vue from 'vue'
+import axios from 'axios'
+import store from '@/store'
+import {Plugin as VueAxios} from '@/plugins/axios'
+import {Modal, Notification} from 'element-ui'
+import {ACCESS_TOKEN} from "@/store/mutation-types"
+
+// 创建 axios 实例
+
+// if (process.env.NODE_ENV == 'development') { 
+//     axios.defaults.baseURL = '/jeecg-boot'
+// } 
+// else if (process.env.NODE_ENV == 'debug') { 
+// } 
+// else if (process.env.NODE_ENV == 'production') { 
+//     // axios.defaults.baseURL = 'http://192.168.1.251/jeecg-boot';
+// axios.defaults.baseURL = 'http://api.tjyourong.com.cn/jeecg-boot';
+// }
+const service = axios.create({
+//   baseURL: '/jeecg-boot', // api base_url
+  timeout: 6000000 // 请求超时时间
+})
+
+
+
+
+const err = (error) => {
+  if (error.esponse) {
+    let data = error.response.data
+    const token = Vue.ls.get(ACCESS_TOKEN)
+    console.log("------异常响应------", token)
+    console.log("------异常响应------", error.response.status)
+    switch (error.response.status) {
+      case 403:
+        Notification.error({message: '系统提示', description: '拒绝访问', duration: 4})
+        break
+      case 500:
+        //notification.error({ message: '系统提示', description:'Token失效,请重新登录!',duration: 4})
+        if (token && data.message == "Token失效,请重新登录") {
+          // update-begin- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
+          // store.dispatch('Logout').then(() => {
+          //     window.location.reload()
+          // })
+          Modal.error({
+            title: '登录已过期',
+            content: '很抱歉,登录已过期,请重新登录',
+            okText: '重新登录',
+            mask: false,
+            onOk: () => {
+              store.dispatch('Logout').then(() => {
+                Vue.ls.remove(ACCESS_TOKEN)
+                window.location.reload()
+              })
+            }
+          })
+          // update-end- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
+        }
+        break
+      case 404:
+        Notification.error({message: '系统提示', description: '很抱歉,资源未找到!', duration: 4})
+        break
+      case 504:
+        Notification.error({message: '系统提示', description: '网络超时'})
+        break
+      case 401:
+        Notification.error({message: '系统提示', description: '未授权,请重新登录', duration: 4})
+        if (token) {
+          store.dispatch('Logout').then(() => {
+            setTimeout(() => {
+              window.location.reload()
+            }, 1500)
+          })
+        }
+        break
+      default:
+        Notification.error({
+          message: '系统提示',
+          description: data.message,
+          duration: 4
+        })
+        break
+    }
+  }
+  return Promise.reject(error)
+};
+
+// request interceptor
+service.interceptors.request.use(config => {
+  const token = Vue.ls.get(ACCESS_TOKEN);
+  // let tokens=JSON.parse(localStorage.getItem('ACCESS_TOKEN'))
+  // console.log(token)
+  if (token) {
+      config.headers['X-Access-Token'] = token// 让每个请求携带自定义 token 请根据实际情况自行修改
+  }
+  if (config.method == 'get') {
+    config.params = {
+      _t: Date.parse(new Date()) / 1000,
+
+      ...config.params
+    }
+  }
+  return config
+}, (error) => {
+  return Promise.reject(error)
+})
+
+// response interceptor
+service.interceptors.response.use((response) => {
+  return response.data
+}, (error) => {
+  console.log(error)
+      Notification.error({
+        title: '系统提示',
+        message: '网络超时,请刷新页面'
+      })
+    return 
+  })
+
+const installer = {
+  vm: {},
+  install(Vue, router = {}) {
+    Vue.use(VueAxios, router, service)
+  }
+}
+
+export {
+  installer as VueAxios,
+  service as axios
+}

+ 11 - 0
src/utils/util.js

@@ -0,0 +1,11 @@
+export function timeFix() {
+    const time = new Date()
+    const hour = time.getHours()
+    return hour < 9 ? '早上好' : (hour <= 11 ? '上午好' : (hour <= 13 ? '中午好' : (hour < 20 ? '下午好' : '晚上好')))
+  }
+  
+  export function welcome() {
+    const arr = ['休息一会儿吧', '准备吃什么呢?', '我猜你可能累了']
+    let index = Math.floor((Math.random() * arr.length))
+    return arr[index]
+  }

+ 15 - 0
src/views/Feedback.vue

@@ -0,0 +1,15 @@
+<template>
+    <div>
+        匿名反馈
+    </div>
+</template>
+
+<script>
+    export default {
+        name:'Feedback'
+    }
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 18 - 0
src/views/Home.vue

@@ -0,0 +1,18 @@
+<template>
+  <div class="home">
+    <!-- <img alt="Vue logo" src="../assets/logo.png"> -->
+    <HelloWorld msg="Welcome to Your Vue.js App"/>
+  </div>
+</template>
+
+<script>
+// @ is an alias to /src
+import HelloWorld from '@/components/HelloWorld.vue'
+
+export default {
+  name: 'Home',
+  components: {
+    HelloWorld
+  }
+}
+</script>

+ 51 - 0
src/views/Login.vue

@@ -0,0 +1,51 @@
+<template>
+    <div class="loginPage">
+        <div class="login">
+             <div id="wx_reg" style="display:flex;justify-content: center;"></div>
+        </div>
+    </div>
+</template>
+
+<script>
+    export default {
+        data() {
+            return {
+                
+            }
+        },
+        methods: {
+            
+        },
+        mounted() {
+            this.$nextTick(() => {
+                var url = '';
+                // console.log(process.env)
+                if (process.env.NODE_ENV === 'development') {
+                    url = 'http://192.168.1.105:3001'
+                } else if (process.env.NODE_ENV === 'production') {
+                    url = 'http://okr.c-top.com.cn'
+                }
+                console.log(url)
+                window.WwLogin({
+                    id: 'wx_reg',
+                    appid: 'ww24b8a47826f5875f',
+                    agentid: '1000004',
+                    redirect_uri: 'http://okr.c-top.com.cn/okr/callback/qywexin',
+                    state: url + '/transfer-local',
+                    href: ''
+                })
+            })
+        },
+    }
+</script>
+
+<style lang="less" scoped>
+.loginPage{
+   
+    .login{
+        padding: 200px 0 0;
+        width: 400px;
+        margin: 0 auto ;
+    }
+}
+</style>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1103 - 0
src/views/OKRList.vue


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1519 - 0
src/views/OKRpage.vue


+ 170 - 0
src/views/TransferLocal.vue

@@ -0,0 +1,170 @@
+<style scoped>
+.transfter{
+    width: 100%;
+    box-sizing: border-box;
+}
+.bounce {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* width: 100%; */
+  color: black;
+  height: 100%;
+  font: normal bold 2rem 'Product Sans', sans-serif;
+  white-space: nowrap;
+  box-sizing: border-box;
+}
+
+.letter {
+  animation: bounce 0.75s cubic-bezier(0.05, 0, 0.2, 1) infinite alternate;
+  display: inline-block;
+  transform: translate3d(0, 0, 0);
+  margin-top: 0.5em;
+  text-shadow: rgba(255, 255, 255, 0.4) 0 0 0.05em;
+  font: normal 500 2rem 'Varela Round', sans-serif;
+}
+.letter:nth-child(1) {
+  animation-delay: 0s;
+}
+.letter:nth-child(2) {
+  animation-delay: 0.1s;
+}
+.letter:nth-child(3) {
+  animation-delay: 0.2s;
+}
+.letter:nth-child(4) {
+  animation-delay: 0.3s;
+}
+.letter:nth-child(5) {
+  animation-delay: 0.4s;
+}
+.letter:nth-child(6) {
+  animation-delay: 0.5s;
+}
+.letter:nth-child(7) {
+  animation-delay: 0.6s;
+}
+.letter:nth-child(8) {
+  animation-delay: 0.7s;
+}
+.letter:nth-child(9) {
+  animation-delay: 0.8s;
+}
+.letter:nth-child(10) {
+  animation-delay: 0.9s;
+}
+
+@keyframes bounce {
+  0% {
+    transform: translate3d(0, 0, 0);
+    text-shadow: rgba(255, 255, 255, 0.4) 0 0 0.05em;
+  }
+  100% {
+    transform: translate3d(0, -1em, 0);
+    text-shadow: rgba(255, 255, 255, 0.4) 0 1em 0.35em;
+  }
+}
+</style>
+<template>
+  <div class="transfter" style="margin:100px 0">
+    <div style="text-align:center;font-size:30px" class="bounce">
+      <span class="letter">企</span>
+      <span class="letter">业</span>
+      <span class="letter">微</span>
+      <span class="letter">信</span>
+      <span class="letter">登</span>
+      <span class="letter">录</span>
+      <span class="letter">中</span>
+      <span class="letter">,</span>
+      <span class="letter">请</span>
+      <span class="letter">稍</span>
+      <span class="letter">候</span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { postAction } from '@/utils/api/http'
+import { mapActions } from 'vuex'
+import { Notification } from 'element-ui';
+// import { timeFix } from '@/utils/util'
+import qs from 'qs'
+import Vue from 'vue'
+export default {
+  name: 'transfer',
+  components: {},
+  data() {
+    return {}
+  },
+  methods: {
+    ...mapActions(['Login', 'Logout', 'PhoneLogin', 'wxLogin']),
+    login(values) {
+      this.wxLogin(values)
+      this.loginSuccess()
+    },
+    // departConfirm(res) {
+    //   if (res.success) {
+    //     let multi_depart = res.result.multi_depart
+    //     //0:无部门 1:一个部门 2:多个部门
+    //     if (multi_depart == 0) {
+    //       this.loginSuccess()
+    //       this.$notification.warn({
+    //         message: '提示',
+    //         description: `您尚未归属部门,请确认账号信息`,
+    //         duration: 3
+    //       })
+    //     } else if (multi_depart == 2) {
+    //       this.departVisible = true
+    //       this.currentUsername = this.form.getFieldValue('username')
+    //       this.departList = res.result.departs
+    //     } else {
+    //       this.loginSuccess()
+    //     }
+    //   } else {
+    //     this.requestFailed(res)
+    //     this.Logout()
+    //   }
+    // },
+    requestFailed(err) {
+
+      Notification.error({
+        title: '登录失败',
+        message: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
+        
+      })
+      this.loginBtn = false
+    },
+    loginSuccess() {
+      this.$router.push({ path: '/' })
+      Notification.success({
+        title: '欢迎',
+        message: `欢迎回来`
+      })
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      console.log(window.location.search)
+      var data = window.location.search.split('?')[1]
+      var arr = data.split('=')
+      var json = {}
+      json[arr[0]] = arr[1]
+      var params = qs.stringify(json)
+      postAction('/api/okr/sys/wxlogin', params).then(res => {
+        console.log(res)
+        if (res.success) {
+          this.login(res)
+        } else {
+          //   this.$message.error('企业微信登录失败,请选择账户登录')
+            this.requestFailed(res)         
+            this.$router.push({ name: 'Login' })         
+        }
+      })
+        
+    })
+  }
+}
+</script>
+
+<style scoped>
+</style>

+ 16 - 0
vue.config.js

@@ -0,0 +1,16 @@
+module.exports = { 
+    devServer: { 
+        port: 3000,
+        proxy: {
+            "/api": {
+                target: 'http://192.168.0.230:8910', // 要访问的接口域名
+                // target: 'http://okr.c-top.com.cn', // 要访问的接口域名
+                ws: true, // 是否启用websockets
+                changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
+                pathRewrite: {
+                    "^/api": "" //这里理解成用'/api'代替target里面的地址,比如我要调用'http://40.00.100.100:3002/user/add',直接写'/api/user/add'即可
+                }
+            }
+        }
+    } 
+}