Ver código fonte

用户管理完成

程志平 4 anos atrás
pai
commit
60758d26b8

+ 1 - 1
.env.development

@@ -2,4 +2,4 @@
 ENV = 'development'
 
 # base api
-VUE_APP_BASE_API = '/dev-api'
+VUE_APP_BASE_API = ''

+ 1 - 1
.env.production

@@ -2,5 +2,5 @@
 ENV = 'production'
 
 # base api
-VUE_APP_BASE_API = '/prod-api'
+VUE_APP_BASE_API = ''
 

BIN
public/favicon.ico


+ 9 - 0
src/api/index.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function ceshi(data) {
+	return request({
+		url: '',
+		method: 'post',
+		data
+	})
+}

+ 21 - 0
src/api/systemSet.js

@@ -0,0 +1,21 @@
+import request from '@/utils/request'
+
+export function updateSet(data) {
+	return request({
+		url: '/airManage/configupdate.action',
+		method: 'post',
+		data
+	})
+}
+
+export function getSet(formData) {
+	let data = new FormData()
+	data.append('page', formData.page)
+	data.append('rows', formData.rows)
+	
+	return request({
+		url: '/airManage/configlist.action',
+		method: 'post',
+		data
+	})
+}

+ 0 - 9
src/api/table.js

@@ -1,9 +0,0 @@
-import request from '@/utils/request'
-
-export function getList(params) {
-  return request({
-    url: '/vue-admin-template/table/list',
-    method: 'get',
-    params
-  })
-}

+ 21 - 15
src/api/user.js

@@ -1,24 +1,30 @@
 import request from '@/utils/request'
 
-export function login(data) {
-  return request({
-    url: '/vue-admin-template/user/login',
-    method: 'post',
-    data
-  })
+export function login(forData) {
+	let data = new FormData()
+	data.append('admin_name', forData.username)
+	data.append('password', forData.password)
+	
+	return request({
+		url: '/airManage/adminlogin.action',
+		method: 'post',
+		data
+	})
 }
 
 export function getInfo(token) {
-  return request({
-    url: '/vue-admin-template/user/info',
-    method: 'get',
-    params: { token }
-  })
+	return request({
+		url: '/airManage/info',
+		method: 'get',
+		params: {
+			token
+		}
+	})
 }
 
 export function logout() {
-  return request({
-    url: '/vue-admin-template/user/logout',
-    method: 'post'
-  })
+	return request({
+		url: '/airManage/adminlogin.action',
+		method: 'post'
+	})
 }

+ 47 - 0
src/api/userMgr.js

@@ -0,0 +1,47 @@
+import service from '@/utils/request'
+import request from '@/utils/request'
+
+// 用户列表
+export function getUserList(forData) {
+	let data = new FormData()
+	data.append('page', forData.page)
+	data.append('rows', forData.rows)
+	if (typeof forData.name_card != 'undefined') {
+		data.append('name_card', forData.name_card)
+	}
+	if (typeof forData.classfy != 'undefined') {
+		data.append('classfy', forData.classfy)
+	}
+
+	return request({
+		url: '/airManage/userslist.action',
+		method: 'post',
+		data
+	})
+}
+
+// 新增用户
+export function addUser(data) {
+	return request({
+		url: '/airManage/usersinsert.action',
+		method: 'post',
+		data
+	})
+}
+
+// 充值
+export function chongzhi(data) {
+	return request({
+		url: '/airManage/usersupdateBalance.action',
+		method: 'post',
+		data
+	})
+}
+
+// 下载
+export function downloadExcel() {
+	return request({
+		url: '/airManage/userstoExcel.action',
+		method: 'post'
+	})
+}

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

@@ -73,7 +73,7 @@
 		},
 		data() {
 			return {
-				role: '管理员',
+				role: this.$store.state.user.name,
 				date_show: '',
 				time_show: '',
 				week_show: ''

+ 2 - 2
src/permission.js

@@ -32,7 +32,8 @@ router.beforeEach(async(to, from, next) => {
       } else {
         try {
           // get user info
-          await store.dispatch('user/getInfo')
+		  // 修改:下一行注释了
+          // await store.dispatch('user/getInfo')
 
           next()
         } catch (error) {
@@ -46,7 +47,6 @@ router.beforeEach(async(to, from, next) => {
     }
   } else {
     /* has no token*/
-
     if (whiteList.indexOf(to.path) !== -1) {
       // in the free login whitelist, go directly
       next()

+ 5 - 5
src/router/index.js

@@ -58,13 +58,13 @@ export const constantRoutes = [{
 	},
 
 	{
-		path: '/userManager',
+		path: '/userMgr',
 		component: Layout,
-		redirect: '/userManager',
+		redirect: '/userMgr',
 		children: [{
-			path: 'userManager',
-			name: 'UserManager',
-			component: () => import('@/views/user/index'),
+			path: 'userMgr',
+			name: 'UserMgr',
+			component: () => import('@/views/userMgr/index'),
 			meta: {
 				title: '用户管理',
 				icon: 'user_menu'

+ 45 - 29
src/store/modules/user.js

@@ -33,9 +33,16 @@ const actions = {
     const { username, password } = userInfo
     return new Promise((resolve, reject) => {
       login({ username: username.trim(), password: password }).then(response => {
-        const { data } = response
-        commit('SET_TOKEN', data.token)
-        setToken(data.token)
+        // const { data } = response
+        // commit('SET_TOKEN', data.token)
+        // setToken(data.token)
+		// 修改:token固定
+		const token = 'admin_token'
+        commit('SET_TOKEN', token)
+        setToken(token)
+		// 添加:
+		commit('SET_NAME', username)
+		// ============================
         resolve()
       }).catch(error => {
         reject(error)
@@ -44,38 +51,47 @@ const actions = {
   },
 
   // get user info
-  getInfo({ commit, state }) {
-    return new Promise((resolve, reject) => {
-      getInfo(state.token).then(response => {
-        const { data } = response
+  // 修改:获取用户信息被注释了
+  // getInfo({ commit, state }) {
+  //   return new Promise((resolve, reject) => {
+  //     getInfo(state.token).then(response => {
+  //       const { data } = response
 
-        if (!data) {
-          return reject('Verification failed, please Login again.')
-        }
+  //       if (!data) {
+  //         return reject('Verification failed, please Login again.')
+  //       }
 
-        const { name, avatar } = data
+  //       const { name, avatar } = data
 
-        commit('SET_NAME', name)
-        commit('SET_AVATAR', avatar)
-        resolve(data)
-      }).catch(error => {
-        reject(error)
-      })
-    })
-  },
+  //       commit('SET_NAME', name)
+  //       commit('SET_AVATAR', avatar)
+  //       resolve(data)
+  //     }).catch(error => {
+  //       reject(error)
+  //     })
+  //   })
+  // },
 
   // user logout
   logout({ commit, state }) {
-    return new Promise((resolve, reject) => {
-      logout(state.token).then(() => {
-        removeToken() // must remove  token  first
-        resetRouter()
-        commit('RESET_STATE')
-        resolve()
-      }).catch(error => {
-        reject(error)
-      })
-    })
+	  return new Promise((resolve, reject) => {
+		removeToken() // must remove  token  first
+		resetRouter()
+		commit('RESET_STATE')
+		commit('SET_NAME')
+		resolve()
+	  })
+	// 修改:下面被注释了
+    // return new Promise((resolve, reject) => {
+    //   logout(state.token).then(() => {
+    //     removeToken() // must remove  token  first
+    //     resetRouter()
+    //     commit('RESET_STATE')
+    //     resolve()
+    //   }).catch(error => {
+    //     reject(error)
+    //   })
+    // })
   },
 
   // remove token

+ 2 - 2
src/utils/auth.js

@@ -1,6 +1,6 @@
 import Cookies from 'js-cookie'
 
-const TokenKey = 'vue_admin_template_token'
+const TokenKey = 'admin_token'
 
 export function getToken() {
   return Cookies.get(TokenKey)
@@ -12,4 +12,4 @@ export function setToken(token) {
 
 export function removeToken() {
   return Cookies.remove(TokenKey)
-}
+}

+ 78 - 68
src/utils/request.js

@@ -1,85 +1,95 @@
 import axios from 'axios'
-import { MessageBox, Message } from 'element-ui'
+import {
+	MessageBox,
+	Message
+} from 'element-ui'
 import store from '@/store'
-import { getToken } from '@/utils/auth'
+import {
+	getToken
+} from '@/utils/auth'
 
-// create an axios instance
+// 创建axios实例
 const service = axios.create({
-  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
-  // withCredentials: true, // send cookies when cross-domain requests
-  timeout: 5000 // request timeout
+	baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
+	// withCredentials: true, // 跨域请求时发送cookie
+	timeout: 5000 // 请求超时
 })
 
-// request interceptor
+// 请求拦截器
 service.interceptors.request.use(
-  config => {
-    // do something before request is sent
+	config => {
+		// 在发送请求之前做些什么
 
-    if (store.getters.token) {
-      // let each request carry token
-      // ['X-Token'] is a custom headers key
-      // please modify it according to the actual situation
-      config.headers['X-Token'] = getToken()
-    }
-    return config
-  },
-  error => {
-    // do something with request error
-    console.log(error) // for debug
-    return Promise.reject(error)
-  }
+		if (store.getters.token) {
+			// 让每个请求携带令牌
+			// ['X-Token'] 是否为自定义标题键
+			// 请根据实际情况进行修改
+			config.headers['X-Token'] = getToken()
+		}
+		return config
+	},
+	error => {
+		// 处理请求错误
+		console.log(error) // 调试命令
+		return Promise.reject(error)
+	}
 )
 
-// response interceptor
+// 响应拦截器
 service.interceptors.response.use(
-  /**
-   * If you want to get http information such as headers or status
-   * Please return  response => response
-  */
+	/**
+	 * 如果您想要获取http信息,如header或状态
+	 * 请返回  response => response
+	 */
 
-  /**
-   * Determine the request status by custom code
-   * Here is just an example
-   * You can also judge the status by HTTP Status Code
-   */
-  response => {
-    const res = response.data
+	/**
+	 * 通过自定义代码确定请求状态
+	 * 这只是一个例子
+	 * 您也可以通过“HTTP状态码”来判断状态
+	 */
+	response => {
+		const res = response.data
 
-    // if the custom code is not 20000, it is judged as an error.
-    if (res.code !== 20000) {
-      Message({
-        message: res.message || 'Error',
-        type: 'error',
-        duration: 5 * 1000
-      })
+		// 如果定制代码不是20000,则判定为错误。
+		if (res.code !== 200) {
+			// 返回格式不规范,也只能如此了
+			return res
+			
+			Message({
+				message: res.message || '返回信息中无code,无法解析数据',
+				type: 'error',
+				duration: 5 * 1000
+			})
 
-      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
-      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
-        // to re-login
-        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
-          confirmButtonText: 'Re-Login',
-          cancelButtonText: 'Cancel',
-          type: 'warning'
-        }).then(() => {
-          store.dispatch('user/resetToken').then(() => {
-            location.reload()
-          })
-        })
-      }
-      return Promise.reject(new Error(res.message || 'Error'))
-    } else {
-      return res
-    }
-  },
-  error => {
-    console.log('err' + error) // for debug
-    Message({
-      message: error.message,
-      type: 'error',
-      duration: 5 * 1000
-    })
-    return Promise.reject(error)
-  }
+			// 50008: 非法的令牌; 50012: 其他客户端已登录; 50014: 过期令牌;
+			if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
+				// 重新登陆
+				MessageBox.confirm('您已注销,您可以取消留在此页面,或重新登录',
+					'确认注销', {
+						confirmButtonText: '重新登入',
+						cancelButtonText: '取消',
+						type: 'warning'
+					}).then(() => {
+					store.dispatch('user/resetToken').then(() => {
+						location.reload()
+					})
+				})
+			}
+			
+			return Promise.reject(new Error(res.message || '未知错误'))
+		} else {
+			return res
+		}
+	},
+	error => {
+		console.log('错误:' + error) // 用于调试
+		Message({
+			message: error.message,
+			type: 'error',
+			duration: 5 * 1000
+		})
+		return Promise.reject(error)
+	}
 )
 
 export default service

+ 9 - 5
src/views/login/index.vue

@@ -9,8 +9,7 @@
 				<div id="caption">登录</div>
 				<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
 					label-position="left">
-
-
+					
 					<el-form-item prop="username">
 						<span class="svg-container">
 							<svg-icon icon-class="login_home" />
@@ -68,7 +67,7 @@
 			return {
 				loginForm: {
 					username: 'admin',
-					password: '111111'
+					password: '123456'
 				},
 				loginRules: {
 					username: [{
@@ -106,6 +105,9 @@
 					this.$refs.password.focus()
 				})
 			},
+			/**
+			 * 登录
+			 */
 			handleLogin() {
 				this.$refs.loginForm.validate(valid => {
 					if (valid) {
@@ -115,11 +117,13 @@
 								path: this.redirect || '/'
 							})
 							this.loading = false
-						}).catch(() => {
+						}).catch((err) => {
+							// console.log(err);
+							// this.$message.error(err.message)
 							this.loading = false
 						})
 					} else {
-						console.log('error submit!!')
+						this.$message.error('请输入账号或密码!')
 						return false
 					}
 				})

+ 234 - 74
src/views/systemSet/index.vue

@@ -9,54 +9,47 @@
 						</div>
 					</div>
 					<div class="cell-body">
-						<el-row>
-							<el-col :span="24">
-								<div>空调开启半小时不足1小时为</div>
-								<el-input placeholder="请输入金额" v-model="less_than_an_hour"></el-input>
-								<div>元</div>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>空调开启每小时为</div>
-								<el-input placeholder="请输入金额" v-model="per_hour"></el-input>
-								<div>元</div>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>自动扣款</div>
-								<el-switch v-model="withhold" active-color="#2B4CFE">
-								</el-switch>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>账户余额少于</div>
-								<el-input placeholder="请输入金额" v-model="balance_less_than"></el-input>
-								<div>元,不能开启空调</div>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>每隔</div>
-								<el-input placeholder="请输入小时数" v-model="hour"></el-input>
-								<div>小时,系统自动发送通知给操作员</div>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>每天</div>
-								<el-input placeholder="请输入时间" v-model="every_day"></el-input>
-								<div>为截止时间,系统自动发送通知给操作员</div>
-							</el-col>
-						</el-row>
-						<el-row>
-							<el-col :span="24">
-								<div>使用问题联系方式</div>
-								<el-input class="contact-style" placeholder="请输入手机号" v-model="contact"></el-input>
-							</el-col>
-						</el-row>
+						<el-form ref="formData" :rules="formRules" :model="formData">
+							<el-form-item prop="noOne">
+								<span>空调开启半小时不足1小时为</span>
+								<el-input v-model="formData.noOne" maxlength="2" placeholder="请输入金额"></el-input>
+								<span>元</span>
+							</el-form-item>
+							<el-form-item prop="one">
+								<span>空调开启每小时为</span>
+								<el-input v-model="formData.one" maxlength="2" placeholder="请输入金额"></el-input>
+								<span>元</span>
+							</el-form-item>
+							<el-form-item prop="isauto">
+								<span>自动扣款</span>
+								<el-switch v-model="formData.isauto" active-color="#2B4CFE"></el-switch>
+							</el-form-item>
+							<el-form-item prop="start_tiao">
+								<span>账户余额少于</span>
+								<el-input v-model="formData.start_tiao" maxlength="2" placeholder="请输入金额"></el-input>
+								<span>元,不能开启空调</span>
+							</el-form-item>
+							<el-form-item prop="send_jian">
+								<span>每隔</span>
+								<el-input v-model="formData.send_jian" maxlength="2" placeholder="请输入小时数"></el-input>
+								<span>小时,系统自动发送通知给操作员</span>
+							</el-form-item>
+							<el-form-item prop="send_start">
+								<span>每天</span>
+								<el-time-picker :editable="false" v-model="formData.send_start" :picker-options="{
+										    start: '00:00',step: '00:01',end: '23:59'
+									}" value-format="HH:mm:ss" placeholder="请输入时间" :clearable="false">
+								</el-time-picker>
+								<span>为截止时间,系统自动发送通知给操作员</span>
+							</el-form-item>
+							<el-form-item prop="phone">
+								<span>使用问题联系方式</span>
+								<el-input v-model="formData.phone" placeholder="请输入手机号" maxlength="11" class="phone-class"></el-input>
+							</el-form-item>
+							<el-form-item>
+								<el-button type="primary" round @click="handle_submit">确认提交</el-button>
+							</el-form-item>
+						</el-form>
 					</div>
 				</div>
 			</el-col>
@@ -65,20 +58,154 @@
 </template>
 
 <script>
+	import {
+		updateSet,
+		getSet
+	} from '@/api/systemSet';
+
 	export default {
 		data() {
+			var checkMoney = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('金额不能为空'));
+				}
+				setTimeout(() => {
+					var reg = /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/
+					if (!reg.test(value)) {
+						callback(new Error('请输入数值型,可保留2位小数'));
+					} else if (value < 0.01 || value > 10) {
+						callback(new Error('范围在0.01-10'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			var checkTime = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('不能为空'));
+				}
+				setTimeout(() => {
+					var reg = /^(\d{1,})$/
+					if (!reg.test(value)) {
+						callback(new Error('请输入整数值'));
+					} else if (value < 1 || value > 10) {
+						callback(new Error('范围在1-10'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			var checkPhone = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请输入手机号'));
+				}
+				setTimeout(() => {
+					var reg = /^1[3456789]\d{9}$/
+					if (!reg.test(value)) {
+						callback(new Error('手机号格式不对'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
 			return {
-				less_than_an_hour: 3, // 半小时不足1小时
-				per_hour: 5, // 每小时
-				withhold: true,
-				balance_less_than: 5,
-				hour: 1,
-				every_day: '19:00',
-				contact: '13677985689'
+				formData: {
+					noOne: '', // 半小时不足1小时
+					one: '', // 每小时
+					isauto: true, // 自动扣款
+					start_tiao: '',
+					send_jian: '',
+					send_start: '',
+					phone: '',
+					state: 1,
+				},
+				currentPage: 1,
+				rows: 6,
+				// 校验规则
+				formRules: {
+					noOne: [{
+						validator: checkMoney
+					}],
+					one: [{
+						validator: checkMoney
+					}],
+					start_tiao: [{
+						validator: checkMoney
+					}],
+					send_jian: [{
+						validator: checkTime
+					}],
+					phone: [{
+						validator: checkPhone
+					}]
+				}
 			}
 		},
+		mounted() {
+			this.get_data()
+		},
 		methods: {
-
+			/**
+			 * 获取配置数据
+			 */
+			get_data() {
+				const params = {
+					page: this.currentPage,
+					rows: this.rows
+				}
+				// 开始发送请求,获取配置数据
+				getSet(params).then((res) => {
+					// console.log(res.rows[0]);
+					let r = res.rows[0]
+					this.formData.noOne = r.noOne
+					this.formData.one = r.one
+					this.formData.isauto = r.isauto == 1 ? true : false
+					this.formData.start_tiao = r.start_tiao
+					this.formData.send_jian = r.send_jian
+					this.formData.send_start = r.send_start
+					this.formData.phone = r.phone
+					this.formData.state = r.state
+				}).catch((err) => {
+					// console.log(err);
+					this.$message.error(err.message)
+				})
+			},
+			/**
+			 * 提交修改后的配置
+			 */
+			handle_submit() {
+				this.$refs["formData"].validate(validate => {
+					if (validate) {
+						//form表单校验通过,可以进行下一步操作
+						const params = {
+							id: 1,
+							noOne: this.formData.noOne,
+							one: this.formData.one,
+							isauto: this.formData.isauto == true ? 1 : 0,
+							start_tiao: this.formData.start_tiao,
+							send_jian: this.formData.send_jian,
+							send_start: this.formData.send_start,
+							phone: this.formData.phone,
+							state: this.formData.state
+						}
+						// 开始发送更新配置请求
+						updateSet(params).then((res) => {
+							// console.log(res);
+							if (res.code === 200) {
+								this.$message.success(res.message)
+							} else {
+								this.$message.error(res.message)
+							}
+						}).catch((err) => {
+							// console.log(err);
+							this.$message.error(err.message)
+						})
+					} else {
+						this.$message.error('验证不通过')
+						return false
+					}
+				})
+			}
 		}
 	}
 </script>
@@ -119,34 +246,67 @@
 					.cell-body {
 						height: 630px;
 
-						.el-row {
+						::v-deep .el-form-item {
+							display: flex;
+							align-items: center;
+							white-space: nowrap;
 
-							.el-col {
-								display: flex;
-								align-items: center;
-								white-space: nowrap;
+							span {
+								font-size: 16px;
+								font-family: Microsoft YaHei-3970(82674968);
+								color: #46515E;
+							}
 
-								::v-deep .el-input,
-								::v-deep .el-input__inner {
-									width: 90px;
-									text-align: center;
-									font-size: 18px;
-									font-family: Microsoft YaHei-3970(82674968);
-									color: #46515E;
-								}
+							.el-input,
+							.el-input__inner {
+								width: 90px;
+								text-align: center;
+								font-size: 18px;
+								font-family: Microsoft YaHei-3970(82674968);
+								color: #46515E;
+							}
+
+							.el-input {
+								margin: 0 10px;
+								width: 140px;
 
-								::v-deep .el-input {
-									margin: 0 10px;
+								.el-input__inner {
+									width: 140px;
 								}
+							}
+
+							.el-switch {
+								margin: 0 10px;
+							}
+
+							.el-date-editor--time {
+								width: 150px;
 
-								::v-deep .contact-style.el-input .el-input__inner {
+								.el-input__inner {
 									width: 150px;
 								}
+							}
+
+							.phone-class {
+								width: 160px;
+
+								.el-input__inner {
+									width: 160px;
+								}
+							}
+
+							.el-button.el-button--primary {
+								background: #3660FF;
+								font-size: 18px;
 
-								.el-switch {
-									margin: 0 10px;
+								span {
+									color: #FFFFFF;
 								}
 							}
+
+							.el-form-item__error {
+								font-size: 16px
+							}
 						}
 					}
 				}

+ 0 - 455
src/views/user/index.vue

@@ -1,455 +0,0 @@
-<template>
-	<div class="app-container">
-		<el-row>
-			<el-col :span="24">
-				<div class="cell">
-					<div class="cell-title">
-						<div class="title">用户管理</div>
-						<div class="title-right">
-							<el-button type="primary">导出表单</el-button>
-							<el-button type="warning">新增用户</el-button>
-						</div>
-					</div>
-					<div class="cell-body">
-						<el-form :inline="true" :model="formInline" class="demo-form-inline">
-							<el-form-item label="关键字:">
-								<el-input v-model="formInline.user" placeholder="请输入姓名或身份证"></el-input>
-							</el-form-item>
-							<el-form-item>
-								<el-button type="warning" @click="btn_search">查询</el-button>
-							</el-form-item>
-							<el-form-item label="">
-								<el-select v-model="formInline.category" placeholder="类别">
-									<el-option label="学生" value="shanghai"></el-option>
-									<el-option label="教工" value="beijing"></el-option>
-									<el-option label="员工" value="beijing"></el-option>
-								</el-select>
-							</el-form-item>
-						</el-form>
-						<el-table :data="tableData" height="510" style="width: 100%" :cell-style="cell_style"
-							:header-cell-style="header_cell_style">
-							<el-table-column label="序号" align="center" width="100">
-								<template slot-scope="scope">
-									<span>{{(pagination.currentPage - 1) * pagination.pageSize + scope.$index + 1}}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="姓名" align="center" width="100">
-								<template slot-scope="scope">
-									<span>{{ scope.row.name }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="手机" align="center" width="180">
-								<template slot-scope="scope">
-									<span>{{ scope.row.phone }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="身份证" align="center">
-								<template slot-scope="scope">
-									<span>{{ scope.row.identityCard }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="类别" align="center" width="100">
-								<template slot-scope="scope">
-									<span>{{ scope.row.category }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="年级" align="center" width="100">
-								<template slot-scope="scope">
-									<span>{{ scope.row.grade }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="账户余额(元)" align="center" width="180">
-								<template slot-scope="scope">
-									<span>{{ scope.row.accountBalance }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="备注" align="center">
-								<template slot-scope="scope">
-									<span>{{ scope.row.comment }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="操作" align="center">
-								<template slot-scope="scope">
-									<el-button size="mini" class="btn-table" @click="recharge(scope.$index, scope.row)">
-										充值</el-button>
-								</template>
-							</el-table-column>
-						</el-table>
-						<div class="pagination-table">
-							<el-pagination @current-change="currentPageChange"
-								:current-page.sync="pagination.currentPage" :page-size="pagination.pageSize"
-								layout="prev, pager, next, jumper" :total="pagination.total">
-							</el-pagination>
-						</div>
-					</div>
-				</div>
-			</el-col>
-		</el-row>
-		<el-dialog title="充值" :visible.sync="dialogFormVisible" :close-on-click-modal="false"
-			:close-on-press-escape="false" @close="dialog_close">
-			<el-form :model="form">
-				<el-form-item label="充值账号:" :label-width="formLabelWidth">
-					<div>{{form.account}}</div>
-				</el-form-item>
-				<el-form-item label="姓  名:" :label-width="formLabelWidth">
-					<div>{{form.name}}</div>
-				</el-form-item>
-				<el-form-item label="充值金额:" :label-width="formLabelWidth" :required="true">
-					<el-input v-model="form.amount" autocomplete="off"></el-input>
-				</el-form-item>
-				<el-form-item label="备  注:" :label-width="formLabelWidth">
-					<el-input type="textarea" v-model="form.desc"></el-input>
-				</el-form-item>
-			</el-form>
-			<div slot="footer" class="dialog-footer">
-				<el-button @click="dialogFormVisible = false">取 消</el-button>
-				<el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
-			</div>
-		</el-dialog>
-	</div>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {
-				// 弹出对话框数据
-				dialogFormVisible: false,
-				form: {
-					account: '',
-					name: '',
-					amount: '',
-					desc: ''
-				},
-				formLabelWidth: '120px',
-				// 表格单元格样式
-				cell_style: {
-					color: '#1A202B',
-					'font-size': '16px',
-					'font-family': 'Microsoft YaHei-3970(82674968)'
-				},
-				// 表格头部样式
-				header_cell_style: {
-					background: '#E6ECFE',
-					color: '#1A202B',
-					'font-size': '18px',
-					'font-family': 'Microsoft YaHei-3970(82674968)'
-				},
-				// 表单数据
-				formInline: {
-					user: '',
-					category: ''
-				},
-				tableData: [{
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}, {
-					name: '王小虎',
-					phone: '18988888888',
-					identityCard: '360123456789012345',
-					category: '学生',
-					grade: '大一',
-					accountBalance: 100.01,
-					comment: '充值100元'
-				}],
-				// 分页参数
-				pagination: {
-					pageSize: 10,
-					currentPage: 1,
-					total: 100
-				}
-			}
-		},
-		mounted() {
-			document.getElementsByClassName("el-pagination__jump")[0].childNodes[0].nodeValue = "跳至";
-		},
-		methods: {
-			btn_search() {
-				console.log('查询');
-			},
-			// 充值对话框初始化
-			recharge(index, row) {
-				// console.log(index, row);
-				this.dialogFormVisible = true
-				this.form.account = row.identityCard
-				this.form.name = row.name
-				this.form.desc = row.comment
-			},
-			// currentPage 改变时会触发
-			currentPageChange(val) {
-				console.log('当前页:' + val);
-			},
-			// 对话框关闭时清理数据
-			dialog_close() {
-				this.form = {}
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.app-container {
-		background-color: #EFF2F7;
-		padding: 10px;
-
-		.el-row {
-
-			.el-col {
-				padding: 10px;
-
-				.cell {
-					padding: 30px;
-					border-radius: 10px;
-					background-color: #FFFFFF;
-					// box-shadow: 5px 5px 15px #979797;
-					box-shadow: 0px 3px 21px 0px rgba(60, 108, 254, 0.16);
-
-					.cell-title {
-						display: flex;
-						justify-content: space-between;
-						align-items: center;
-						margin-bottom: 30px;
-						padding-bottom: 30px;
-						border-bottom: 1px solid #CCCCCC;
-
-						.title {
-							font-size: 22px;
-							font-family: Microsoft YaHei-3970(82674968);
-							font-weight: bold;
-							color: #1A202B;
-						}
-
-						.title-right {
-							display: flex;
-							justify-content: space-between;
-							align-items: center;
-
-							.el-button {
-								width: 110px;
-								height: 46px;
-								background: #2B4CFE;
-								font-size: 18px;
-								color: #FFFFFF;
-								font-family: Microsoft YaHei-3970(82674968);
-								border-radius: 5px;
-							}
-
-							.el-button--warning {
-								background: #F88A64;
-							}
-						}
-					}
-
-					.cell-body {
-
-						.el-button--warning {
-							background: #F88A64;
-						}
-
-						.btn-table {
-							border-radius: 15px !important;
-							border-color: #5488FE;
-							color: #5488FE;
-						}
-
-						.pagination-table {
-							display: flex;
-							justify-content: flex-end;
-							align-items: center;
-							height: 30px;
-							margin-top: 20px;
-							padding-right: 100px;
-
-							::v-deep .el-pagination {
-								display: flex;
-								justify-content: flex-end;
-								align-items: center;
-							}
-
-							::v-deep .el-pagination ul {
-								display: flex;
-
-							}
-
-							::v-deep .el-pagination button,
-							::v-deep .el-pagination li {
-								display: flex;
-								justify-content: center;
-								align-items: center;
-								width: 50px;
-								height: 36px;
-								border: 1px solid #626262;
-								border-radius: 3px;
-								font-size: 14px;
-								margin: 0 5px;
-							}
-
-							::v-deep .el-pagination span {
-								margin-left: 10px;
-							}
-
-							::v-deep .el-pagination .el-pagination__jump {
-								font-size: 16px;
-							}
-
-							::v-deep .el-pagination .el-pagination__editor {
-								width: 50px;
-								height: 36px;
-								margin: 0 5px;
-							}
-
-							::v-deep .el-pagination .el-input__inner {
-								width: 50px;
-								height: 36px;
-								border: 1px solid #626262;
-								margin: -4px 0 0 0;
-							}
-						}
-					}
-				}
-			}
-		}
-
-		::v-deep .el-dialog {
-			margin: 0 !important;
-			width: 600px;
-			height: 460px;
-			background: #FFFFFF;
-			box-shadow: 0px 0px 13px 0px rgba(0, 0, 0, 0.29);
-			border-radius: 10px;
-			position: absolute;
-			top: 50%;
-			left: 50%;
-			transform: translate(-50%, -50%);
-
-			.el-dialog__header {
-				display: flex;
-				align-items: center;
-				width: 100%;
-				height: 58px;
-				padding: 30px;
-				background: #E6EBFE;
-				border-radius: 10px 10px 0px 0px;
-				font-weight: bold;
-			}
-
-			.el-dialog__body {
-				padding-bottom: 0;
-
-				.el-form-item__label,
-				.el-form-item__content {
-					font-size: 16px;
-					font-family: Microsoft YaHei-3970(82674968);
-					color: #53575A;
-				}
-
-				.el-input__inner {
-					width: 100px;
-				}
-			}
-
-			.el-dialog__footer {
-				padding-bottom: 0 !important;
-				text-align: center;
-
-				.el-button.el-button--default {
-					width: 75px;
-					height: 40px;
-					border: 1px solid #2B4CFE;
-					border-radius: 6px;
-					font-size: 16px;
-					font-family: Microsoft YaHei-3970(82674968);
-					color: #2B4CFE;
-				}
-
-				.el-button.el-button--primary {
-					width: 75px;
-					height: 40px;
-					background: #2B4CFE;
-					border-radius: 6px;
-					font-size: 16px;
-					font-family: Microsoft YaHei-3970(82674968);
-					color: #FFFFFF;
-					margin-left: 60px;
-				}
-			}
-		}
-	}
-</style>

+ 713 - 0
src/views/userMgr/index.vue

@@ -0,0 +1,713 @@
+<template>
+	<div class="app-container">
+		<el-row>
+			<el-col :span="24">
+				<div class="cell">
+					<div class="cell-title">
+						<div class="title">用户管理</div>
+						<div class="title-right">
+							<el-button type="primary" @click="handler_download_excel">导出表单</el-button>
+							<el-button type="warning" @click="add_user">新增用户</el-button>
+						</div>
+					</div>
+					<div class="cell-body">
+						<el-form :inline="true" :model="formInline" class="demo-form-inline">
+							<el-form-item label="关键字:">
+								<el-input v-model="formInline.user" placeholder="请输入姓名或身份证"></el-input>
+							</el-form-item>
+							<el-form-item>
+								<el-button type="warning" @click="btn_search">查询</el-button>
+							</el-form-item>
+							<el-form-item label="">
+								<el-select v-model="formInline.category" placeholder="类别" @change="btn_search"
+									clearable>
+									<el-option label="学生" value="学生"></el-option>
+									<el-option label="教工" value="教工"></el-option>
+									<el-option label="员工" value="员工"></el-option>
+								</el-select>
+							</el-form-item>
+						</el-form>
+						<el-table :data="tableData" height="510" style="width: 100%" :cell-style="cell_style"
+							:header-cell-style="header_cell_style">
+							<el-table-column label="序号" align="center" width="100">
+								<template slot-scope="scope">
+									<span>{{(pagination.currentPage - 1) * pagination.pageSize + scope.$index + 1}}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="姓名" align="center" width="100">
+								<template slot-scope="scope">
+									<span>{{ scope.row.user_name }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="手机" align="center" width="180">
+								<template slot-scope="scope">
+									<span>{{ scope.row.phone }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="身份证" align="center">
+								<template slot-scope="scope">
+									<span>{{ scope.row.sfzh }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="类别" align="center" width="100">
+								<template slot-scope="scope">
+									<span>{{ scope.row.classfy }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="年级" align="center" width="100">
+								<template slot-scope="scope">
+									<span>{{ scope.row.bj }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="账户余额(元)" align="center" width="180">
+								<template slot-scope="scope">
+									<span>{{ scope.row.balance }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="备注" align="center">
+								<template slot-scope="scope">
+									<span>{{ scope.row.remark }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="操作" align="center">
+								<template slot-scope="scope">
+									<el-button size="mini" class="btn-table" @click="recharge(scope.$index, scope.row)">
+										充值</el-button>
+								</template>
+							</el-table-column>
+						</el-table>
+						<div class="pagination-table">
+							<el-pagination @current-change="currentPageChange"
+								:current-page.sync="pagination.currentPage" :page-size="pagination.pageSize"
+								layout="prev, pager, next, jumper" :total="pagination.total">
+							</el-pagination>
+						</div>
+					</div>
+				</div>
+			</el-col>
+		</el-row>
+		<!-- 新增用户对话框 -->
+		<el-dialog title="新增用户" custom-class="add-user-dialog" :visible.sync="dialogAddUserVisible"
+			:close-on-click-modal="false" :close-on-press-escape="false" @close="add_user_dialog_close">
+			<el-form :model="addForm" ref="addUserForm" :rules="addFormRules">
+				<el-form-item label="姓  名:" :label-width="formLabelWidth" :required="true" prop="user_name">
+					<el-input v-model="addForm.user_name" autocomplete="off" maxlength="10" ref="username_focus">
+					</el-input>
+				</el-form-item>
+				<el-form-item label="手  机:" :label-width="formLabelWidth" :required="true" prop="phone">
+					<el-input v-model="addForm.phone" autocomplete="off" maxlength="11"></el-input>
+				</el-form-item>
+				<el-form-item label="身份证号:" :label-width="formLabelWidth" :required="true" prop="sfzh">
+					<el-input v-model="addForm.sfzh" autocomplete="off" maxlength="18"></el-input>
+				</el-form-item>
+				<el-form-item label="类  别:" :label-width="formLabelWidth" :required="true" prop="classfy">
+					<el-select v-model="addForm.classfy" placeholder="类别">
+						<el-option label="学生" value="学生"></el-option>
+						<el-option label="教工" value="教工"></el-option>
+						<el-option label="员工" value="员工"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="年  级:" :label-width="formLabelWidth" :required="true" prop="bj">
+					<el-select v-model="addForm.bj" placeholder="年级">
+						<el-option label="大一" value="大一"></el-option>
+						<el-option label="大二" value="大二"></el-option>
+						<el-option label="大三" value="大三"></el-option>
+						<el-option label="大四" value="大四"></el-option>
+						<el-option label="非学生" value="非学生"></el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="备  注:" :label-width="formLabelWidth">
+					<el-input type="textarea" resize="none" :rows="4" placeholder="请输入内容" v-model="addForm.remark"
+						maxlength="100" show-word-limit></el-input>
+				</el-form-item>
+			</el-form>
+			<div slot="footer" class="dialog-footer">
+				<el-button @click="dialogAddUserVisible = false">取 消</el-button>
+				<el-button type="primary" @click="handler_add_user">新 增</el-button>
+			</div>
+		</el-dialog>
+		<!-- 充值对话框 -->
+		<el-dialog title="充值" custom-class="chongzhi-dialog" :visible.sync="dialogChongzhiVisible"
+			:close-on-click-modal="false" :close-on-press-escape="false" @close="dialog_close">
+			<el-form :model="form" ref="chongzhiForm" :rules="chongzhiRules">
+				<el-form-item label="充值账号:" :label-width="formLabelWidth">
+					<div>{{form.sfzh}}</div>
+				</el-form-item>
+				<el-form-item label="姓  名:" :label-width="formLabelWidth">
+					<div>{{form.user_name}}</div>
+				</el-form-item>
+				<el-form-item label="充值金额:" :label-width="formLabelWidth" :required="true" prop="amount">
+					<el-input v-model="form.amount" autocomplete="off" maxlength="3" ref="amount_focus"></el-input>
+				</el-form-item>
+				<el-form-item label="备  注:" :label-width="formLabelWidth">
+					<el-input type="textarea" resize="none" :rows="4" placeholder="请输入内容" v-model="form.desc"
+						maxlength="100" show-word-limit></el-input>
+				</el-form-item>
+			</el-form>
+			<div slot="footer" class="dialog-footer">
+				<el-button @click="dialogChongzhiVisible = false">取 消</el-button>
+				<el-button type="primary" @click="handler_chongzhi">确 定</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	import {
+		getUserList,
+		addUser,
+		chongzhi,
+		downloadExcel
+	} from '@/api/userMgr';
+	export default {
+		data() {
+			var checkUserName = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请输入姓名'));
+				}
+				setTimeout(() => {
+					var reg = /^[\u4E00-\u9FA5]{2,10}$/
+					if (!reg.test(value)) {
+						callback(new Error('必须为2-10个汉字!'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			var checkPhone = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请输入手机号'));
+				}
+				setTimeout(() => {
+					var reg = /^1[3456789]\d{9}$/
+					if (!reg.test(value)) {
+						callback(new Error('手机号格式不对'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			var checkIdCard = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请输入身份证'));
+				}
+				setTimeout(() => {
+					var reg =
+						/^[1-9]\d{5}(18|19|([2]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
+					if (!reg.test(value)) {
+						callback(new Error('身份证不符合要求'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			var checkClassfy = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请选择类别'));
+				}
+				if (this.addForm.classfy == '学生' && this.addForm.bj == '非学生') {
+					return callback(new Error('类型与年级不一致'));
+				}
+				if ((this.addForm.classfy == '教工' || this.addForm.classfy == '员工') && (this.addForm.bj == '大一' || this
+						.addForm.bj == '大二' || this.addForm.bj == '大三' || this.addForm.bj == '大四')) {
+					return callback(new Error('类型与年级不一致'));
+				}
+				callback();
+			}
+			var checkBj = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('请选择年级'));
+				}
+				if (this.addForm.classfy == '学生' && this.addForm.bj == '非学生') {
+					return callback(new Error('类型与年级不一致'));
+				}
+				if ((this.addForm.classfy == '教工' || this.addForm.classfy == '员工') && (this.addForm.bj == '大一' || this
+						.addForm.bj == '大二' || this.addForm.bj == '大三' || this.addForm.bj == '大四')) {
+					return callback(new Error('类型与年级不一致'));
+				}
+				callback();
+			}
+			var checkMoney = (rule, value, callback) => {
+				if (!value) {
+					return callback(new Error('金额不能为空'));
+				}
+				setTimeout(() => {
+					var reg = /^([1-9]{1}\d*)$/
+					if (!reg.test(value)) {
+						callback(new Error('请输入正整数'));
+					} else if (value < 1 || value > 200) {
+						callback(new Error('范围在1-200'));
+					} else {
+						callback();
+					}
+				}, 100);
+			}
+			return {
+				// 弹出对话框数据
+				dialogChongzhiVisible: false,
+				form: {
+					id: '',
+					sfzh: '',
+					user_name: '',
+					amount: '',
+					remark: ''
+				},
+				chongzhiRules: {
+					amount: [{
+						validator: checkMoney
+					}]
+				},
+				// 添加用户对话框数据
+				dialogAddUserVisible: false,
+				addForm: {
+					user_name: '',
+					phone: '',
+					sfzh: '',
+					classfy: '',
+					bj: '',
+					remark: ''
+				},
+				addFormRules: {
+					user_name: [{
+						validator: checkUserName
+					}],
+					phone: [{
+						validator: checkPhone
+					}],
+					sfzh: [{
+						validator: checkIdCard
+					}],
+					classfy: [{
+						validator: checkClassfy
+					}],
+					bj: [{
+						validator: checkBj
+					}]
+				},
+				// 查询表单数据
+				formInline: {
+					user: '',
+					category: ''
+				},
+				tableData: [],
+				// 分页参数
+				pagination: {
+					currentPage: 1,
+					pageSize: 8,
+					total: 0
+				},
+				formLabelWidth: '120px',
+				// 表格单元格样式
+				cell_style: {
+					color: '#1A202B',
+					'font-size': '16px',
+					'font-family': 'Microsoft YaHei-3970(82674968)'
+				},
+				// 表格头部样式
+				header_cell_style: {
+					background: '#E6ECFE',
+					color: '#1A202B',
+					'font-size': '18px',
+					'font-family': 'Microsoft YaHei-3970(82674968)'
+				}
+			}
+		},
+		mounted() {
+			document.getElementsByClassName("el-pagination__jump")[0].childNodes[0].nodeValue = "跳至";
+			// 获取用户列表数据
+			this.get_user_list('list')
+		},
+		methods: {
+			/**
+			 * 下载Excel表格
+			 */
+			handler_download_excel() {
+				// 开始发送请求,获取配置数据
+				downloadExcel().then((res) => {
+					console.log(res);
+					if (typeof res.code == 'undefined' || res.code == '') {
+						this.$message.error('返回数据格式问题,code未获取到!')
+						return
+					}
+
+					if (res.code == 200) {
+						this.$message.success('下载成功!')
+						let xls = 'http://demo.xwsyjjy.com' + res.downurl
+						window.open(xls)
+					} else {
+						this.$message.error('未知异常!')
+					}
+				}).catch((err) => {
+					// console.log(err);
+					this.$message.error(err.message)
+				})
+			},
+			/**
+			 * 充值
+			 */
+			handler_chongzhi() {
+				this.$refs["chongzhiForm"].validate(validate => {
+					if (validate) {
+						let params = {
+							id: this.form.id,
+							balance: this.form.amount
+						}
+						// 开始发送请求,获取配置数据
+						chongzhi(params).then((res) => {
+							// console.log(res);
+							if (typeof res.code == 'undefined' || res.code == '') {
+								this.$message.error('返回数据格式问题,code未获取到!')
+								return
+							}
+
+							if (res.code == 200) {
+								this.dialogChongzhiVisible = false
+								this.$message.success('充值成功!')
+								this.get_user_list('list')
+							} else {
+								this.$message.error('未知异常!')
+							}
+						}).catch((err) => {
+							// console.log(err);
+							this.$message.error(err.message)
+						})
+					} else {
+						this.$message.error('验证不通过')
+						return false
+					}
+				})
+			},
+			/**
+			 * 打开新增用户对话框
+			 */
+			add_user() {
+				this.dialogAddUserVisible = true
+
+				setTimeout(() => {
+					this.$nextTick(() => {
+						this.$refs.username_focus.focus()
+					})
+				}, 100)
+			},
+			/**
+			 * 新增用户操作
+			 */
+			handler_add_user() {
+				this.$refs["addUserForm"].validate(validate => {
+					console.log(typeof validate);
+					console.log(validate);
+					if (validate) {
+						let params = {
+							user_name: this.addForm.user_name,
+							phone: this.addForm.phone,
+							sfzh: this.addForm.sfzh,
+							classfy: this.addForm.classfy,
+							bj: this.addForm.bj,
+							remark: this.addForm.remark
+						}
+						// 开始发送请求,获取配置数据
+						addUser(params).then((res) => {
+							console.log(res);
+							if (typeof res.code == 'undefined' || res.code == '') {
+								this.$message.error('返回数据格式问题,code未获取到!')
+								return
+							}
+
+							if (res.code == 200) {
+								this.dialogAddUserVisible = false
+								this.$message.success('新增用户成功!')
+								this.get_user_list('list')
+							} else {
+								this.$message.error('未知异常!')
+							}
+						}).catch((err) => {
+							// console.log(err);
+							this.$message.error(err.message)
+						})
+					} else {
+						this.$message.error('验证不通过')
+						return false
+					}
+				})
+			},
+			/**
+			 * 获取用户列表数据
+			 */
+			get_user_list(param) {
+				let params = {
+					page: this.pagination.currentPage,
+					rows: this.pagination.pageSize
+				}
+				if (param == 'search') {
+					params.page = 1
+					if (this.formInline.user !== '') {
+						params.name_card = this.formInline.user
+					}
+					if (this.formInline.category !== '') {
+						params.classfy = this.formInline.category
+					}
+				}
+				// 开始发送请求,获取配置数据
+				getUserList(params).then((res) => {
+					// console.log(res.rows);
+					if (typeof res.rows !== 'undefined' && res.rows !== '') {
+						this.pagination.total = res.total
+						this.tableData = []
+						for (var i = 0; i < res.rows.length; i++) {
+							this.tableData.push(res.rows[i])
+						}
+					} else {
+						this.$message.warning('没有符合条件的数据!')
+					}
+				}).catch((err) => {
+					// console.log(err);
+					this.$message.error(err.message)
+				})
+			},
+			/**
+			 * 查询
+			 */
+			btn_search() {
+				this.get_user_list('search')
+			},
+			/**
+			 * 充值对话框初始化
+			 * @param {Object} index
+			 * @param {Object} row
+			 */
+			recharge(index, row) {
+				// console.log(index, row);
+				this.dialogChongzhiVisible = true
+				this.form.id = row.id
+				this.form.sfzh = row.sfzh
+				this.form.user_name = row.user_name
+				// 使金额输入框input_amount获得焦点
+				setTimeout(() => {
+					this.$nextTick(() => {
+						this.$refs.amount_focus.focus()
+					})
+				}, 100)
+			},
+			/**
+			 * currentPage 改变时会触发
+			 * @param {Object} val
+			 */
+			currentPageChange(val) {
+				this.pagination.currentPage = val
+				this.get_user_list('pages')
+			},
+			/**
+			 * 对话框关闭时清理数据
+			 */
+			add_user_dialog_close() {
+				this.addForm = {}
+			},
+			/**
+			 * 对话框关闭时清理数据
+			 */
+			dialog_close() {
+				this.form = {}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app-container {
+		background-color: #EFF2F7;
+		padding: 10px;
+
+		.el-row {
+
+			.el-col {
+				padding: 10px;
+
+				.cell {
+					padding: 30px;
+					border-radius: 10px;
+					background-color: #FFFFFF;
+					// box-shadow: 5px 5px 15px #979797;
+					box-shadow: 0px 3px 21px 0px rgba(60, 108, 254, 0.16);
+
+					.cell-title {
+						display: flex;
+						justify-content: space-between;
+						align-items: center;
+						margin-bottom: 30px;
+						padding-bottom: 30px;
+						border-bottom: 1px solid #CCCCCC;
+
+						.title {
+							font-size: 22px;
+							font-family: Microsoft YaHei-3970(82674968);
+							font-weight: bold;
+							color: #1A202B;
+						}
+
+						.title-right {
+							display: flex;
+							justify-content: space-between;
+							align-items: center;
+
+							.el-button {
+								width: 110px;
+								height: 46px;
+								background: #2B4CFE;
+								font-size: 18px;
+								color: #FFFFFF;
+								font-family: Microsoft YaHei-3970(82674968);
+								border-radius: 5px;
+							}
+
+							.el-button--warning {
+								background: #F88A64;
+							}
+						}
+					}
+
+					.cell-body {
+
+						.el-button--warning {
+							background: #F88A64;
+						}
+
+						.btn-table {
+							border-radius: 15px !important;
+							border-color: #5488FE;
+							color: #5488FE;
+						}
+
+						.pagination-table {
+							display: flex;
+							justify-content: flex-end;
+							align-items: center;
+							height: 30px;
+							margin-top: 20px;
+							padding-right: 100px;
+
+							::v-deep .el-pagination {
+								display: flex;
+								justify-content: flex-end;
+								align-items: center;
+							}
+
+							::v-deep .el-pagination ul {
+								display: flex;
+
+							}
+
+							::v-deep .el-pagination button,
+							::v-deep .el-pagination li {
+								display: flex;
+								justify-content: center;
+								align-items: center;
+								width: 50px;
+								height: 36px;
+								border: 1px solid #626262;
+								border-radius: 3px;
+								font-size: 14px;
+								margin: 0 5px;
+							}
+
+							::v-deep .el-pagination span {
+								margin-left: 10px;
+							}
+
+							::v-deep .el-pagination .el-pagination__jump {
+								font-size: 16px;
+							}
+
+							::v-deep .el-pagination .el-pagination__editor {
+								width: 50px;
+								height: 36px;
+								margin: 0 5px;
+							}
+
+							::v-deep .el-pagination .el-input__inner {
+								width: 50px;
+								height: 36px;
+								border: 1px solid #626262;
+								margin: -4px 0 0 0;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		::v-deep .el-dialog {
+			margin: 0 !important;
+			width: 600px;
+			height: 500px;
+			background: #FFFFFF;
+			box-shadow: 0px 0px 13px 0px rgba(0, 0, 0, 0.29);
+			border-radius: 10px;
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			transform: translate(-50%, -50%);
+
+			.el-dialog__header {
+				display: flex;
+				align-items: center;
+				width: 100%;
+				height: 58px;
+				padding: 30px;
+				background: #E6EBFE;
+				border-radius: 10px 10px 0px 0px;
+				font-weight: bold;
+			}
+
+			.el-dialog__body {
+				padding-bottom: 0;
+
+				.el-form-item__label,
+				.el-form-item__content {
+					font-size: 16px;
+					font-family: Microsoft YaHei-3970(82674968);
+					color: #53575A;
+				}
+
+				.el-input__inner {
+					width: 180px;
+				}
+			}
+
+			.el-dialog__footer {
+				padding-bottom: 0 !important;
+				text-align: center;
+
+				.el-button.el-button--default {
+					width: 75px;
+					height: 40px;
+					border: 1px solid #2B4CFE;
+					border-radius: 6px;
+					font-size: 16px;
+					font-family: Microsoft YaHei-3970(82674968);
+					color: #2B4CFE;
+				}
+
+				.el-button.el-button--primary {
+					width: 75px;
+					height: 40px;
+					background: #2B4CFE;
+					border-radius: 6px;
+					font-size: 16px;
+					font-family: Microsoft YaHei-3970(82674968);
+					color: #FFFFFF;
+					margin-left: 60px;
+				}
+			}
+		}
+	}
+</style>
+
+<style>
+	.add-user-dialog {
+		height: 600px !important;
+	}
+
+	.chongzhi-dialog {
+		height: 500px !important;
+	}
+</style>

+ 109 - 101
vue.config.js

@@ -3,7 +3,7 @@ const path = require('path')
 const defaultSettings = require('./src/settings.js')
 
 function resolve(dir) {
-  return path.join(__dirname, dir)
+	return path.join(__dirname, dir)
 }
 
 const name = defaultSettings.title || '共享空调运营管理平台' // page title
@@ -17,107 +17,115 @@ const port = process.env.port || process.env.npm_config_port || 9528 // dev port
 
 // All configuration item explanations can be find in https://cli.vuejs.org/config/
 module.exports = {
-  /**
-   * You will need to set publicPath if you plan to deploy your site under a sub path,
-   * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
-   * then publicPath should be set to "/bar/".
-   * In most cases please use '/' !!!
-   * Detail: https://cli.vuejs.org/config/#publicpath
-   */
-  publicPath: '/',
-  outputDir: 'dist',
-  assetsDir: 'static',
-  lintOnSave: process.env.NODE_ENV === 'development',
-  productionSourceMap: false,
-  devServer: {
-    port: port,
-    open: true,
-    overlay: {
-      warnings: false,
-      errors: true
-    },
-    before: require('./mock/mock-server.js')
-  },
-  configureWebpack: {
-    // provide the app's title in webpack's name field, so that
-    // it can be accessed in index.html to inject the correct title.
-    name: name,
-    resolve: {
-      alias: {
-        '@': resolve('src')
-      }
-    }
-  },
-  chainWebpack(config) {
-    // it can improve the speed of the first screen, it is recommended to turn on preload
-    config.plugin('preload').tap(() => [
-      {
-        rel: 'preload',
-        // to ignore runtime.js
-        // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
-        fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
-        include: 'initial'
-      }
-    ])
+	/**
+	 * You will need to set publicPath if you plan to deploy your site under a sub path,
+	 * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
+	 * then publicPath should be set to "/bar/".
+	 * In most cases please use '/' !!!
+	 * Detail: https://cli.vuejs.org/config/#publicpath
+	 */
+	publicPath: '/',
+	outputDir: 'dist',
+	assetsDir: 'static',
+	lintOnSave: process.env.NODE_ENV === 'development',
+	productionSourceMap: false,
+	devServer: {
+		port: port,
+		open: true,
+		overlay: {
+			warnings: false,
+			errors: true
+		},
+		proxy: {
+			[process.env.VUE_APP_BASE_API]: {
+				target: 'http://demo.xwsyjjy.com',
+				// target: 'http://127.0.0.1:9999',
+				changeOrigin: true,
+				pathRewrite: {
+					['^' + process.env.VUE_APP_BASE_API]: ''
+				}
+			}
+		}
+		// before: require('./mock/mock-server.js')
+	},
+	configureWebpack: {
+		// provide the app's title in webpack's name field, so that
+		// it can be accessed in index.html to inject the correct title.
+		name: name,
+		resolve: {
+			alias: {
+				'@': resolve('src')
+			}
+		}
+	},
+	chainWebpack(config) {
+		// it can improve the speed of the first screen, it is recommended to turn on preload
+		config.plugin('preload').tap(() => [{
+			rel: 'preload',
+			// to ignore runtime.js
+			// https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
+			fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
+			include: 'initial'
+		}])
 
-    // when there are many pages, it will cause too many meaningless requests
-    config.plugins.delete('prefetch')
+		// when there are many pages, it will cause too many meaningless requests
+		config.plugins.delete('prefetch')
 
-    // set svg-sprite-loader
-    config.module
-      .rule('svg')
-      .exclude.add(resolve('src/icons'))
-      .end()
-    config.module
-      .rule('icons')
-      .test(/\.svg$/)
-      .include.add(resolve('src/icons'))
-      .end()
-      .use('svg-sprite-loader')
-      .loader('svg-sprite-loader')
-      .options({
-        symbolId: 'icon-[name]'
-      })
-      .end()
+		// set svg-sprite-loader
+		config.module
+			.rule('svg')
+			.exclude.add(resolve('src/icons'))
+			.end()
+		config.module
+			.rule('icons')
+			.test(/\.svg$/)
+			.include.add(resolve('src/icons'))
+			.end()
+			.use('svg-sprite-loader')
+			.loader('svg-sprite-loader')
+			.options({
+				symbolId: 'icon-[name]'
+			})
+			.end()
 
-    config
-      .when(process.env.NODE_ENV !== 'development',
-        config => {
-          config
-            .plugin('ScriptExtHtmlWebpackPlugin')
-            .after('html')
-            .use('script-ext-html-webpack-plugin', [{
-            // `runtime` must same as runtimeChunk name. default is `runtime`
-              inline: /runtime\..*\.js$/
-            }])
-            .end()
-          config
-            .optimization.splitChunks({
-              chunks: 'all',
-              cacheGroups: {
-                libs: {
-                  name: 'chunk-libs',
-                  test: /[\\/]node_modules[\\/]/,
-                  priority: 10,
-                  chunks: 'initial' // only package third parties that are initially dependent
-                },
-                elementUI: {
-                  name: 'chunk-elementUI', // split elementUI into a single package
-                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
-                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
-                },
-                commons: {
-                  name: 'chunk-commons',
-                  test: resolve('src/components'), // can customize your rules
-                  minChunks: 3, //  minimum common number
-                  priority: 5,
-                  reuseExistingChunk: true
-                }
-              }
-            })
-          // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
-          config.optimization.runtimeChunk('single')
-        }
-      )
-  }
+		config
+			.when(process.env.NODE_ENV !== 'development',
+				config => {
+					config
+						.plugin('ScriptExtHtmlWebpackPlugin')
+						.after('html')
+						.use('script-ext-html-webpack-plugin', [{
+							// `runtime` must same as runtimeChunk name. default is `runtime`
+							inline: /runtime\..*\.js$/
+						}])
+						.end()
+					config
+						.optimization.splitChunks({
+							chunks: 'all',
+							cacheGroups: {
+								libs: {
+									name: 'chunk-libs',
+									test: /[\\/]node_modules[\\/]/,
+									priority: 10,
+									chunks: 'initial' // only package third parties that are initially dependent
+								},
+								elementUI: {
+									name: 'chunk-elementUI', // split elementUI into a single package
+									priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
+									test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
+								},
+								commons: {
+									name: 'chunk-commons',
+									test: resolve('src/components'), // can customize your rules
+									minChunks: 3, //  minimum common number
+									priority: 5,
+									reuseExistingChunk: true
+								}
+							}
+						})
+					// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
+					config.optimization.runtimeChunk('single')
+				}
+			)
+	}
 }