lyn7568 2 years ago
parent
commit
9fcb2fd227

+ 2 - 1
.env.development

2
ENV = 'development'
2
ENV = 'development'
3
3
4
# base api
4
# base api
5
VUE_APP_BASE_API = '/dev-api'
5
# VUE_APP_BASE_API = '/dev-api'
6
VUE_APP_BASE_API = ''

+ 10 - 3
src/api/user.js

2
2
3
export function login(data) {
3
export function login(data) {
4
  return request({
4
  return request({
5
    url: '/vue-admin-template/user/login',
5
    url: '/sys/Login/checkLogin',
6
    method: 'post',
6
    method: 'post',
7
    data
7
    data
8
  })
8
  })
10
10
11
export function getInfo(token) {
11
export function getInfo(token) {
12
  return request({
12
  return request({
13
    url: '/vue-admin-template/user/info',
13
    url: '/sys/User/info',
14
    method: 'get',
15
    params: { token }
16
  })
17
}
18
export function getCaptcha(token) {
19
  return request({
20
    url: '/sys/Login/captcha',
14
    method: 'get',
21
    method: 'get',
15
    params: { token }
22
    params: { token }
16
  })
23
  })
18
25
19
export function logout() {
26
export function logout() {
20
  return request({
27
  return request({
21
    url: '/vue-admin-template/user/logout',
28
    url: '/sys/Login/logout',
22
    method: 'post'
29
    method: 'post'
23
  })
30
  })
24
}
31
}

+ 4 - 4
src/layout/components/Navbar.vue

13
        <el-dropdown-menu slot="dropdown" class="user-dropdown">
13
        <el-dropdown-menu slot="dropdown" class="user-dropdown">
14
          <router-link to="/">
14
          <router-link to="/">
15
            <el-dropdown-item>
15
            <el-dropdown-item>
16
              Home
16
              首页
17
            </el-dropdown-item>
17
            </el-dropdown-item>
18
          </router-link>
18
          </router-link>
19
          <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
19
          <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
20
            <el-dropdown-item>Github</el-dropdown-item>
20
            <el-dropdown-item>Github</el-dropdown-item>
21
          </a>
21
          </a>
22
          <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
22
          <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
23
            <el-dropdown-item>Docs</el-dropdown-item>
23
            <el-dropdown-item>Docs</el-dropdown-item>
24
          </a>
24
          </a> -->
25
          <el-dropdown-item divided @click.native="logout">
25
          <el-dropdown-item divided @click.native="logout">
26
            <span style="display:block;">Log Out</span>
26
            <span style="display:block;">退出登录</span>
27
          </el-dropdown-item>
27
          </el-dropdown-item>
28
        </el-dropdown-menu>
28
        </el-dropdown-menu>
29
      </el-dropdown>
29
      </el-dropdown>

+ 8 - 8
src/main.js

11
import App from './App'
11
import App from './App'
12
import store from './store'
12
import store from './store'
13
import router from './router'
13
import router from './router'
14
14
import httpRequest from './utils/httpRequest'
15
import '@/icons' // icon
15
import '@/icons' // icon
16
import '@/permission' // permission control
16
import '@/permission' // permission control
17
17
23
 * Currently MockJs will be used in the production environment,
23
 * Currently MockJs will be used in the production environment,
24
 * please remove it before going online ! ! !
24
 * please remove it before going online ! ! !
25
 */
25
 */
26
if (process.env.NODE_ENV === 'production') {
27
  const { mockXHR } = require('../mock')
28
  mockXHR()
29
}
26
// if (process.env.NODE_ENV === 'production') {
27
//   const { mockXHR } = require('../mock')
28
//   mockXHR()
29
// }
30
30
31
// set ElementUI lang to EN
31
// set ElementUI lang to EN
32
Vue.use(ElementUI, { locale })
32
// Vue.use(ElementUI, { locale })
33
// 如果想要中文版 element-ui,按如下方式声明
33
// 如果想要中文版 element-ui,按如下方式声明
34
// Vue.use(ElementUI)
35
34
Vue.use(ElementUI)
35
Vue.prototype.$http = httpRequest
36
Vue.config.productionTip = false
36
Vue.config.productionTip = false
37
37
38
new Vue({
38
new Vue({

+ 13 - 10
src/router/index.js

89
      }
89
      }
90
    ]
90
    ]
91
  },
91
  },
92
  {
93
    path: '/user',
94
    component: Layout,
95
    children: [
96
      {
97
        path: 'user',
98
        name: 'User',
99
        component: () => import('@/views/user/user.vue'),
100
        meta: { title: 'User', icon: 'form' }
101
      }
102
    ]
103
  },
92
104
93
  {
105
  {
94
    path: '/nested',
106
    path: '/nested',
149
    ]
161
    ]
150
  },
162
  },
151
163
152
  {
153
    path: 'external-link',
154
    component: Layout,
155
    children: [
156
      {
157
        path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
158
        meta: { title: 'External Link', icon: 'link' }
159
      }
160
    ]
161
  },
164
 
162
165
163
  // 404 page must be placed at the end !!!
166
  // 404 page must be placed at the end !!!
164
  { path: '*', redirect: '/404', hidden: true }
167
  { path: '*', redirect: '/404', hidden: true }

+ 5 - 6
src/store/modules/user.js

30
const actions = {
30
const actions = {
31
  // user login
31
  // user login
32
  login({ commit }, userInfo) {
32
  login({ commit }, userInfo) {
33
    const { username, password } = userInfo
33
    const { username, password, vercode } = userInfo
34
    return new Promise((resolve, reject) => {
34
    return new Promise((resolve, reject) => {
35
      login({ username: username.trim(), password: password }).then(response => {
36
        const { data } = response
35
      login({ username: username.trim(), password: password, vercode: vercode }).then(response => {
36
        const data = response
37
        commit('SET_TOKEN', data.token)
37
        commit('SET_TOKEN', data.token)
38
        setToken(data.token)
38
        setToken(data.token)
39
        resolve()
39
        resolve()
48
    return new Promise((resolve, reject) => {
48
    return new Promise((resolve, reject) => {
49
      getInfo(state.token).then(response => {
49
      getInfo(state.token).then(response => {
50
        const { data } = response
50
        const { data } = response
51
52
        if (!data) {
51
        if (!data) {
53
          return reject('Verification failed, please Login again.')
52
          return reject('Verification failed, please Login again.')
54
        }
53
        }
55
54
56
        const { name, avatar } = data
55
        const { username, avatar } = data
57
56
58
        commit('SET_NAME', name)
57
        commit('SET_NAME', username)
59
        commit('SET_AVATAR', avatar)
58
        commit('SET_AVATAR', avatar)
60
        resolve(data)
59
        resolve(data)
61
      }).catch(error => {
60
      }).catch(error => {

+ 107 - 0
src/utils/httpRequest.js

1
import axios from 'axios'
2
import { MessageBox, Message } from 'element-ui'
3
import store from '@/store'
4
import { getToken } from '@/utils/auth'
5
import qs from 'qs'
6
import merge from 'lodash/merge'
7
8
// create an axios instance
9
const service = axios.create({
10
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
11
  // withCredentials: true, // send cookies when cross-domain requests
12
  timeout: 5000 // request timeout
13
})
14
15
// request interceptor
16
service.interceptors.request.use(
17
  config => {
18
    // do something before request is sent
19
20
    if (store.getters.token) {
21
      // let each request carry token
22
      // ['X-Token'] is a custom headers key
23
      // please modify it according to the actual situation
24
      config.headers['X-Token'] = getToken()
25
    }
26
    return config
27
  },
28
  error => {
29
    // do something with request error
30
    console.log(error) // for debug
31
    return Promise.reject(error)
32
  }
33
)
34
35
// response interceptor
36
service.interceptors.response.use(
37
  /**
38
   * If you want to get http information such as headers or status
39
   * Please return  response => response
40
  */
41
42
  /**
43
   * Determine the request status by custom code
44
   * Here is just an example
45
   * You can also judge the status by HTTP Status Code
46
   */
47
  response => {
48
    
49
    if (response.data && response.data.code === 401) { // 401, token失效
50
      clearLoginInfo()
51
      router.push({
52
        name: 'login'
53
      })
54
    }
55
    return response
56
  },
57
  error => {
58
    console.log('err' + error) // for debug
59
    Message({
60
      message: error.message,
61
      type: 'error',
62
      duration: 5 * 1000
63
    })
64
    return Promise.reject(error)
65
  }
66
)
67
68
69
/**
70
 * 请求地址处理
71
 * @param {*} actionName action方法名称
72
 */
73
 service.adornUrl = (actionName) => {
74
  // 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
75
  return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? '/proxyApi/' : '') + actionName
76
}
77
78
/**
79
 * get请求参数处理
80
 * @param {*} params 参数对象
81
 * @param {*} openDefultParams 是否开启默认参数?
82
 */
83
service.adornParams = (params = {}, openDefultParams = true) => {
84
  var defaults = {
85
    't': new Date().getTime()
86
  }
87
  return openDefultParams ? merge(defaults, params) : params
88
}
89
90
/**
91
 * post请求数据处理
92
 * @param {*} data 数据对象
93
 * @param {*} openDefultdata 是否开启默认数据?
94
 * @param {*} contentType 数据格式
95
 *  json: 'application/json; charset=utf-8'
96
 *  form: 'application/x-www-form-urlencoded; charset=utf-8'
97
 */
98
service.adornData = (data = {}, openDefultdata = true, contentType = 'json') => {
99
  var defaults = {
100
    't': new Date().getTime()
101
  }
102
  data = openDefultdata ? merge(defaults, data) : data
103
  console.log(data);
104
  return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
105
}
106
107
export default service

+ 8 - 1
src/utils/index.js

1
/**
1
/**
2
 * Created by PanJiaChen on 16/11/18.
2
 * Created by PanJiaChen on 16/11/18.
3
 */
3
 */
4
4
import { removeToken } from "./auth"
5
/**
5
/**
6
 * Parse the time to string
6
 * Parse the time to string
7
 * @param {(Object|string|number)} time
7
 * @param {(Object|string|number)} time
115
  })
115
  })
116
  return obj
116
  return obj
117
}
117
}
118
119
120
export function clearLoginInfo(){
121
  removeToken()
122
 store.commit('resetStore')
123
 router.options.isAddDynamicMenuRoutes = false
124
}

+ 3 - 3
src/utils/request.js

46
    const res = response.data
46
    const res = response.data
47
47
48
    // if the custom code is not 20000, it is judged as an error.
48
    // if the custom code is not 20000, it is judged as an error.
49
    if (res.code !== 20000) {
49
    if (res.code !== 0) {
50
      Message({
50
      Message({
51
        message: res.message || 'Error',
51
        message: res.msg || 'Error',
52
        type: 'error',
52
        type: 'error',
53
        duration: 5 * 1000
53
        duration: 5 * 1000
54
      })
54
      })
66
          })
66
          })
67
        })
67
        })
68
      }
68
      }
69
      return Promise.reject(new Error(res.message || 'Error'))
69
      return Promise.reject(new Error(res.msg || 'Error'))
70
    } else {
70
    } else {
71
      return res
71
      return res
72
    }
72
    }

+ 118 - 53
src/views/login/index.vue

1
<template>
1
<template>
2
  <div class="login-container">
2
  <div class="login-container">
3
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
4
3
    <el-form
4
      ref="loginForm"
5
      :model="loginForm"
6
      :rules="loginRules"
7
      class="login-form"
8
      auto-complete="on"
9
      label-position="left"
10
    >
5
      <div class="title-container">
11
      <div class="title-container">
6
        <h3 class="title">Login Form</h3>
12
        <h3 class="title">管理后台</h3>
7
      </div>
13
      </div>
8
14
9
      <el-form-item prop="username">
15
      <el-form-item prop="username">
13
        <el-input
19
        <el-input
14
          ref="username"
20
          ref="username"
15
          v-model="loginForm.username"
21
          v-model="loginForm.username"
16
          placeholder="Username"
22
          placeholder="用户名"
17
          name="username"
23
          name="username"
18
          type="text"
24
          type="text"
19
          tabindex="1"
25
          tabindex="1"
30
          ref="password"
36
          ref="password"
31
          v-model="loginForm.password"
37
          v-model="loginForm.password"
32
          :type="passwordType"
38
          :type="passwordType"
33
          placeholder="Password"
39
          placeholder="密码"
34
          name="password"
40
          name="password"
35
          tabindex="2"
41
          tabindex="2"
36
          auto-complete="on"
42
          auto-complete="on"
37
          @keyup.enter.native="handleLogin"
43
          @keyup.enter.native="handleLogin"
38
        />
44
        />
39
        <span class="show-pwd" @click="showPwd">
45
        <span class="show-pwd" @click="showPwd">
40
          <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
46
          <svg-icon
47
            :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
48
          />
41
        </span>
49
        </span>
42
      </el-form-item>
50
      </el-form-item>
43
51
44
      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
52
      <el-form-item prop="vercode">
53
        <el-input
54
          style="width: 40%"
55
          v-model="loginForm.vercode"
56
          placeholder="验证码"
57
        >
58
        </el-input>
59
60
        <img
61
          class="vercodeImg"
62
          :src="vercodePath"
63
          @click="getCaptcha()"
64
          alt=""
65
        />
66
      </el-form-item>
45
67
68
      <el-button
69
        :loading="loading"
70
        type="primary"
71
        style="width: 100%; margin-bottom: 30px"
72
        @click.native.prevent="handleLogin"
73
        >登录</el-button
74
      >
75
      <!-- 
46
      <div class="tips">
76
      <div class="tips">
47
        <span style="margin-right:20px;">username: admin</span>
77
        <span style="margin-right: 20px">username: admin</span>
48
        <span> password: any</span>
78
        <span> password: any</span>
49
      </div>
50
79
      </div> -->
51
    </el-form>
80
    </el-form>
52
  </div>
81
  </div>
53
</template>
82
</template>
54
83
55
<script>
84
<script>
56
import { validUsername } from '@/utils/validate'
85
import { validUsername } from "@/utils/validate";
57
86
58
export default {
87
export default {
59
  name: 'Login',
88
  name: "Login",
60
  data() {
89
  data() {
61
    const validateUsername = (rule, value, callback) => {
90
    const validateUsername = (rule, value, callback) => {
62
      if (!validUsername(value)) {
91
      if (!validUsername(value)) {
63
        callback(new Error('Please enter the correct user name'))
92
        callback(new Error("请输入用户名"));
64
      } else {
93
      } else {
65
        callback()
94
        callback();
66
      }
95
      }
67
    }
96
    };
97
    const validateVercode = (rule, value, callback) => {
98
      if (!value) {
99
        callback(new Error("请输入验证码"));
100
      } else {
101
        callback();
102
      }
103
    };
68
    const validatePassword = (rule, value, callback) => {
104
    const validatePassword = (rule, value, callback) => {
69
      if (value.length < 6) {
105
      if (value.length < 6) {
70
        callback(new Error('The password can not be less than 6 digits'))
106
        callback(new Error("密码不能小于6位数"));
71
      } else {
107
      } else {
72
        callback()
108
        callback();
73
      }
109
      }
74
    }
110
    };
75
    return {
111
    return {
76
      loginForm: {
112
      loginForm: {
77
        username: 'admin',
78
        password: '111111'
113
        username: "",
114
        password: "",
115
        vercode: "",
79
      },
116
      },
117
      vercodePath: "",
80
      loginRules: {
118
      loginRules: {
81
        username: [{ required: true, trigger: 'blur', validator: validateUsername }],
82
        password: [{ required: true, trigger: 'blur', validator: validatePassword }]
119
        username: [
120
          { required: true, trigger: "blur", validator: validateUsername },
121
        ],
122
        password: [
123
          { required: true, trigger: "blur", validator: validatePassword },
124
        ],
125
        vercode:[
126
          { required: true, trigger: "blur", validator: validateVercode },
127
        ],
83
      },
128
      },
84
      loading: false,
129
      loading: false,
85
      passwordType: 'password',
86
      redirect: undefined
87
    }
130
      passwordType: "password",
131
      redirect: undefined,
132
    };
88
  },
133
  },
89
  watch: {
134
  watch: {
90
    $route: {
135
    $route: {
91
      handler: function(route) {
92
        this.redirect = route.query && route.query.redirect
136
      handler: function (route) {
137
        this.redirect = route.query && route.query.redirect;
93
      },
138
      },
94
      immediate: true
95
    }
139
      immediate: true,
140
    },
141
  },
142
  created() {
143
    this.getCaptcha();
96
  },
144
  },
97
  methods: {
145
  methods: {
146
    //验证码
147
    getCaptcha() {
148
      let uuid = Math.random();
149
      this.vercodePath = `/sys/Login/captcha?${uuid}`;
150
    },
151
98
    showPwd() {
152
    showPwd() {
99
      if (this.passwordType === 'password') {
100
        this.passwordType = ''
153
      if (this.passwordType === "password") {
154
        this.passwordType = "";
101
      } else {
155
      } else {
102
        this.passwordType = 'password'
156
        this.passwordType = "password";
103
      }
157
      }
104
      this.$nextTick(() => {
158
      this.$nextTick(() => {
105
        this.$refs.password.focus()
106
      })
159
        this.$refs.password.focus();
160
      });
107
    },
161
    },
108
    handleLogin() {
162
    handleLogin() {
109
      this.$refs.loginForm.validate(valid => {
163
      this.$refs.loginForm.validate((valid) => {
110
        if (valid) {
164
        if (valid) {
111
          this.loading = true
112
          this.$store.dispatch('user/login', this.loginForm).then(() => {
113
            this.$router.push({ path: this.redirect || '/' })
114
            this.loading = false
115
          }).catch(() => {
116
            this.loading = false
117
          })
165
          this.loading = true;
166
          this.$store
167
            .dispatch("user/login", this.loginForm)
168
            .then(() => {
169
              this.$router.push({ path: this.redirect || "/" });
170
              this.loading = false;
171
            })
172
            .catch(() => {
173
              this.loading = false;
174
              this.loginForm.vercode = '';
175
              this.getCaptcha();
176
            });
118
        } else {
177
        } else {
119
          console.log('error submit!!')
120
          return false
178
          console.log("error submit!!");
179
          return false;
121
        }
180
        }
122
      })
123
    }
124
  }
125
}
181
      });
182
    },
183
  },
184
};
126
</script>
185
</script>
127
186
128
<style lang="scss">
187
<style lang="scss">
129
/* 修复input 背景不协调 和光标变色 */
188
/* 修复input 背景不协调 和光标变色 */
130
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
189
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
131
190
132
$bg:#283443;
133
$light_gray:#fff;
191
$bg: #283443;
192
$light_gray: #fff;
134
$cursor: #fff;
193
$cursor: #fff;
135
194
136
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
195
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
173
</style>
232
</style>
174
233
175
<style lang="scss" scoped>
234
<style lang="scss" scoped>
176
$bg:#2d3a4b;
177
$dark_gray:#889aa4;
178
$light_gray:#eee;
235
$bg: #2d3a4b;
236
$dark_gray: #889aa4;
237
$light_gray: #eee;
179
238
180
.login-container {
239
.login-container {
181
  min-height: 100%;
240
  min-height: 100%;
234
    user-select: none;
293
    user-select: none;
235
  }
294
  }
236
}
295
}
296
.vercodeImg {
297
  float: right;
298
  height: 47px;
299
  overflow: hidden;
300
  cursor:pointer;
301
}
237
</style>
302
</style>

+ 345 - 0
src/views/user/user-add-or-update.vue

1
<template>
2
  <el-dialog
3
    :title="!dataForm.id ? '新增' : '修改'"
4
    :close-on-click-modal="false"
5
    :visible.sync="visible"
6
  >
7
    <el-form
8
      :model="dataForm"
9
      :rules="dataRule"
10
      ref="dataForm"
11
      @keyup.enter.native="dataFormSubmit()"
12
      label-width="80px"
13
    >
14
      <el-form-item label="用户名" prop="userName">
15
        <el-input v-model="dataForm.userName" placeholder="登录帐号"></el-input>
16
      </el-form-item>
17
      <el-form-item
18
        label="密码"
19
        prop="password"
20
        :class="{ 'is-required': !dataForm.id }"
21
      >
22
        <el-input
23
          v-model="dataForm.password"
24
          type="password"
25
          placeholder="密码"
26
        ></el-input>
27
      </el-form-item>
28
      <el-form-item
29
        label="确认密码"
30
        prop="comfirmPassword"
31
        :class="{ 'is-required': !dataForm.id }"
32
      >
33
        <el-input
34
          v-model="dataForm.comfirmPassword"
35
          type="password"
36
          placeholder="确认密码"
37
        ></el-input>
38
      </el-form-item>
39
      <el-form-item label="邮箱" prop="email">
40
        <el-input v-model="dataForm.email" placeholder="邮箱"></el-input>
41
      </el-form-item>
42
      <el-form-item label="手机号" prop="mobile">
43
        <el-input v-model="dataForm.mobile" placeholder="手机号"></el-input>
44
      </el-form-item>
45
      <!-- <el-form-item label="部门" prop="departmentList">
46
        <el-select
47
          v-model="dataForm.departmentList"
48
          placeholder="部门"
49
          allow-create
50
          filterable
51
          @change="getClientName"
52
        >
53
          <el-tree
54
            v-for="item in departmentList"
55
            :label="item.departmentName"
56
            :value="item.departmentId"
57
            :key="item.departmentId"
58
          ></el-tree>
59
        </el-select>
60
      </el-form-item> -->
61
      <el-form-item label="部门" prop="departmentName">
62
        <el-popover
63
          ref="menuListPopover"
64
          placement="bottom-start"
65
          trigger="click">
66
          <el-tree
67
            :data="departmentList"
68
            :props="menuListTreeProps"
69
            node-key="departmentId"
70
            ref="departmentListTree"
71
            @current-change="departmentListTreeCurrentChangeHandle"
72
            :default-expand-all="true"
73
            :highlight-current="true"
74
            :expand-on-click-node="true">
75
          </el-tree>
76
        </el-popover>
77
        <el-input v-model="dataForm.departmentName" v-popover:menuListPopover :readonly="true" placeholder="点击选择部门" class="menu-list__input"></el-input>
78
      </el-form-item>
79
      <el-form-item label="角色" size="mini" prop="roleIdList">
80
        <el-checkbox-group v-model="dataForm.roleIdList">
81
          <el-checkbox
82
            v-for="role in roleList"
83
            :key="role.roleId"
84
            :label="role.roleId"
85
            >{{ role.roleName }}</el-checkbox
86
          >
87
        </el-checkbox-group>
88
      </el-form-item>
89
      <el-form-item label="状态" size="mini" prop="status">
90
        <el-radio-group v-model="dataForm.status">
91
          <el-radio :label="0">禁用</el-radio>
92
          <el-radio :label="1">正常</el-radio>
93
        </el-radio-group>
94
      </el-form-item>
95
      <el-form-item label="上传头像" prop="titlePicture">
96
        <el-upload
97
          class="avatar-uploader"
98
          :action="dialogImageUrl"
99
          :show-file-list="false"
100
          :on-success="handlePictureCardPreview"
101
          name="file"
102
        >
103
          <img
104
            v-if="this.dataForm.avatar"
105
            :src="this.dataForm.avatar"
106
            class="avatar"
107
          />
108
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
109
        </el-upload>
110
      </el-form-item>
111
    </el-form>
112
    <span slot="footer" class="dialog-footer">
113
      <el-button @click="visible = false">取消</el-button>
114
      <el-button type="primary" @click="dataFormSubmit()">确定</el-button>
115
    </span>
116
  </el-dialog>
117
</template>
118
119
<script>
120
import { isEmail, isMobile } from "@/utils/validate";
121
import { treeDataTranslate } from '@/utils'
122
export default {
123
  data() {
124
    var validatePassword = (rule, value, callback) => {
125
      if (!this.dataForm.id && !/\S/.test(value)) {
126
        callback(new Error("密码不能为空"));
127
      } else {
128
        callback();
129
      }
130
    };
131
    var validateComfirmPassword = (rule, value, callback) => {
132
      if (!this.dataForm.id && !/\S/.test(value)) {
133
        callback(new Error("确认密码不能为空"));
134
      } else if (this.dataForm.password !== value) {
135
        callback(new Error("确认密码与密码输入不一致"));
136
      } else {
137
        callback();
138
      }
139
    };
140
    var validateEmail = (rule, value, callback) => {
141
      if (!isEmail(value)) {
142
        callback(new Error("邮箱格式错误"));
143
      } else {
144
        callback();
145
      }
146
    };
147
    var validateMobile = (rule, value, callback) => {
148
      if (!isMobile(value)) {
149
        callback(new Error("手机号格式错误"));
150
      } else {
151
        callback();
152
      }
153
    };
154
    return {
155
      visible: false,
156
      dialogImageUrl: "",
157
      roleList: [],
158
      dataForm: {
159
        id: 0,
160
        userName: "",
161
        password: "",
162
        comfirmPassword: "",
163
        salt: "",
164
        email: "",
165
        mobile: "",
166
        roleIdList: [],
167
        status: 1,
168
        avatar: "",
169
        departmentId:"",
170
        departmentName:"",
171
      },
172
      departmentList: [],
173
        menuListTreeProps: {
174
          label: 'departmentName',
175
          children: 'children'
176
        },
177
      dataRule: {
178
        userName: [
179
          { required: true, message: "用户名不能为空", trigger: "blur" },
180
        ],
181
        password: [{ validator: validatePassword, trigger: "blur" }],
182
        comfirmPassword: [
183
          { validator: validateComfirmPassword, trigger: "blur" },
184
        ],
185
        email: [
186
          { required: true, message: "邮箱不能为空", trigger: "blur" },
187
          { validator: validateEmail, trigger: "blur" },
188
        ],
189
        mobile: [
190
          { required: true, message: "手机号不能为空", trigger: "blur" },
191
          { validator: validateMobile, trigger: "blur" },
192
        ],
193
      },
194
    };
195
  },
196
  methods: {
197
    // 上传成功
198
    handlePictureCardPreview(response, file) {
199
      console.log(response);
200
      this.dataForm.avatar = response.url;
201
    },
202
    getClientName(e) {
203
      console.log(e);
204
      let obj = {};
205
      obj = this.departmentList.find((item) => {
206
        return item.departmentId === e;
207
      });
208
      console.log(obj);
209
      console.log(obj.name);
210
      this.dataForm.departmentId = e;
211
    },
212
    init(id) {
213
      this.dataForm.id = id || 0;
214
      this.$http({
215
        url: this.$http.adornUrl("/sys/user/index"),
216
        method: "get",
217
        params: this.$http.adornParams(),
218
      }).then(({ data }) => {
219
          this.departmentList = treeDataTranslate(data.list, 'departmentId')
220
      }).then(() => {
221
          this.visible = true
222
          this.$nextTick(() => {
223
            this.$refs['dataForm'].resetFields()
224
          })
225
        })
226
      this.$http({
227
        url: this.$http.adornUrl("/sys/user/index"),
228
        method: "get",
229
        params: this.$http.adornParams(),
230
      })
231
        .then(({ data }) => {
232
          this.roleList = data && data.code === 0 ? data.list : [];
233
        })
234
        .then(() => {
235
          this.visible = true;
236
          this.$nextTick(() => {
237
            this.$refs["dataForm"].resetFields();
238
          });
239
        })
240
        .then(() => {
241
          if (this.dataForm.id) {
242
            this.$http({
243
              url: this.$http.adornUrl(`/sys/user/info/${this.dataForm.id}`),
244
              method: "get",
245
              params: this.$http.adornParams(),
246
            }).then(({ data }) => {
247
              if (data && data.code === 0) {
248
                this.dataForm.userName = data.user.username;
249
                this.dataForm.salt = data.user.salt;
250
                this.dataForm.email = data.user.email;
251
                this.dataForm.mobile = data.user.mobile;
252
                this.dataForm.roleIdList = data.user.roleIdList;
253
                this.dataForm.status = data.user.status;
254
                this.dataForm.avatar = data.user.avatar;
255
                this.dataForm.departmentId = data.user.departmentId;
256
                this.dataForm.departmentName = data.user.departmentName;
257
                this.menuListTreeSetCurrentNode()
258
              }
259
            });
260
          }else{
261
            this.menuListTreeSetCurrentNode()
262
          }
263
        });
264
      // this.dialogImageUrl = this.$http.adornUrl(
265
      //   `/sys/oss/uploadimg?token=${this.$cookie.get("token")}`
266
      // );
267
      // console.log(this.dialogImageUrl);
268
    },
269
    // 菜单树选中
270
      departmentListTreeCurrentChangeHandle (data, node) {
271
        this.dataForm.departmentId = data.departmentId
272
        this.dataForm.departmentName = data.departmentName
273
      },
274
      // 菜单树设置当前选中节点
275
      menuListTreeSetCurrentNode () {
276
        this.$refs.departmentListTree.setCurrentKey(this.dataForm.departmentId)
277
        this.dataForm.departmentName = (this.$refs.departmentListTree.getCurrentNode() || {})['departmentName']
278
      },
279
    // 表单提交
280
    dataFormSubmit() {
281
      this.$refs["dataForm"].validate((valid) => {
282
        if (valid) {
283
          this.$http({
284
            url: this.$http.adornUrl(
285
              `/sys/user/${!this.dataForm.id ? "save" : "update"}`
286
            ),
287
            method: "post",
288
            data: this.$http.adornData({
289
              userId: this.dataForm.id || undefined,
290
              username: this.dataForm.userName,
291
              password: this.dataForm.password,
292
              salt: this.dataForm.salt,
293
              email: this.dataForm.email,
294
              mobile: this.dataForm.mobile,
295
              status: this.dataForm.status,
296
              roleIdList: this.dataForm.roleIdList,
297
              departmentId: this.dataForm.departmentId,
298
              avatar: this.dataForm.avatar,
299
            }),
300
          }).then(({ data }) => {
301
            if (data && data.code === 0) {
302
              this.$message({
303
                message: "操作成功",
304
                type: "success",
305
                duration: 1500,
306
                onClose: () => {
307
                  this.visible = false;
308
                  this.$emit("refreshDataList");
309
                },
310
              });
311
            } else {
312
              this.$message.error(data.msg);
313
            }
314
          });
315
        }
316
      });
317
    },
318
  },
319
};
320
</script>
321
<style lang="scss">
322
.avatar-uploader .el-upload {
323
  border: 1px dashed #d9d9d9;
324
  border-radius: 6px;
325
  cursor: pointer;
326
  position: relative;
327
  overflow: hidden;
328
}
329
.avatar-uploader .el-upload:hover {
330
  border-color: #409eff;
331
}
332
.avatar-uploader-icon {
333
  font-size: 28px;
334
  color: #8c939d;
335
  width: 178px;
336
  height: 178px;
337
  line-height: 178px;
338
  text-align: center;
339
}
340
.avatar {
341
  width: 178px;
342
  height: 178px;
343
  display: block;
344
}
345
</style>

+ 195 - 0
src/views/user/user.vue

1
<template>
2
  <div class="app-container">
3
    <el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()"  label-width="120px">
4
      <el-form-item>
5
        <el-input v-model="dataForm.userName" placeholder="用户名" clearable></el-input>
6
      </el-form-item>
7
      <el-form-item>
8
        <el-button @click="getDataList()">查询</el-button>
9
        <el-button v-if="" type="primary" @click="addOrUpdateHandle()">新增</el-button>
10
        <el-button v-if="" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0">批量删除</el-button>
11
      </el-form-item>
12
    </el-form>
13
    <el-table
14
      :data="dataList"
15
      border
16
      v-loading="dataListLoading"
17
      @selection-change="selectionChangeHandle"
18
      style="width: 100%;">
19
      <el-table-column
20
        type="selection"
21
        header-align="center"
22
        align="center"
23
        width="50">
24
      </el-table-column>
25
      <el-table-column
26
        prop="userid"
27
        header-align="center"
28
        align="center"
29
        width="80"
30
        label="ID">
31
      </el-table-column>
32
      <el-table-column
33
        prop="username"
34
        header-align="center"
35
        align="center"
36
        label="用户名">
37
      </el-table-column>
38
      <el-table-column
39
        prop="email"
40
        header-align="center"
41
        align="center"
42
        label="邮箱">
43
      </el-table-column>
44
      <el-table-column
45
        prop="rolename"
46
        header-align="center"
47
        align="center"
48
        label="用户组">
49
      </el-table-column>
50
      <el-table-column
51
        prop="status"
52
        header-align="center"
53
        align="center"
54
        label="状态">
55
        <template slot-scope="scope">
56
          <el-tag v-if="scope.row.status === 0" size="small" type="danger">禁用</el-tag>
57
          <el-tag v-else size="small">正常</el-tag>
58
        </template>
59
      </el-table-column>
60
      <el-table-column
61
        prop="create_time"
62
        header-align="center"
63
        align="center"
64
        width="180"
65
        label="创建时间">
66
      </el-table-column>
67
      <el-table-column
68
        fixed="right"
69
        header-align="center"
70
        align="center"
71
        width="150"
72
        label="操作">
73
        <template slot-scope="scope">
74
          <el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.userId)">修改</el-button>
75
          <el-button type="text" size="small" @click="deleteHandle(scope.row.userId)">删除</el-button>
76
        </template>
77
      </el-table-column>
78
    </el-table>
79
    <el-pagination
80
      @size-change="sizeChangeHandle"
81
      @current-change="currentChangeHandle"
82
      :current-page="pageIndex"
83
      :page-sizes="[10, 20, 50, 100]"
84
      :page-size="pageSize"
85
      :total="totalPage"
86
      layout="total, sizes, prev, pager, next, jumper">
87
    </el-pagination>
88
    <!-- 弹窗, 新增 / 修改 -->
89
    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
90
  </div>
91
</template>
92
93
<script>
94
  import AddOrUpdate from './user-add-or-update'
95
  export default {
96
    data () {
97
      return {
98
        dataForm: {
99
          userName: ''
100
        },
101
        dataList: [],
102
        pageIndex: 1,
103
        pageSize: 10,
104
        totalPage: 0,
105
        dataListLoading: false,
106
        dataListSelections: [],
107
        addOrUpdateVisible: false
108
      }
109
    },
110
    components: {
111
      AddOrUpdate
112
    },
113
    created () {
114
      this.getDataList()
115
    },
116
    methods: {
117
      // 获取数据列表
118
      getDataList () {
119
        this.dataListLoading = true
120
        console.log(1);
121
        this.$http({
122
          url: this.$http.adornUrl('/sys/user/index'),
123
          method: 'get',
124
          params: this.$http.adornParams({
125
            'page': this.pageIndex,
126
            'limit': this.pageSize,
127
            'username': this.dataForm.userName
128
          })
129
        }).then(({data}) => {
130
         console.log(data);
131
          if (data && data.code === 0) {
132
            this.dataList = data.data.data
133
            this.totalPage = data.data.total
134
          } else {
135
            this.dataList = []
136
            this.totalPage = 0
137
          }
138
          this.dataListLoading = false
139
        })
140
      },
141
      // 每页数
142
      sizeChangeHandle (val) {
143
        this.pageSize = val
144
        this.pageIndex = 1
145
        this.getDataList()
146
      },
147
      // 当前页
148
      currentChangeHandle (val) {
149
        this.pageIndex = val
150
        this.getDataList()
151
      },
152
      // 多选
153
      selectionChangeHandle (val) {
154
        this.dataListSelections = val
155
      },
156
      // 新增 / 修改
157
      addOrUpdateHandle (id) {
158
        this.addOrUpdateVisible = true
159
        this.$nextTick(() => {
160
          this.$refs.addOrUpdate.init(id)
161
        })
162
      },
163
      // 删除
164
      deleteHandle (id) {
165
        var userIds = id ? [id] : this.dataListSelections.map(item => {
166
          return item.userId
167
        })
168
        this.$confirm(`确定对[id=${userIds.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
169
          confirmButtonText: '确定',
170
          cancelButtonText: '取消',
171
          type: 'warning'
172
        }).then(() => {
173
          this.$http({
174
            url: this.$http.adornUrl('/sys/user/delete'),
175
            method: 'post',
176
            data: this.$http.adornData(userIds, false)
177
          }).then(({data}) => {
178
            if (data && data.code === 0) {
179
              this.$message({
180
                message: '操作成功',
181
                type: 'success',
182
                duration: 1500,
183
                onClose: () => {
184
                  this.getDataList()
185
                }
186
              })
187
            } else {
188
              this.$message.error(data.msg)
189
            }
190
          })
191
        }).catch(() => {})
192
      }
193
    }
194
  }
195
</script>

+ 14 - 2
vue.config.js

27
  publicPath: '/',
27
  publicPath: '/',
28
  outputDir: 'dist',
28
  outputDir: 'dist',
29
  assetsDir: 'static',
29
  assetsDir: 'static',
30
  lintOnSave: process.env.NODE_ENV === 'development',
30
  // lintOnSave: process.env.NODE_ENV === 'development',
31
  lintOnSave: false,
31
  productionSourceMap: false,
32
  productionSourceMap: false,
32
  devServer: {
33
  devServer: {
33
    port: port,
34
    port: port,
36
      warnings: false,
37
      warnings: false,
37
      errors: true
38
      errors: true
38
    },
39
    },
39
    before: require('./mock/mock-server.js')
40
    // before: require('./mock/mock-server.js')
41
    proxy: {
42
      [process.env.VUE_APP_BASE_API]: {
43
        target: `http://192.168.2.251:8010`,
44
        changeOrigin: true,
45
        ws: true,
46
        secure: false,
47
        pathRewrite: {
48
          ["^" + process.env.VUE_APP_BASE_API]: ""
49
        }
50
      }
51
    }
40
  },
52
  },
41
  configureWebpack: {
53
  configureWebpack: {
42
    // provide the app's title in webpack's name field, so that
54
    // provide the app's title in webpack's name field, so that