chenrui 4 år sedan
förälder
incheckning
435706d28a

+ 59 - 0
src/api/power-role.js

@@ -0,0 +1,59 @@
+import { axios } from '@/utils/request'
+
+// 获取列表数据
+export const getPowerRoleList = params => {
+  const url = `/role/queryLike/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 改变权限状态接口 flag 0:禁用 1:启用
+export const updateEnableStatus = params => {
+  return axios({
+    url: `/role/enable/${params.id}/${params.flag}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 删除用户接口
+export const delectRolePower = params => {
+  return axios({
+    url: `/role/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 新增/编辑保存接口
+export const saveRolePower = params => {
+  return axios({
+    url: '/role/save',
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 获取菜单树数据
+export const getMenuList = params => {
+  const url = `/role/findAllMenu/${params.id}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}
+
+// 保存权限分配
+export const addMenuPower = params => {
+  const url = `/role/saveRoleMenu`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 58 - 0
src/api/power-user.js

@@ -0,0 +1,58 @@
+import { axios } from '@/utils/request'
+
+// 重置密码
+export const resetPSD = params => {
+  return axios({
+    url: '/user/resetPwd',
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 获取列表数据
+export const getPowerUserList = params => {
+  const url = `/user/queryLike/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 改变权限状态接口
+export const updateEnableStatus = params => {
+  return axios({
+    url: `/user/enable/${params.id}/${params.flag}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 删除用户接口
+export const delectUserPower = params => {
+  return axios({
+    url: `/user/delete/${params.id}`,
+    data: {},
+    method: 'get'
+  })
+}
+
+// 新增/编辑保存接口
+export const saveUserPower = params => {
+  return axios({
+    url: '/user/save',
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 获取角色列表接口
+export const getRoleList = params => {
+  return axios({
+    url: '/role/findAll',
+    data: params,
+    method: 'POST'
+  })
+}

+ 3 - 0
src/components/Select/index.js

@@ -81,6 +81,9 @@ export default {
       change: obj => {
         this.$emit('change', obj, _.find(this.dataList, ['code', obj]))
         this.$emit('input', obj)
+      },
+      dropdownVisibleChange: obj => {
+        this.$emit('dropdownVisibleChange', obj, _.find(this.dataList, ['code', obj]))
       }
     }
     if (this.showType === 'tabs') {

+ 2 - 2
src/components/Table/index.js

@@ -156,7 +156,7 @@ export default {
       if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
         result.then(r => {
           const list = r.list || r.data || r
-          console.log(r, 'rrrrrrrrrr')
+          // console.log(r, 'rrrrrrrrrr')
           this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {
             current: r.pageNo, // 返回结果中的当前分页数
             total: r.count, // 返回结果中的总记录数
@@ -180,7 +180,7 @@ export default {
           } catch (e) {
             this.localPagination = false
           }
-          console.log('loadData -> this.localPagination', this.localPagination)
+          // console.log('loadData -> this.localPagination', this.localPagination)
           this.localDataSource = list // 返回结果中的数组数据
           this.localLoading = false
         })

+ 20 - 0
src/config/router.config.js

@@ -160,6 +160,26 @@ export const asyncRouterMap = [
       }
       ]
     },
+    {
+      path: '/auth',
+      redirect: '/auth/userList',
+      component: PageView,
+      meta: { title: '后台权限管理', icon: 'lock', permission: 'M_auth_0' },
+      children: [
+        {
+          path: '/auth/userList',
+          name: 'powerUserList',
+          component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
+          meta: { title: '用户管理', icon: 'user', permission: 'M_auth_userList' }
+        },
+        {
+          path: '/auth/roleList',
+          name: 'powerRoleList',
+          component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
+          meta: { title: '角色管理', icon: 'solution', permission: 'M_auth_roleList' }
+        }
+      ]
+    },
     {
       path: '/setting',
       redirect: '/setting/userList',

+ 37 - 24
src/views/CarWashManagement/AddCarWashModal.vue

@@ -47,7 +47,7 @@
           </a-form-model-item>
         </a-col>
         <a-col :span="12">
-          <a-form-model-item label="设备" prop="equipment" class="default-form-item">
+          <a-form-model-item label="设备ID" prop="equipment" class="default-form-item">
             <a-row :gutter="20">
               <a-col :span="19">
                 <a-tag v-if="equipmentName" color="blue">{{equipmentName}}</a-tag>
@@ -84,7 +84,7 @@
         </a-col>
         <a-col :span="12">
           <a-form-model-item label="服务类型" prop="serviceType">
-            <v-select ref="serviceType" mode="multiple" placeholder="请选择服务类型" v-model="form.serviceType" @change="serviceTypeChange" code="CHECK_ENABLE_STATE"></v-select>
+            <v-select ref="serviceType" mode="multiple" placeholder="请选择服务类型" v-model="form.serviceType" :disabled="isResetPeriodPriceStatus" @dropdownVisibleChange="isResetPeriodPrice" code="CHECK_ENABLE_STATE"></v-select>
           </a-form-model-item>
         </a-col>
         <a-col :span="12">
@@ -92,13 +92,13 @@
             <a-row :gutter="20">
               <a-col :span="11">
                 <a-form-model-item prop="startTime">
-                  <a-time-picker v-model="form.startTime" @change="startTimeChange" format="HH:mm" placeholder="请选择开始时间" class="time-picker" />
+                  <a-time-picker v-model="form.startTime" @openChange="isResetPeriodPrice" :disabled="isResetPeriodPriceStatus" format="HH:mm" placeholder="请选择开始时间" class="time-picker" />
                 </a-form-model-item>
               </a-col>
               <a-col :span="2">至</a-col>
               <a-col :span="11">
                 <a-form-model-item prop="endTime">
-                  <a-time-picker v-model="form.endTime" @change="endTimeChange" format="HH:mm" placeholder="请选择结束时间" class="time-picker" />
+                  <a-time-picker v-model="form.endTime" @openChange="isResetPeriodPrice" :disabled="isResetPeriodPriceStatus" format="HH:mm" placeholder="请选择结束时间" class="time-picker" />
                 </a-form-model-item>
               </a-col>
             </a-row>
@@ -112,13 +112,13 @@
                 <a-row :gutter="20">
                   <a-col :span="11">
                     <a-form-model-item :prop="'periodPrice.'+ ind + '.startTime'" :rules="{required: true, message: '请选择开始时间', trigger: 'change'}">
-                      <a-time-picker v-model="item.startTime" disabled @change="startTimeChange" format="HH:mm" placeholder="请选择" class="time-picker" />
+                      <a-time-picker v-model="item.startTime" disabled format="HH:mm" placeholder="请选择" class="time-picker" />
                     </a-form-model-item>
                   </a-col>
                   <a-col :span="2">至</a-col>
                   <a-col :span="11">
                     <a-form-model-item :prop="'periodPrice.'+ ind + '.endTime'" :rules="{required: true, message: '请选择结束时间', trigger: 'change'}">
-                      <a-time-picker v-model="item.endTime" @change="endTimeChange" format="HH:mm" placeholder="请选择" class="time-picker" />
+                      <a-time-picker v-model="item.endTime" format="HH:mm" placeholder="请选择" class="time-picker" />
                     </a-form-model-item>
                   </a-col>
                 </a-row>
@@ -144,13 +144,13 @@
         </a-col>
         <a-col :span="24">
           <a-form-model-item label="温馨提示" prop="reminder" :label-col="{ span: 3 }" :wrapper-col="{ span: 21 }">
-            <a-textarea v-model="form.reminder" :maxLength="128" :auto-size="{ minRows: 3, maxRows: 5 }" placeholder="请输入温馨提示,128个字以内" />
+            <a-textarea ref="reminder" v-model="form.reminder" :maxLength="128" :auto-size="{ minRows: 3, maxRows: 5 }" placeholder="请输入温馨提示,128个字以内" />
           </a-form-model-item>
         </a-col>
         <a-col :span="24">
           <a-form-model-item :label-col="{ span: 3 }" :wrapper-col="{ span: 21 }" class="btn-cont">
             <a-button type="primary" @click="onSubmit('ruleForm')">保存</a-button>
-            <a-button style="margin-left: 10px;" @click="resetForm">取消</a-button>
+            <a-button class="resetForm" @click="resetForm">取消</a-button>
           </a-form-model-item>
         </a-col>
       </a-row>
@@ -246,6 +246,7 @@
         },
         openEquipmentModal: false  ,//  选择设备  弹框展示状态
         equipmentName: '',  //  选中的设备  名称
+        isResetPeriodPriceStatus: false,  //  是否重置时段价格
       }
     },
     methods: {
@@ -261,9 +262,15 @@
         console.log(this.form, '表单数据')
         this.$refs[formName].validate(valid => {
           if (valid) {
-            
+            let formData = JSON.parse(JSON.stringify(this.form))
+            //  校验营业时间结束时间是否与时段价格一致
+            let endTime = formData.periodPrice[formData.periodPrice.length - 1].endTime
+            if(formData.endTime != endTime){
+              this.$message.error('时段价格与营业时间不一致,请修改后再保存!')
+              return
+            }
+            console.log(formData,'-----提交的表单数据')
           } else {
-            console.log('error submit!!')
             return false
           }
         })
@@ -273,9 +280,23 @@
         this.$refs.ruleForm.resetFields()
         this.isShow = false
       },
-      serviceTypeChange(e){
-        
-        console.log(e)
+      // 是否重置时段价格
+      isResetPeriodPrice(open){
+        const _this = this
+        if(_this.form.periodPrice.length != 0 && open){
+          _this.isResetPeriodPriceStatus = true
+          _this.$confirm({
+            title: '提示',
+            content: '更改后已设置的时段价格将会全部清空,确定更改吗?',
+            onOk () {
+              _this.form.periodPrice = []
+            },
+            onCancel() {
+              _this.$confirm.$destroy
+              _this.isResetPeriodPriceStatus = false
+            }
+          })
+        }
       },
       //  选择设备
       closeChooseEquipment(val, name){
@@ -285,16 +306,6 @@
         }
         this.openEquipmentModal = false
       },
-      //  营业时间 开始时间  change
-      startTimeChange(time, timeString) {
-        console.log(time, timeString,'---开始时间')
-        // this.form.startTime = timeString
-      },
-      //  营业时间 结束时间  change
-      endTimeChange(time, timeString) {
-        console.log(time, timeString,'---结束时间')
-        // this.form.endTime = timeString
-      },
       //  设置时段价格
       setTimeInterval(){
         if(this.form.serviceType.length == 0){
@@ -327,7 +338,6 @@
         this.form.serviceType.map((item, index) => {
           arr.price.push({ name: this.$refs.serviceType.getNameByCode(item), value: '' })
         })
-        console.log(arr,'----arr')
         this.form.periodPrice.push(arr)
       }
     },
@@ -376,6 +386,9 @@
     }
     .btn-cont{
       text-align: center;
+      .resetForm{
+        margin-left: 10px;
+      }
     }
     .setTimeInterval{
       width: 40%;

+ 95 - 4
src/views/CarWashManagement/CarWashManagement.vue

@@ -39,9 +39,26 @@
     <!-- 新建 -->
     <div class="table-operator">
       <a-button type="primary" icon="plus" @click="modalHandle('add')">新建</a-button>
+      <a-button type="primary" icon="plus">详情</a-button>
     </div>
     <!-- 表格列表 -->
     <s-table ref="table" size="default" rowKey="id" :columns="columns" :data="loadData" bordered >
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-tooltip placement="left" trigger="click" overlayClassName="btn-cont">
+          <template slot="title">
+            <div class="btn-set-cont">
+              <p class="set-sub-btn normal"><a-icon type="check-circle" class="icon" />正常营业</p>
+              <p class="set-sub-btn suspension"><a-icon type="pause-circle" class="icon" />暂停营业</p>
+              <p class="set-sub-btn soon"><a-icon type="play-circle" class="icon" />即将开业</p>
+            </div>
+          </template>
+          <a-icon type="setting" title="设置" :style="{ fontSize: '20px', color: '#19be6b', padding: '0 10px' }" />
+        </a-tooltip>
+        <a-icon type="edit" title="编辑" :style="{ fontSize: '20px', color: '#1890FF', padding: '0 10px' }" />
+        <a-icon type="eye" title="查看详情" @click="openDetailsModal=true" :style="{ fontSize: '20px', color: '#e29e14', padding: '0 10px' }" />
+        <a-icon type="delete" title="删除" @click="del(record)" :style="{ fontSize: '20px', color: 'red', padding: '0 10px' }" />
+      </template>
     </s-table>
     
     <!-- 新增/编辑 洗车机 -->
@@ -50,15 +67,21 @@
       :mtitle="mtitle"
       @close="openModal=false"
     />
+    <!-- 查看详情 洗车机 -->
+    <details-car-wash-modal
+      :openModal="openDetailsModal"
+      @close="openDetailsModal=false"
+    />
   </a-card>
 </template>
 
 <script>
   import { STable, VSelect } from '@/components'
   import AddCarWashModal from './AddCarWashModal.vue'
+  import DetailsCarWashModal from './DetailsCarWashModal.vue'
   export default{
     name: 'CarWashManagement',
-    components: { STable, VSelect, AddCarWashModal },
+    components: { STable, VSelect, AddCarWashModal, DetailsCarWashModal },
     data(){
       return{
         queryParam: {
@@ -70,6 +93,16 @@
         },
         columns: [
           { title: '创建时间', dataIndex: 'createDate', width: '100', align: 'center' },
+          { title: '设备ID', dataIndex: 'equipment', width: '100', align: 'center' },
+          { title: '网点名称', dataIndex: 'name', width: '100', align: 'center' },
+          { title: '省', dataIndex: 'addrProvince', width: '100', align: 'center' },
+          { title: '市', dataIndex: 'addrCity', width: '100', align: 'center' },
+          { title: '地址', dataIndex: 'addrDetail', width: '100', align: 'center' },
+          { title: '营业时间', dataIndex: 'businessHours', width: '100', align: 'center' },
+          { title: '设备状态', dataIndex: 'equipmentStatus', width: '100', align: 'center' },
+          { title: '营业状态', dataIndex: 'businessStatus', width: '100', align: 'center' },
+          { title: '小程序码', dataIndex: 'wechatCode', width: '100', align: 'center' },
+          { title: '操作', scopedSlots: {customRender: 'action'}, width: '200', align: 'center' }
         ],
         // 加载数据方法 必须为 Promise 对象
         loadData: parameter => {
@@ -82,9 +115,19 @@
           //   }
           //   return res.data
           // })
+          let data = [
+            { createDate: '2020-07-31 15:09', equipment: 'ID585787887', name: '网点A', addrProvince: '陕西省', addrCity: '西安市', addrDetail: '华帝金座', businessHours: '8:30 - 22:00', equipmentStatus: '在线', businessStatus: '正常营业', wechatCode: '' },
+            { createDate: '2020-07-31 15:09', equipment: 'ID585787887', name: '网点A', addrProvince: '陕西省', addrCity: '西安市', addrDetail: '华帝金座', businessHours: '8:30 - 22:00', equipmentStatus: '在线', businessStatus: '正常营业', wechatCode: '' },
+            { createDate: '2020-07-31 15:09', equipment: 'ID585787887', name: '网点A', addrProvince: '陕西省', addrCity: '西安市', addrDetail: '华帝金座', businessHours: '8:30 - 22:00', equipmentStatus: '在线', businessStatus: '正常营业', wechatCode: '' },
+          ]
+          return new Promise((resolve, reject) => {
+            console.log((resolve, reject))
+            resolve(data)
+          }).catch(() => console.log('Oops errors!'))
         },
         openModal: false,  //  新增/编辑 洗车机  弹框展示状态
         mtitle: '',  //  新增/编辑 洗车机  弹框标题
+        openDetailsModal: false,  //  查看详情 洗车机  弹框展示状态
       }
     },
     methods: {
@@ -93,6 +136,17 @@
         this.mtitle = type == 'add' ? '新增' : '编辑'
         this.openModal = true
       },
+      // 删除
+      del(item){
+        console.log(item)
+        this.$confirm({
+          title: '提示',
+          content: '确定要删除吗?',
+          onOk () {
+            
+          }
+        })
+      },
       //  重置
       reset(){
         this.queryParam = {
@@ -111,12 +165,49 @@
 <style lang="less">
   .CarWashManagement{
     .table-page-search-wrapper{
-      .search-item{
-        // margin-bottom: 0;
-      }
       .search-btn{
         margin-right: 10px;
       }
     }
   }
+  .btn-cont{
+    .ant-tooltip-inner{
+      background-color: #fff;
+    }
+    .ant-tooltip-arrow:before{
+      background-color: #fff;
+    }
+    .btn-set-cont{
+      .set-sub-btn{
+        padding: 5px 15px 6px;
+        font-size: 12px;
+        border: 1px dashed #dcdee2;
+        border-radius: 4px;
+        margin: 0;
+        cursor: pointer;
+      }
+      .normal{
+        color: rgb(0, 204, 0);
+        border-color: rgb(0, 204, 0);
+        .icon{
+          margin-right: 5px;
+        }
+      }
+      .suspension{
+        color: rgb(255, 85, 0);
+        border-color: rgb(255, 85, 0);
+        margin: 7px 0;
+        .icon{
+          margin-right: 5px;
+        }
+      }
+      .soon{
+        color: #2d8cf0;
+        border-color: #2d8cf0;
+        .icon{
+          margin-right: 5px;
+        }
+      }
+    }
+  }
 </style>

+ 16 - 2
src/views/CarWashManagement/ChooseEquipment.vue

@@ -9,7 +9,8 @@
         </div>
       </a-radio>
     </a-radio-group>
-    
+    <!-- 分页 -->
+    <a-pagination class="pagination-s" show-size-changer :current="pageNo" :pageSize.sync="pageSize" :total="500" @showSizeChange="onShowSizeChange" @change="onShowPageChange" />
   </a-modal>
 </template>
 
@@ -42,7 +43,9 @@
           { name: 'Option B', bindStatus: 0, value: 2 },
           { name: 'Option C', bindStatus: 0, value: 3 },
           { name: 'Option D', bindStatus: 1, value: 4 }
-        ]
+        ],
+        pageNo: 1,  //  页码
+        pageSize: 10,  //  每页条数
       }
     },
     methods: {
@@ -59,6 +62,14 @@
         setTimeout(()=>{
           _this.modalIsShow = false
         },500)
+      },
+      //  页码  change
+      onShowPageChange(page, pageSize){
+        console.log(page, pageSize,'++++++')
+      },
+      //  pageSize 变化的回调
+      onShowSizeChange(current, size){
+        console.log(current, size,'_______')
       }
     },
     watch: {
@@ -109,5 +120,8 @@
         }
       }
     }
+    .pagination-s{
+      margin-top: 20px;
+    }
   }
 </style>

+ 140 - 0
src/views/CarWashManagement/DetailsCarWashModal.vue

@@ -0,0 +1,140 @@
+<template>
+  <a-modal class="DetailsCarWashModal" title="查看详情" :width="1000" :footer="null" :destroyOnClose="true" @cancel="isShow=false" v-model="isShow">
+    <a-row :gutter="20">
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">网点名称:</p>
+        <p class="item-main">车领主网络科技有限公司-北二环贞观路口店车领主网络科技有限公司-北二环贞观路口店车领主网络科技有限公司-北二环贞观路口店车领主网络科技有限公司-北二环贞观路口店车领主网络科技有限公司-北二环贞观路口店</p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">地址:</p>
+        <p class="item-main">陕西省 - 西安市 - 未央区</p>
+      </a-col>
+      <a-col :span="24" class="item-cont">
+        <p class="item-label">详细地址:</p>
+        <p class="item-main">北二环贞观路口华帝金座</p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">设备ID:</p>
+        <p class="item-main">ID58787878787878787</p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">网点标签:</p>
+        <p class="item-main">
+          <a-tag color="blue">网点A</a-tag>
+          <a-tag color="blue">网点B</a-tag>
+        </p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">经度:</p>
+        <p class="item-main">105.45</p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">纬度:</p>
+        <p class="item-main">187.05</p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">服务类型:</p>
+        <p class="item-main">
+          <a-tag color="blue">极速洗车</a-tag>
+          <a-tag color="blue">精致洗车</a-tag>
+          <a-tag color="blue">机动洗车</a-tag>
+        </p>
+      </a-col>
+      <a-col :span="12" class="item-cont">
+        <p class="item-label">营业时间:</p>
+        <p class="item-main">08:30 - 22:00</p>
+      </a-col>
+      <a-col :span="24" class="item-cont">
+        <p class="item-label">时段价格:</p>
+        <div class="item-main">
+          <div class="item-period">
+            <p class="period-name">【时段1】</p>
+            <p class="period">08:30 - 11:30</p>
+            <p class="period-price">极速洗车:<strong class="price">15</strong><span class="price-unit">元</span></p>
+            <p class="period-price">精致洗车:<strong class="price">30</strong><span class="price-unit">元</span></p>
+            <p class="period-price">机动洗车:<strong class="price">20</strong><span class="price-unit">元</span></p>
+          </div>
+          <div class="item-period">
+            <p class="period-name">【时段2】</p>
+            <p class="period">11:30 - 7:30</p>
+            <p class="period-price">极速洗车:<strong class="price">15</strong><span class="price-unit">元</span></p>
+            <p class="period-price">精致洗车:<strong class="price">30</strong><span class="price-unit">元</span></p>
+            <p class="period-price">机动洗车:<strong class="price">20</strong><span class="price-unit">元</span></p>
+          </div>
+        </div>
+      </a-col>
+      <a-col :span="24" class="item-cont">
+        <p class="item-label">路段指引:</p>
+        <p class="item-main">陕西省西安市未央区北二环贞观路口华帝金座</p>
+      </a-col>
+      <a-col :span="24" class="item-cont">
+        <p class="item-label">温馨提示:</p>
+        <p class="item-main">请注意避过高峰时期</p>
+      </a-col>
+      <a-col :span="24" class="btn-cont">
+        <a-button @click="isShow=false">取消</a-button>
+      </a-col>
+    </a-row>
+  </a-modal>
+</template>
+
+<script>
+  export default{
+    name: 'DetailsCarWashModal',
+    props: {
+      openModal: {  //  弹框是否展示
+        type: Boolean,
+        default: false
+      },
+    },
+    data(){
+      return{
+        isShow: this.openModal,  //  弹框是否展示
+      }
+    },
+    watch: {
+      //  父页面传过来的弹框状态
+      openModal (newValue, oldValue) {
+        this.isShow = newValue
+      },
+      //  重定义的弹框状态
+      isShow (val){
+        if (!val){
+          this.$emit('close')
+        }
+      }
+    }
+  }
+</script>
+
+<style lang="less">
+  .DetailsCarWashModal{
+    p{
+      margin: 0;
+    }
+    .item-cont{
+      margin-bottom: 24px;
+      display: flex;
+      align-items: center;
+      .item-label{
+        width: 115px;
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.85);
+        text-align: right;
+        flex-shrink: 0;
+      }
+      .item-main{
+        flex-grow: 1;
+      }
+      .item-period{
+        display: flex;
+        align-items: center;
+        justify-content: space-evenly;
+        flex-grow: 1;
+      }
+    }
+    .btn-cont{
+      text-align: center;
+    }
+  }
+</style>

+ 194 - 0
src/views/power/role/menuModal.vue

@@ -0,0 +1,194 @@
+<template>
+  <div>
+    <a-modal class="modalBox" :title="roleName" v-model="isshow" @cancle="cancel">
+      <a-form class="form-box" style="max-height: 600px;" :form="form" @submit="handleSubmit">
+
+        <a-tree
+          checkable
+          @check="onCheck"
+          @expand="onExpand"
+          :expandedKeys="expandedKeys"
+          :autoExpandParent="autoExpandParent"
+          v-model="checkedKeys"
+          :treeData="treeData"
+        />
+
+      </a-form>
+      <a-form-item :wrapper-col="{ offset: 15 }">
+        <a-button type="primary" @click="handleSubmit()">
+          保存
+        </a-button>
+        <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+          取消
+        </a-button>
+      </a-form-item>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { addMenuPower } from '@/api/power-role.js'
+export default {
+  name: 'RoleModal',
+  components: {
+    STable, VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      treeData: [],
+      roleName: '',
+      expandedKeys: [],
+      autoExpandParent: true,
+      checkedKeys: [],
+      checkedData: [],
+      isshow: this.visible,
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'menuModal' }),
+      id: '' // 角色id
+    }
+  },
+  methods: {
+    onExpand (expandedKeys) {
+      // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+      // or, you can remove all expanded children keys.
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+    onCheck (checkedKeys, info) {
+      this.checkedData = [...checkedKeys, ...info.halfCheckedKeys]
+      this.checkedKeys = checkedKeys
+    },
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          if (this.checkedData.length == 0) {
+            return this.$message.warning('请先选择菜单')
+          }
+          const arr = this.checkedData.join(',')
+          addMenuPower({ id: this.id, menuIds: arr }).then(res => {
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+      this.roleName = ''
+      this.id = ''
+      this.checkedKeys = []
+    },
+    findLeaf (data, arr) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        if (node.children) {
+          this.findLeaf(node.children, arr)
+        } else {
+          const hasNode = arr.find(item => {
+            return item == node.id
+          })
+          if (hasNode) {
+            this.checkedKeys.push(node.id)
+          }
+        }
+      }
+    }
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'menuModal' })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        if (this.data) { // 编辑
+          this.treeData = this.data.allMenuList
+          this.id = this.data.role.id
+          this.roleName = '分配权限' + '(' + this.data.role.name + ')'
+          if (this.data.role.menuIds) {
+            const arr = this.data.role.menuIds.split(',')
+            const temp = []
+            arr.map(item => {
+              temp.push(Number(item))
+            })
+            this.checkedData = temp
+            this.expandedKeys = temp
+            // 找出叶子节点
+            this.findLeaf(this.treeData, temp)
+          }
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style >
+  .modalBox{
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+  .form-box {
+    max-height: 600px !important;
+    overflow: auto;
+  }
+  .form-box::-webkit-scrollbar{
+    width: 6px;
+    height: 6px ;
+  }
+
+  .form-box::-webkit-scrollbar-thumb{
+    width: 6px;
+    height: 6px ;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 0 2px #d1d1d1;
+    background: #e4e4e4;
+  }
+</style>

+ 222 - 0
src/views/power/role/roleList.vue

@@ -0,0 +1,222 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="48">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="角色名称">
+              <a-input allowClear v-model="queryParam.name" placeholder="请输入角色名称"/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="6" :sm="24">
+            <a-form-item label="状态">
+              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.isEnable" allowClear placeholder="请选择状态" ></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider/>
+    <div class="table-operator">
+      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
+    </div>
+
+    <s-table
+      ref="table"
+      size="default"
+      rowKey="id"
+      :columns="columns"
+      :data="loadData"
+      bordered
+    >
+      <span slot="status" slot-scope="text, record">
+        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.isEnable" @change="changeFlagHandle(text, record)"/>
+      </span>
+
+      <span slot="action" slot-scope="text, record">
+        <template>
+          <a class="action-button menu-text" @click="openMenuModal(record)">菜单权限</a>
+          <a class="action-button" @click="handleEdit(record)">修改</a>
+          <a v-if="!record.isEnable" class="action-button red-text" @click="delect(record)">删除</a>
+        </template>
+      </span>
+    </s-table>
+    <roleModal :visible="showModal" :data="itemData" @refresh="refreshTable" @close="showModal = false"></roleModal>
+    <menuModal :visible="showMenuModal" :data="menuData" @close="showMenuModal = false"></menuModal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import roleModal from './roleModal.vue'
+import menuModal from './menuModal.vue'
+import { getPowerRoleList, updateEnableStatus, delectRolePower, getMenuList } from '@/api/power-role.js'
+export default {
+  name: 'RoleList',
+  components: {
+    STable, VSelect, roleModal, menuModal
+  },
+  data () {
+    return {
+      // 查询参数
+      queryParam: {
+        name: '',
+        isEnable: ''
+      },
+      showModal: false,
+      showMenuModal: false,
+      itemData: {}, // 编辑行数据
+      menuData: {},
+      // 表头
+      columns: [
+        {
+          title: '序号',
+          dataIndex: 'no',
+          width: '40',
+          align: 'center'
+        },
+        {
+          title: '角色名称',
+          dataIndex: 'name',
+          width: '100',
+          align: 'center'
+        },
+        {
+          title: '角色描述',
+          dataIndex: 'remarks',
+          width: '100',
+          align: 'center'
+        },
+        {
+          title: '状态',
+          width: '100',
+          align: 'center',
+          scopedSlots: { customRender: 'status' }
+        },
+        {
+          title: '创建时间',
+          dataIndex: 'createDate',
+          width: '120',
+          align: 'center'
+        },
+        {
+          title: '操作',
+          width: '100',
+          align: 'center',
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return getPowerRoleList(Object.assign(parameter, this.queryParam)).then(res => {
+          const no = (res.data.pageNo - 1) * res.data.pageSize
+          for (let i = 0; i < res.data.list.length; i++) {
+            const _item = res.data.list[i]
+            _item.no = no + i + 1
+            _item.isEnable = _item.isEnable + '' === '1'
+          }
+          return res.data
+        })
+      },
+      optionAlertShow: false
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      // vm.$refs.table.refresh()
+    })
+  },
+  methods: {
+    // 刷新列表
+    refreshTable () {
+      this.$refs.table.refresh(true)
+    },
+    // 新建
+    openModal () {
+      this.showModal = true
+      this.itemData = {}
+    },
+    // 打开分配权限弹窗
+    openMenuModal (row) {
+      this.getMenuList(row.id)
+    },
+    // 获取菜单树列表
+    getMenuList (id) {
+      const _this = this
+      getMenuList({ id: id }).then(res => {
+        if (res.status == 200) {
+          _this.menuData = res.data
+          this.showMenuModal = true
+        }
+      })
+    },
+
+    // 删除
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '警告',
+        content: '删除后无法恢复,确认删除?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          delectRolePower({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success('删除成功')
+              _this.$refs.table.refresh()
+            } else {
+              this.$message.error(res.message)
+            }
+          }).catch(() => {
+            _this.$message.success('删除失败, 请稍后重试')
+          })
+        }
+      })
+    },
+    handleEdit (row) {
+      this.showModal = true
+      this.itemData = row
+    },
+    // 修改状态
+    changeFlagHandle (text, record) {
+      const _data = {
+        id: record.id,
+        flag: record.isEnable ? '1' : '0'
+      }
+      updateEnableStatus(_data).then(res => {
+        if (res.status + '' === '200') {
+          this.$message.success('修改成功')
+        } else {
+          record.isEnable = !record.isEnable
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped>
+  .table-page-search-wrapper .ant-form-inline .ant-form-item{
+    margin-bottom: 0;
+  }
+  .action-button{
+    line-height: 40px;
+    white-space: nowrap;
+    padding: 5px 10px;
+    background-color: #1890ff;
+    border-radius: 4px;
+    color: #fff;
+    margin-right: 5px;
+  }
+  .red-text{
+    background-color: red;
+  }
+  .menu-text {
+    background-color: #f90;
+  }
+</style>

+ 172 - 0
src/views/power/role/roleModal.vue

@@ -0,0 +1,172 @@
+<template>
+  <div>
+    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+      <a-form :form="form" @submit="handleSubmit">
+        <!-- 用户名称 -->
+        <a-form-item label="角色名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入角色名称"
+            v-decorator="['formData.name', {
+              initialValue: formData.name,
+              rules: [{ required: true, message: '请输入角色名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
+          />
+        </a-form-item>
+
+        <!-- 状态 -->
+        <a-form-item label="状态" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-radio-group
+            name="radioGroup"
+            v-decorator="[
+              'formData.isEnable',
+              {
+                initialValue: formData.isEnable,
+                rules: [{ required: true, message: '请选择状态!' }] },
+            ]"
+          >
+            <a-radio :value="1">启用</a-radio>
+            <a-radio :value="0">禁用</a-radio>
+          </a-radio-group>
+        </a-form-item>
+
+        <a-form-item label="角色描述" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-textarea
+            v-decorator="[
+              'formData.remarks',
+              { initialValue: formData.remarks,
+                rules: [] },
+            ]"
+            style="min-height: 60px;"
+            placeholder=""
+            autosize />
+        </a-form-item>
+
+        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+          <a-button type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { saveRolePower } from '@/api/power-role.js'
+export default {
+  name: 'RoleModal',
+  components: {
+    STable, VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      titleText: '添加角色',
+      isshow: this.visible,
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'roleModal' }),
+      formData: {
+        name: '',
+        isEnable: '', // 活动状态
+        remarks: ''
+      }
+
+    }
+  },
+  methods: {
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          saveRolePower(Object.assign(this.formData, values.formData)).then(res => {
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+      delete this.formData.id
+      this.formData.name = ''
+      this.formData.isEnable = ''
+      this.formData.remarks = ''
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'roleModal' })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        if (this.data.id) { // 编辑
+          this.titleText = '编辑角色'
+          this.formData = Object.assign({}, this.data)
+          delete this.formData.no
+          this.formData.isEnable = Number(this.formData.isEnable)
+        } else {
+          this.titleText = '添加角色'
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style >
+  .modalBox{
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+</style>

+ 242 - 0
src/views/power/user/userList.vue

@@ -0,0 +1,242 @@
+<template>
+  <a-card :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="48">
+          <a-col :md="6" :sm="24">
+            <a-form-item label="用户名称">
+              <a-input allowClear v-model="queryParam.name" placeholder="请输入用户名称"/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="6" :sm="24">
+            <a-form-item label="手机号码">
+              <a-input allowClear v-model="queryParam.phone" placeholder="请输入手机号码"/>
+            </a-form-item>
+          </a-col>
+
+          <a-col :md="6" :sm="24">
+            <a-form-item label="状态">
+              <v-select code="CHECK_ENABLE_STATE" v-model="queryParam.loginFlag" allowClear placeholder="请选择状态"></v-select>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider/>
+    <div class="table-operator">
+      <a-button type="primary" icon="plus" @click="openModal">新建</a-button>
+    </div>
+
+    <s-table
+      ref="table"
+      size="default"
+      rowKey="id"
+      :columns="columns"
+      :data="loadData"
+      bordered
+    >
+      <span slot="status" slot-scope="text, record">
+        <a-switch checkedChildren="" unCheckedChildren="" v-model="record.loginFlag" @change="changeFlagHandle(text, record)"/>
+      </span>
+      <div slot="roleNames" slot-scope="text, record" :title="record.roleNames">
+        <span v-if="record.roleNames">{{ record.roleNames.substr(0,12) + '...' }}</span>
+        <span v-else>无</span>
+      </div>
+      <span slot="action" slot-scope="text, record">
+        <template>
+          <div >
+            <a class="action-button" @click="handleEdit(record)">修改</a>
+            <a v-if="record.loginFlag" class="action-button reset-text" @click="resetPassword(record)">重置密码</a>
+            <a v-if="!record.loginFlag" class="action-button red-text" @click="delect(record)">删除</a>
+          </div>
+        </template>
+      </span>
+    </s-table>
+    <userModal :visible="showModal" @refresh="$refs.table.refresh(true)" :data="itemData" @close="showModal = false"></userModal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import userModal from './userModal.vue'
+import { resetPSD, updateEnableStatus, getPowerUserList, delectUserPower } from '@/api/power-user.js'
+export default {
+  name: 'UserList',
+  components: {
+    STable, VSelect, userModal
+  },
+  data () {
+    return {
+      // 查询参数
+      queryParam: {
+        name: '',
+        phone: '',
+        loginFlag: ''
+      },
+      showModal: false,
+      itemData: {}, // 编辑行数据
+      // 表头
+      columns: [
+        {
+          title: '序号',
+          dataIndex: 'no',
+          width: '40',
+          align: 'center'
+        },
+        {
+          title: '用户名称',
+          dataIndex: 'name',
+          width: '100',
+          align: 'center'
+        },
+        {
+          title: '手机号码',
+          dataIndex: 'phone',
+          width: '100',
+          align: 'center'
+        },
+        {
+          title: '角色',
+          width: '100',
+          align: 'center',
+          scopedSlots: { customRender: 'roleNames' }
+        },
+        {
+          title: '状态',
+          width: '100',
+          align: 'center',
+          scopedSlots: { customRender: 'status' }
+        },
+        {
+          title: '创建时间',
+          dataIndex: 'createDate',
+          width: '120',
+          align: 'center'
+        },
+        {
+          title: '操作',
+          width: '100',
+          align: 'center',
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return getPowerUserList(Object.assign(parameter, this.queryParam)).then(res => {
+          const no = (res.data.pageNo - 1) * res.data.pageSize
+          for (let i = 0; i < res.data.list.length; i++) {
+            const _item = res.data.list[i]
+            _item.no = no + i + 1
+            _item.loginFlag = _item.loginFlag + '' === '1'
+          }
+          return res.data
+        })
+      },
+      optionAlertShow: false
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      // vm.$refs.table.refresh()
+    })
+  },
+  methods: {
+    // 刷新列表
+    refreshTable () {
+      this.$refs.table.refresh(true)
+    },
+    // 新建
+    openModal () {
+      this.showModal = true
+      this.itemData = {}
+    },
+    // 重置密码
+    resetPassword (row) {
+      resetPSD({
+        id: row.id
+      }).then(res => {
+        if (res.status == 200) {
+          this.$message.success('密码重置成功')
+        } else {
+          this.$message.error(res.message)
+        }
+      }).catch(() => {
+        this.$message.success('密码重置失败, 请稍后重试')
+      })
+    },
+    // 删除
+    delect (row) {
+      const _this = this
+      this.$confirm({
+        title: '警告',
+        content: '删除后无法恢复,确认删除?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          delectUserPower({
+            id: row.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success('删除成功')
+              _this.$refs.table.refresh()
+            } else {
+              _this.$message.error(res.message)
+            }
+          }).catch(() => {
+            _this.$message.success('删除失败, 请稍后重试')
+          })
+        }
+      })
+    },
+    getBizStr (storeBizList) {
+      const str = []
+      storeBizList.forEach(item => {
+        str.push(item.bizTypeName)
+      })
+      return str.join(',')
+    },
+    handleEdit (row) {
+      this.showModal = true
+      this.itemData = row
+    },
+    // 修改状态
+    changeFlagHandle (text, record) {
+      const _data = {
+        id: record.id,
+        flag: record.loginFlag ? '1' : '0'
+      }
+      updateEnableStatus(_data).then(res => {
+        if (res.status + '' === '200') {
+          this.$message.success('修改成功')
+        } else {
+          record.loginFlag = !record.loginFlag
+        }
+      })
+    }
+  }
+}
+</script>
+<style scoped>
+  .table-page-search-wrapper .ant-form-inline .ant-form-item{
+    margin-bottom: 0;
+  }
+  .action-button{
+   line-height: 40px;
+   white-space: nowrap;
+    padding: 5px 10px;
+    background-color: #1890ff;
+    border-radius: 4px;
+    color: #fff;
+    margin-right: 5px;
+  }
+  .red-text{
+    background-color: red;
+  }
+  .reset-text {
+    background-color: #31b50b;
+  }
+</style>

+ 268 - 0
src/views/power/user/userModal.vue

@@ -0,0 +1,268 @@
+<template>
+  <div>
+    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+      <a-form :form="form" @submit="handleSubmit">
+        <a-row :gutter="24">
+          <a-col :span="12">
+            <!-- 用户名称 -->
+            <a-form-item label="用户名称" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-input
+                placeholder="请输入用户名称"
+                v-decorator="['formData.name', {
+                  initialValue: formData.name,
+                  rules: [{ required: true, message: '请输入用户名称!' },{pattern:'^[^<|>]{1,20}$',message:'请输入不含<或>的字符,最多20个字符'}] }]"
+              />
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <!-- 手机号码 -->
+            <a-form-item label="手机号码" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-input
+                placeholder="请输入手机号码"
+                v-decorator="['formData.phone', {
+                  initialValue: formData.phone,
+                  rules: [{ required: true, message: '请输入手机号码!' },{pattern:/^[1][0-9]{10}$/, message: '请输入正确的手机号码!'}] }]"
+              />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <!-- 性别 -->
+          <a-col :span="12">
+            <a-form-item label="性别" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <v-select
+                code="SEX"
+                v-decorator="[
+                  'formData.sex',
+                  {
+                    initialValue: formData.sex,
+                    rules: [{ required: true, message: '请选择性别!' }] },
+                ]"
+                allowClear ></v-select>
+
+            </a-form-item>
+          </a-col>
+          <!-- 状态 -->
+          <a-col :span="12">
+            <a-form-item label="状态" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
+              <a-radio-group
+                name="radioGroup"
+                v-decorator="[
+                  'formData.loginFlag',
+                  {
+                    initialValue: formData.loginFlag,
+                    rules: [{ required: true, message: '请选择状态!' }] },
+                ]"
+              >
+                <a-radio :value="1">是</a-radio>
+                <a-radio :value="0">否</a-radio>
+              </a-radio-group>
+
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="24">
+            <a-form-item label="角色" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
+              <a-select
+                v-decorator="[
+                  'formData.roleNames',
+                  {
+                    initialValue: formData.roleNames,
+                    rules: [{ required: true, message: '请选择状态!' }] },
+                ]"
+                mode="multiple"
+                style="width: 100%"
+                placeholder="请选择角色"
+              >
+                <a-select-option
+                  v-for="item in roleList"
+                  :key="item.id"
+                  :disabled="item.isEnable == '0' ? true : false"
+                >{{ item.name }}</a-select-option
+                >
+              </a-select>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="24">
+          <a-col :span="24">
+            <a-form-item label="备注" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
+              <a-textarea
+                v-decorator="[
+                  'formData.remarks',
+                  {
+                    initialValue: formData.remarks,
+                    rules: [] },
+                ]"
+                style="min-height: 50px;"
+                placeholder=""
+                autosize />
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+          <a-button type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { getRoleList, saveUserPower } from '@/api/power-user.js'
+export default {
+  name: 'UserModal',
+  components: {
+    STable, VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      titleText: '添加用户',
+      isshow: this.visible,
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'miniForm' }),
+      roleList: [],
+      formData: {
+        roleNames: undefined, // 角色
+        name: '',
+        loginFlag: '', // 活动状态
+        phone: '',
+        sex: '',
+        remarks: ''
+      }
+    }
+  },
+  methods: {
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          values.formData.roleNames = values.formData.roleNames.join(',')
+          saveUserPower(Object.assign({ id: this.data.id ? this.data.id : '' }, values.formData)).then(res => {
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.error(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+      delete this.formData.id
+      this.formData.roleNames = []
+      this.formData.name = ''
+      this.formData.loginFlag = ''
+      this.formData.phone = ''
+      this.formData.sex = ''
+      this.formData.remarks = ''
+    },
+
+    // 获取角色列表接口
+    getRoleList () {
+      getRoleList().then(res => {
+        if (res.status + '' === '200') {
+          this.roleList = res.data
+        } else {
+          this.$message.warning(res.message)
+        }
+      })
+    }
+
+  },
+  mounted () {
+    this.getRoleList()
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'miniForm' })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        if (this.data.id) { // 编辑
+          this.titleText = '编辑用户'
+          this.formData = Object.assign({}, this.data)
+          delete this.formData.no
+          let roleNames = this.formData.roleNames
+          if (roleNames) {
+            roleNames = roleNames.split(',')
+            const arr = []
+            roleNames.map(item => {
+              const row = this.roleList.find(a => {
+                return a.name == item
+              })
+              if (row) {
+                arr.push(row.id)
+              }
+            })
+            this.formData.roleNames = arr
+          } else {
+            this.formData.roleNames = []
+          }
+
+          this.formData.loginFlag = Number(this.formData.loginFlag)
+        } else {
+          this.titleText = '添加用户'
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style >
+  .modalBox{
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+</style>