Bladeren bron

供应商系统设置菜单新增

yuwenjun1997 2 jaren geleden
bovenliggende
commit
f49904a56d

+ 2 - 0
src/components/index.js

@@ -1,9 +1,11 @@
 import AuditStatus from './AuditStatus'
 import AuditButtonGroup from './AuditButtonGroup'
+import Pagination from './Pagination'
 
 const install = (Vue) => {
   Vue.component(AuditStatus.name, AuditStatus)
   Vue.component(AuditButtonGroup.name, AuditButtonGroup)
+  Vue.component(Pagination.name, Pagination)
 }
 
 export default {

+ 2 - 0
src/router/index.js

@@ -26,6 +26,7 @@ import normalPersonal from './module/normal/personal'
 import normalPersonnel from './module/normal/personnel'
 import normalVip from './module/normal/vip'
 import normalUser from './module/normal/user'
+import normalSettings from './module/normal/settings'
 
 // 需要权限访问的路由列表
 export const asyncRoutes = [
@@ -41,6 +42,7 @@ export const asyncRoutes = [
   ...normalMaterial,
   ...normalPersonal,
   ...normalPersonnel,
+  ...normalSettings,
   ...normalUser
 ]
 

+ 7 - 0
src/router/module/admin/settings.js

@@ -54,6 +54,13 @@ const settingRoutes = [
         hidden: true,
         meta: { title: '修改用户', noCache: true },
         component: () => import('@/views/admin/settings/accounts/edit')
+      },
+      {
+        path: 'auth-card',
+        name: 'SettingsAuthCard',
+        hidden: true,
+        meta: { title: '授权牌模板', noCache: true },
+        component: () => import('@/views/admin/settings/auth-card')
       }
     ]
   }

+ 63 - 0
src/router/module/normal/settings.js

@@ -0,0 +1,63 @@
+/* Layout */
+import Layout from '@/layout'
+
+const settingRoutes = [
+  {
+    path: '/settings',
+    component: Layout,
+    redirect: '/settings/menus',
+    name: 'NormalSettings',
+    meta: { title: '系统设置', icon: 'el-icon-s-tools', noCache: true },
+    children: [
+      {
+        path: 'roles',
+        name: 'NormalSettingsRoles',
+        meta: { title: '角色管理', noCache: true },
+        component: () => import('@/views/normal/settings/roles')
+      },
+      {
+        path: 'roles/add',
+        name: 'NormalSettingsRolesAdd',
+        hidden: true,
+        meta: { title: '添加角色', noCache: true },
+        component: () => import('@/views/normal/settings/roles/edit')
+      },
+      {
+        path: 'roles/edit',
+        name: 'NormalSettingsRolesEdit',
+        hidden: true,
+        meta: { title: '修改角色', noCache: true },
+        component: () => import('@/views/normal/settings/roles/edit')
+      },
+      {
+        path: 'accounts',
+        name: 'NormalSettingsAccounts',
+        meta: { title: '用户管理', noCache: true },
+        component: () => import('@/views/normal/settings/accounts')
+      },
+      {
+        path: 'accounts/add',
+        name: 'NormalSettingsAccountsAdd',
+        hidden: true,
+        meta: { title: '添加用户', noCache: true },
+        component: () => import('@/views/normal/settings/accounts/edit')
+      },
+      {
+        path: 'accounts/edit',
+        name: 'NormalSettingsAccountsEdit',
+        hidden: true,
+        meta: { title: '修改用户', noCache: true },
+        component: () => import('@/views/normal/settings/accounts/edit')
+      },
+      {
+        path: 'auth-card',
+        name: 'NormalSettingsAuthCard',
+        hidden: true,
+        meta: { title: '授权牌模板', noCache: true },
+        component: () => import('@/views/normal/settings/auth-card')
+      }
+    ]
+  }
+]
+
+export default settingRoutes

+ 142 - 0
src/views/admin/settings/auth-card/components/supplier-list.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          size="mini"
+          placeholder="供应商名称"
+          clearable
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商类型:</span>
+        <el-select
+          v-model="listQuery.shopType"
+          placeholder="供应商类型"
+          size="mini"
+          clearable
+          @change="fetchSupplierList"
+        >
+          <el-option label="所有类型" value="" />
+          <el-option label="代理商" :value="2" />
+          <el-option label="品牌方" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.mobile"
+          clearable
+          size="mini"
+          placeholder="手机号"
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" size="mini" @click="filterSupplierList">查询</el-button>
+      </div>
+    </div>
+    <el-table
+      v-infinite-scroll="onLoad"
+      :data="supplierList"
+      border
+      class="infinite-list hide-table-check-all"
+      style="overflow: auto"
+      :infinite-scroll-delay="300"
+      :infinite-scroll-immediate="false"
+      header-row-class-name="tableHeader"
+      highlight-current-row
+      @row-click="handleSelectSupplier"
+    >
+      >
+      <el-table-column label="选择" width="55" align="center">
+        <template slot-scope="{ row }">
+          <el-radio v-model="selectedAuthUserId" :label="row.authUserId"><span v-show="false">1</span></el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column label="序号" type="index" width="80" align="center" />
+      <el-table-column property="name" label="供应商名称" />
+      <el-table-column label="供应商类型" align="center" width="120">
+        <template slot-scope="{ row }">
+          <span v-if="row.shopType === 1">品牌方</span>
+          <span v-else>代理商</span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="登录账号" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.loginAccount">{{ row.loginAccount }}</span>
+          <span v-else>未绑定</span>
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="mobile" label="手机号" align="center" width="160" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+    </el-table>
+  </div>
+</template>
+<script>
+import { fetchSupplierList } from '@/api/supplier'
+export default {
+  name: 'SupplierList',
+  data() {
+    return {
+      listQuery: {
+        shopName: '',
+        shopType: '',
+        mobile: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      supplierList: [],
+      selectedAuthUserId: ''
+    }
+  },
+  created() {
+    this.filterSupplierList()
+  },
+  methods: {
+    // 确认选中的供应商
+    handleSubmitSupplier() {
+      this.dialogTableVisible = false
+      this.currentSupplierList = [this.selectedSupplierInfo]
+    },
+    // 选择供应商
+    handleSelectSupplier(e) {
+      this.selectedAuthUserId = e.authUserId
+      this.selectedSupplierInfo = e
+      this.$emit('selected', e)
+    },
+    // 选择供应商对话框关闭事件
+    handleDialogClosed() {
+      this.listQuery.pageNum = 1
+      this.listQuery.shopName = ''
+      this.listQuery.shopType = ''
+      this.listQuery.mobile = ''
+      this.listQuery.linkMan = ''
+    },
+    // 筛选供应商
+    filterSupplierList() {
+      this.pageNum = 1
+      this.supplierList = []
+      this.fetchSupplierList()
+    },
+    // 获取供应商列表
+    fetchSupplierList() {
+      fetchSupplierList(this.listQuery).then((res) => {
+        console.log(res)
+        this.supplierList = [...this.supplierList, ...res.data.list]
+        this.hasNextPage = res.data.hasNextPage
+        this.total = res.data.total
+      })
+    },
+    onLoad() {
+      if (!this.hasNextPage) return
+      this.listQuery.pageNum++
+      this.fetchSupplierList()
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 142 - 0
src/views/admin/settings/auth-card/index.vue

@@ -0,0 +1,142 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>所属供应商:</span>
+        <el-select
+          v-model="listQuery.shopId"
+          placeholder="请选择供应商"
+          clearable
+          style="width: 200px"
+          class="filter-item"
+          @change="getList"
+        >
+          <el-option label="已启用" :value="0" />
+          <el-option label="未启用" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary">查询</el-button>
+        <el-button type="primary" @click="addCardVisible = true">添加</el-button>
+      </div>
+    </div>
+    <el-table v-loading="listLoading" style="width: 100%" header-row-class-name="tableHeader" :data="list" border fit>
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column label="授权牌模板" align="center" width="200px">
+        <template slot-scope="{ row }">
+          <el-tooltip effect="dark" content="点击查看全图" placement="top-start">
+            <el-image :src="row.image" :preview-src-list="[row.image]" fit="cover" />
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column prop="shopName" label="所属供应商" align="center" />
+      <el-table-column label="操作" align="center" width="280px">
+        <template>
+          <el-button type="primary" size="mini" @click="selectSupplierVisible = true">更换供应商</el-button>
+          <el-button type="primary" size="mini">停用</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 供应商列表 -->
+    <el-dialog title="提示" :visible.sync="selectSupplierVisible" width="66%">
+      <supplier-list @selected="onSupplierSelected" />
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="selectSupplierVisible = false">取 消</el-button>
+        <el-button type="primary" @click="selectSupplierVisible = false">确 定</el-button>
+      </span>
+    </el-dialog>
+    <!-- 上传图片 -->
+    <el-dialog title="添加授权牌" :visible.sync="addCardVisible" width="30%">
+      <el-dialog width="66%" title="选择供应商" :visible.sync="addCardInnerVisible" append-to-body>
+        <supplier-list @selected="onSupplierSelected" />
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="addCardInnerVisible = false">取 消</el-button>
+          <el-button type="primary" @click="addCardInnerVisible = false">确 定</el-button>
+        </div>
+      </el-dialog>
+      <el-form :model="formData" label-width="100px">
+        <el-form-item label="授权牌模板:">
+          <el-input v-show="false" v-model="formData.image" />
+          <upload-image />
+        </el-form-item>
+        <el-form-item label="所属供应商:">
+          <el-input v-show="false" v-model="formData.shopId" />
+          <el-button type="primary" size="mini" @click="addCardInnerVisible = true">选择供应商</el-button>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="addCardVisible = false">取 消</el-button>
+        <el-button type="primary" @click="addCardVisible = false">确定</el-button>
+      </div>
+    </el-dialog>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList(listQuery)"
+    />
+  </div>
+</template>
+<script>
+import UploadImage from '@/components/UploadImage'
+import SupplierList from './components/supplier-list.vue'
+export default {
+  components: {
+    UploadImage,
+    SupplierList
+  },
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        shopId: '',
+        pageSize: 15,
+        pageNum: 1
+      },
+      list: [],
+      total: 0,
+      formData: {
+        image: '',
+        shopId: ''
+      },
+      addCardVisible: false,
+      addCardInnerVisible: false,
+      selectSupplierVisible: false
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取授权牌模板列表
+    getList() {
+      this.list = [
+        {
+          shopName: 'ROSS',
+          image: 'https://picsum.photos/500/400'
+        }
+      ]
+      console.log(123)
+    },
+
+    // 选中供应商
+    onSupplierSelected(e) {
+      console.log(e)
+    },
+
+    // 表格序号
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.el-image {
+  max-width: 120px;
+  max-height: 30px;
+  display: block;
+  margin: 0 auto;
+}
+</style>

+ 170 - 0
src/views/normal/settings/accounts/edit.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="app-container menus-edit">
+    <el-form ref="userInfoFormRef" label-width="100px" :model="userInfo" :rules="rules">
+      <!-- <el-form-item label="用户头像:">
+        <el-input v-show="false" v-model="user.avatar" />
+        <upload-image tip="建议尺寸:60 * 60px" />
+      </el-form-item> -->
+      <el-form-item label="登录名:" prop="username">
+        <el-input v-model="userInfo.username" placeholder="登录名" />
+      </el-form-item>
+      <el-form-item v-if="!userInfo.id" label="密码:" prop="password">
+        <el-input v-model="userInfo.password" placeholder="密码" />
+      </el-form-item>
+      <el-form-item label="联系人:">
+        <el-input v-model="userInfo.linkMan" placeholder="联系人" />
+      </el-form-item>
+      <el-form-item label="手机号:" prop="mobile">
+        <el-input v-model="userInfo.mobile" placeholder="手机号" />
+      </el-form-item>
+      <el-form-item label="状态:">
+        <el-radio-group v-model="userInfo.status">
+          <el-radio :label="1">启用</el-radio>
+          <el-radio :label="0">停用</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="用户角色:" prop="roleList">
+        <el-checkbox-group v-model="userInfo.roleList">
+          <el-checkbox v-for="item in roleList" :key="item.id" :label="item.id">{{ item.roleName }}</el-checkbox>
+        </el-checkbox-group>
+      </el-form-item>
+      <el-form-item>
+        <!-- 确认 取消 -->
+        <div class="control-box">
+          <el-button type="warning" @click="$_back">返回</el-button>
+          <el-button type="primary" @click="onSubmit">保存</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { fetchRoleList, createUser, getUser, updateUser } from '@/api/system'
+import { isMobile } from '@/utils/validate'
+
+export default {
+  data() {
+    // 校验角色
+    const validateRoleList = (rule, value, callback) => {
+      if (value instanceof Array) {
+        if (value.length === 0) {
+          callback(new Error('请至少选择一个角色'))
+        } else {
+          callback()
+        }
+      } else {
+        callback(new Error('角色列表为一个数组'))
+      }
+    }
+    // 校验手机号
+    const validateMobile = (rule, value, callback) => {
+      if (value && isMobile(value)) {
+        callback()
+      } else {
+        callback(new Error('请输入合法的手机号'))
+      }
+    }
+    return {
+      editType: 'add',
+      userInfo: {
+        id: 0,
+        username: '',
+        password: '',
+        linkMan: '',
+        mobile: '',
+        status: 1,
+        roleList: [],
+        roleIds: ''
+      },
+      roleList: [],
+      rules: {
+        username: [
+          { required: true, message: '请输入登录名', trigger: 'blur' },
+          { min: 2, max: 15, message: '长度在 2 到 15 个字符', trigger: 'blur' }
+        ],
+        mobile: [{ validator: validateMobile, trigger: 'blur' }],
+        password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+        roleList: [{ required: true, validator: validateRoleList, trigger: 'change' }]
+      }
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type
+    this.fetchRoleList()
+    if (this.editType === 'edit') {
+      this.userInfo.id = this.$route.query.id
+      this.fetchUserInfo()
+    }
+  },
+  methods: {
+    // 获取角色列表
+    fetchRoleList() {
+      fetchRoleList().then(res => {
+        this.roleList = [...this.roleList, ...res.data.list]
+      })
+    },
+    // 修改保存用户信息
+    updateUserInfo() {
+      this.userInfo.roleIds = this.userInfo.roleList.join(',')
+      updateUser(this.userInfo.id, this.userInfo).then(res => {
+        this.$message.success('修改用户成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 保存用户信息
+    createUserInfo() {
+      this.userInfo.roleIds = this.userInfo.roleList.join(',')
+      createUser(this.userInfo).then(res => {
+        this.$message.success('添加用户成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 提交表单
+    onSubmit() {
+      this.$refs.userInfoFormRef.validate(valide => {
+        if (!valide) return
+        if (this.editType === 'add') {
+          this.createUserInfo()
+        } else {
+          this.updateUserInfo()
+        }
+      })
+    },
+    // 获取用户信息
+    fetchUserInfo() {
+      getUser(this.userInfo.id).then(res => {
+        this.setUserInfo(res.data)
+      })
+    },
+    // 设置用户信息
+    setUserInfo(data) {
+      console.log(data)
+      for (const key in this.userInfo) {
+        if (Object.hasOwnProperty.call(data, key)) {
+          this.userInfo[key] = data[key]
+        }
+      }
+      this.userInfo.roleList = data.roleIds.split(',').map(item => parseInt(item))
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.menus-edit {
+  width: 600px;
+  margin: 0 auto;
+  margin-top: 100px;
+}
+.control-box {
+  margin: 20px 0;
+  text-align: center;
+  .el-button {
+    width: 120px;
+    margin: 0 8px;
+  }
+}
+</style>

+ 118 - 0
src/views/normal/settings/accounts/index.vue

@@ -0,0 +1,118 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索区域START -->
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>启用状态:</span>
+        <el-select
+          v-model="listQuery.status"
+          placeholder="启用状态"
+          clearable
+          style="width: 200px"
+          class="filter-item"
+          @change="getList()"
+        >
+          <el-option label="全部" value="" />
+          <el-option label="已启用" :value="0" />
+          <el-option label="未启用" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="$_navigationTo('accounts/add?type=add')">添加用户</el-button>
+      </div>
+    </div>
+    <!-- 搜索区域END -->
+    <el-table
+      v-loading="listLoading"
+      :data="list"
+      style="width: 100%"
+      border
+      fit
+      class="table-cell"
+      header-row-class-name="tableHeader"
+    >
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <!-- <el-table-column prop="title" label="头像" align="center" width="60">
+        <template slot-scope="{ row }">
+          <img :src="row.avatar" class="avatar" alt="">
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="username" label="登录名" align="center" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+      <el-table-column label="手机号" align="center">
+        <template slot-scope="{row}">
+          <span>{{ row.mobile || '—' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="角色描述" align="center">
+        <template slot-scope="{ row }">
+          <span>{{ row.roleDesc || '—' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="启用状态" align="center" width="100">
+        <template slot-scope="{ row }">
+          <el-switch v-model="row.status" :active-value="1" :inactive-value="0" />
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" :disabled="!row.id" @click="$_navigationTo(`accounts/edit?type=edit&id=${row.id}`)">编辑</el-button>
+          <el-button type="danger" size="mini" :disabled="!row.id" @click="removeUser(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import { fetchUserList, deleteUser } from '@/api/system'
+export default {
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        status: '',
+        pageSize: 10,
+        pageNum: 1
+      },
+      list: []
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    // 获取列表
+    getList() {
+      this.listQuery.pageNum = 1
+      this.list = []
+      this.fetchUserList()
+    },
+    // 获取用户列表
+    fetchUserList() {
+      fetchUserList(this.listQuery).then(res => {
+        console.log(res)
+        this.list = [...this.list, ...res.data.list]
+      })
+    },
+    // 删除用户
+    removeUser(row) {
+      deleteUser(row.id).then(res => {
+        this.$message.success('删除用户成功')
+        this.getList()
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.avatar{
+  display: block;
+  width: 40px;
+  height: 40px;
+}
+</style>

+ 142 - 0
src/views/normal/settings/auth-card/components/supplier-list.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          size="mini"
+          placeholder="供应商名称"
+          clearable
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商类型:</span>
+        <el-select
+          v-model="listQuery.shopType"
+          placeholder="供应商类型"
+          size="mini"
+          clearable
+          @change="fetchSupplierList"
+        >
+          <el-option label="所有类型" value="" />
+          <el-option label="代理商" :value="2" />
+          <el-option label="品牌方" :value="1" />
+        </el-select>
+      </div>
+      <div class="filter-control">
+        <span>手机号:</span>
+        <el-input
+          v-model="listQuery.mobile"
+          clearable
+          size="mini"
+          placeholder="手机号"
+          @keyup.enter.native="fetchSupplierList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" size="mini" @click="filterSupplierList">查询</el-button>
+      </div>
+    </div>
+    <el-table
+      v-infinite-scroll="onLoad"
+      :data="supplierList"
+      border
+      class="infinite-list hide-table-check-all"
+      style="overflow: auto"
+      :infinite-scroll-delay="300"
+      :infinite-scroll-immediate="false"
+      header-row-class-name="tableHeader"
+      highlight-current-row
+      @row-click="handleSelectSupplier"
+    >
+      >
+      <el-table-column label="选择" width="55" align="center">
+        <template slot-scope="{ row }">
+          <el-radio v-model="selectedAuthUserId" :label="row.authUserId"><span v-show="false">1</span></el-radio>
+        </template>
+      </el-table-column>
+      <el-table-column label="序号" type="index" width="80" align="center" />
+      <el-table-column property="name" label="供应商名称" />
+      <el-table-column label="供应商类型" align="center" width="120">
+        <template slot-scope="{ row }">
+          <span v-if="row.shopType === 1">品牌方</span>
+          <span v-else>代理商</span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="登录账号" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.loginAccount">{{ row.loginAccount }}</span>
+          <span v-else>未绑定</span>
+        </template>
+      </el-table-column> -->
+      <el-table-column prop="mobile" label="手机号" align="center" width="160" />
+      <el-table-column prop="linkMan" label="联系人" align="center" />
+    </el-table>
+  </div>
+</template>
+<script>
+import { fetchSupplierList } from '@/api/supplier'
+export default {
+  name: 'SupplierList',
+  data() {
+    return {
+      listQuery: {
+        shopName: '',
+        shopType: '',
+        mobile: '',
+        pageNum: 1,
+        pageSize: 10
+      },
+      supplierList: [],
+      selectedAuthUserId: ''
+    }
+  },
+  created() {
+    this.filterSupplierList()
+  },
+  methods: {
+    // 确认选中的供应商
+    handleSubmitSupplier() {
+      this.dialogTableVisible = false
+      this.currentSupplierList = [this.selectedSupplierInfo]
+    },
+    // 选择供应商
+    handleSelectSupplier(e) {
+      this.selectedAuthUserId = e.authUserId
+      this.selectedSupplierInfo = e
+      this.$emit('selected', e)
+    },
+    // 选择供应商对话框关闭事件
+    handleDialogClosed() {
+      this.listQuery.pageNum = 1
+      this.listQuery.shopName = ''
+      this.listQuery.shopType = ''
+      this.listQuery.mobile = ''
+      this.listQuery.linkMan = ''
+    },
+    // 筛选供应商
+    filterSupplierList() {
+      this.pageNum = 1
+      this.supplierList = []
+      this.fetchSupplierList()
+    },
+    // 获取供应商列表
+    fetchSupplierList() {
+      fetchSupplierList(this.listQuery).then((res) => {
+        console.log(res)
+        this.supplierList = [...this.supplierList, ...res.data.list]
+        this.hasNextPage = res.data.hasNextPage
+        this.total = res.data.total
+      })
+    },
+    onLoad() {
+      if (!this.hasNextPage) return
+      this.listQuery.pageNum++
+      this.fetchSupplierList()
+    }
+  }
+}
+</script>
+<style lang="scss" scoped></style>

+ 100 - 0
src/views/normal/settings/auth-card/index.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary">一键生效</el-button>
+      </div>
+    </div>
+    <div class="tip">提示:请勿频繁更新授权牌模板,如有需要,在更新授权牌模板后点击左上角一键生效按钮即可</div>
+    <el-table v-loading="listLoading" style="width: 100%" header-row-class-name="tableHeader" :data="list" border fit>
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column label="授权牌模板" align="center" width="200px">
+        <template slot-scope="{ row }">
+          <el-tooltip effect="dark" content="点击查看全图" placement="top-start">
+            <el-image :src="row.image" :preview-src-list="[row.image]" fit="cover" />
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column label="使用位置" align="center">
+        <template slot-scope="{ row }">
+          <el-checkbox v-model="row.isClubAuth">机构认证</el-checkbox>
+          <el-checkbox v-model="row.isDeviceAuth">设备认证</el-checkbox>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="280px">
+        <template>
+          <el-button type="primary" size="mini">查看</el-button>
+          <el-button type="primary" size="mini">编辑</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList(listQuery)"
+    />
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        shopId: '',
+        pageSize: 15,
+        pageNum: 1
+      },
+      list: [],
+      total: 0,
+      formData: {
+        image: '',
+        shopId: '',
+        isClubAuth: false,
+        isDeviceAuth: false
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    // 获取授权牌模板列表
+    getList() {
+      this.list = [
+        {
+          shopName: 'ROSS',
+          image: 'https://picsum.photos/500/400'
+        }
+      ]
+      console.log(123)
+    },
+
+    // 选中供应商
+    onSupplierSelected(e) {
+      console.log(e)
+    },
+
+    // 表格序号
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.el-image {
+  max-width: 120px;
+  max-height: 30px;
+  display: block;
+  margin: 0 auto;
+}
+
+.tip {
+  margin: 12px 0;
+  font-size: 14px;
+  color: #f56c6c;
+}
+</style>

+ 143 - 0
src/views/normal/settings/roles/edit.vue

@@ -0,0 +1,143 @@
+<template>
+  <div class="app-container roles-edit">
+    <el-form ref="ruleRef" label-width="100px" :model="role" :rules="rules">
+      <el-form-item label="角色名称:" prop="roleName">
+        <el-input v-model="role.roleName" placeholder="角色名称" maxlength="20" />
+      </el-form-item>
+      <el-form-item label="角色描述:" prop="roleDesc">
+        <el-input v-model="role.roleDesc" placeholder="角色描述" maxlength="20" />
+      </el-form-item>
+      <el-form-item label="角色授权:" prop="menuIds">
+        <el-input v-show="false" v-model="role.menuIds" />
+        <el-tree
+          ref="tree"
+          :data="menuTree"
+          show-checkbox
+          default-expand-all
+          node-key="id"
+          highlight-current
+          :props="defaultProps"
+          @check-change="getCheckedKeys"
+        />
+      </el-form-item>
+      <el-form-item>
+        <!-- 确认 取消 -->
+        <div class="control-box">
+          <el-button type="warning" @click="$_back">返回</el-button>
+          <el-button type="primary" @click="handleSubmit">保存</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { sysMenuTree, createRole, getRole, updateRole } from '@/api/system'
+export default {
+  data() {
+    return {
+      editType: '',
+      role: {
+        id: '',
+        roleName: '',
+        roleDesc: '',
+        menuIds: ''
+      },
+      rules: {
+        roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
+        menuIds: [{ required: true, message: '角色授权不能为空', trigger: 'change' }]
+      },
+      menuTree: [],
+      defaultProps: {
+        children: 'subMenus',
+        label: 'title'
+      }
+    }
+  },
+  created() {
+    this.editType = this.$route.query.type
+    if (this.editType === 'edit') {
+      this.role.id = parseInt(this.$route.query.id)
+      this.fetchRoleInfo()
+    }
+    this.getMenuTree()
+  },
+  methods: {
+    getCheckedNodes() {
+      console.log(this.$refs.tree.getCheckedNodes())
+    },
+    getCheckedKeys() {
+      // console.log(this.$refs.tree.getCheckedNodes(false, true).map(item => item.id))
+      this.role.menuIds = this.$refs.tree.getCheckedNodes(false, true).map(item => item.id).join(',')
+    },
+    // 获取菜单权限列表
+    getMenuTree() {
+      sysMenuTree({ menuType: 1 }).then(res => {
+        this.menuTree = res.data
+      })
+    },
+    // 设置角色信息
+    setRoleInfo(data) {
+      for (const key in this.role) {
+        if (Object.hasOwnProperty.call(this.role, key)) {
+          this.role[key] = data[key]
+        }
+      }
+      console.log(this.role.menuIds.split(','))
+      this.$refs.tree.setCheckedKeys([...this.role.menuIds.split(',')])
+    },
+    // 获取角色信息
+    fetchRoleInfo() {
+      getRole(this.role.id).then(res => {
+        console.log(res.data)
+        this.setRoleInfo(res.data)
+      })
+    },
+    // 修改角色
+    updateRole() {
+      updateRole(this.role.id, this.role).then(res => {
+        console.log(res)
+        this.$message.success('修改角色成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 创建角色
+    createRole() {
+      createRole(this.role).then(res => {
+        console.log(res)
+        this.$message.success('添加角色成功')
+        this.$store.dispatch('tagsView/delView', this.$route)
+        this.$router.back()
+      })
+    },
+    // 提交
+    handleSubmit() {
+      this.$refs.ruleRef.validate(valide => {
+        if (!valide) return
+        if (this.editType === 'add') {
+          this.createRole()
+        } else {
+          this.updateRole()
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.roles-edit {
+  width: 600px;
+  margin: 0 auto;
+  margin-top: 40px;
+}
+.control-box {
+  margin: 20px 0;
+  text-align: center;
+  .el-button {
+    width: 120px;
+    margin: 0 8px;
+  }
+}
+</style>

+ 107 - 0
src/views/normal/settings/roles/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-control">
+        <el-button type="primary" @click="$_navigationTo('roles/add?type=add')">添加角色</el-button>
+      </div>
+    </div>
+    <!-- 搜索区域END -->
+    <el-table
+      v-loading="listLoading"
+      :data="list"
+      style="width: 100%"
+      border
+      fit
+      class="table-cell"
+      header-row-class-name="tableHeader"
+    >
+      <el-table-column :index="indexMethod" label="序号" type="index" width="80" align="center" />
+      <el-table-column prop="roleName" label="角色名" align="center" />
+      <el-table-column label="角色描述" align="center">
+        <template slot-scope="{ row }">
+          <span v-if="row.roleDesc">{{ row.roleDesc }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" width="160px">
+        <template slot-scope="{ row }">
+          <span v-if="row.createTime">{{ row.createTime | formatTime }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="更新时间" align="center" width="160px">
+        <template slot-scope="{ row }">
+          <span v-if="row.updateTime">{{ row.updateTime | formatTime }}</span>
+          <span v-else>—</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="{ row }">
+          <el-button type="primary" size="mini" @click="$_navigationTo(`roles/edit?type=edit&id=${row.id}`)">编辑</el-button>
+          <el-button type="danger" size="mini" @click="removeRole(row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import { fetchRoleList, deleteRole } from '@/api/system'
+export default {
+  data() {
+    return {
+      listLoading: false,
+      listQuery: {
+        status: '',
+        pageSize: 10,
+        pageNum: 1
+      },
+      list: []
+    }
+  },
+  created() {
+    this.fetchRoleList()
+  },
+  methods: {
+    indexMethod(index) {
+      return index + this.listQuery.pageSize * (this.listQuery.pageNum - 1) + 1
+    },
+    getList() {
+      this.list = []
+      this.listQuery.pageNum = 1
+      this.fetchRoleList()
+    },
+    // 获取角色列表
+    fetchRoleList() {
+      fetchRoleList(this.listQuery).then(res => {
+        this.list = [...this.list, ...res.data.list]
+      })
+    },
+    // 删除角色
+    removeRole(row) {
+      this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          deleteRole(row.id).then(res => {
+            this.$message.success('删除角色成功')
+            this.getList()
+          })
+        })
+        .catch(() => {
+          this.$message.info('已取消删除')
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.avatar {
+  display: block;
+  width: 40px;
+  height: 40px;
+}
+</style>