SaaS系统用户权限设计3

简介: SaaS系统用户权限设计3

导入员工模块

注册模块

import employees from '@/module-employees/' // 员工管理
Vue.use(employees, store)

在/src/api/base/下配置API(user.js)

import {createAPI} from '@/utils/request'
export const list = data => createAPI('/sys/user', 'get', data)
export const simple = data => createAPI('/sys/user/simple', 'get', data)
export const add = data => createAPI('/sys/user', 'post', data)
export const update = data => createAPI(`/sys/user/${data.id}`, 'put', data)
export const remove = data => createAPI(`/sys/user/${data.id}`, 'delete', data)
export const detail = data => createAPI(`/sys/user/${data.id}`, 'get', data)

用户列表展示

页面代码

<template>
  <div class="dashboard-container">
    <div class="app-container">
      <el-card>
        <span class="seleInfo">
          <el-select v-model="requestParameters.stausInfo">
            <el-option v-for="item in baseData.stausInfos" :key="item.value" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </span>
        <span class="posInfo">
          本月&nbsp;&nbsp;(--)&nbsp;&nbsp;
          <span>在职:
            <em>--</em>
          </span>
          <span>入职:
            <em class="active">--</em>
          </span>
          <span>离职:
            <em class="disabled">--</em>
          </span>
        </span>
        <div class="fr">
            <router-link :to="{'path':'/employees/import/',query: {name: '员工'}}" class="el-button el-button--primary el-button--mini" title="导入">导入</router-link>
            <el-button type="primary" size="mini" title="设置">设置</el-button>
            <router-link :to="{'path':'/employees/archiving/'}" class="el-button el-button--primary el-button--mini" title="历史归档">历史归档</router-link>
            <router-link :to="{'path':'/employees/report/1'}" class="el-button el-button--primary el-button--mini" >1月份报表</router-link>
            <el-button  type="primary" size="mini" icon="el-icon-plus" @click="handlAdd">新增员工</el-button>
        </div>
      </el-card>
      <el-card shadow="never" class="boxMar">
        <el-table :data="dataList" fit style="width: 100%;" border>
          <el-table-column type="index" :index="1" label="序号" width="150"> </el-table-column>
          <el-table-column sortable prop="username" label="姓名" width="150"></el-table-column>
          <el-table-column sortable prop="mobile" label="手机号" width="150"></el-table-column>
          <el-table-column sortable prop="workNumber" label="工号" width="120"></el-table-column>
          <el-table-column sortable prop="formOfEmployment" label="聘用形势" width="200"></el-table-column>
          <el-table-column sortable prop="departmentName" label="部门" width="200"></el-table-column>
          <el-table-column sortable prop="timeOfEntry" label="入职时间" width="150"></el-table-column>
          <el-table-column sortable label="状态" width="120">
            <template slot-scope="scope">
              <el-switch 
              v-model="scope.row.accountStatus" 
              active-color="#13ce66"
              inactive-color="#ff4949"
               @change="handleStatus(scope.row)">
              </el-switch>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" align="center" width="220">
            <template slot-scope="scope">
              <router-link :to="{'path':'/employees/details/' + scope.row.id}" class="el-button el-button--text el-button--small">
                查看
              </router-link>
              <el-button @click="handleRole(scope.row)" type="text" size="small">分配角色</el-button>
              <el-button @click="handleDelete(scope.row)" type="text" size="small">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <div class="pagination">
          <PageTool :paginationPage="requestParameters.page" :paginationPagesize="requestParameters.size" :total="counts" @pageChange="handleCurrentChange" @pageSizeChange="handleSizeChange">
          </PageTool>
        </div>
        <!-- end -->
        <!-- 新增员工弹层 -->
        <component v-bind:is="employeesAdd" ref="addUser" @doQuery="doQuery"></component>
        <!--分配角色组件 -->
      </el-card>
    </div>
  </div>
</template>

js构造数据

<script>
import constantApi from '@/api/constant/employees'
import {list,remove} from "@/api/base/users"
import PageTool from './../../components/page/page-tool'
import employeesAdd from './../components/add'
export default {
  name: 'employeesList',
  components: {
    PageTool,employeesAdd
  },
  data() {
    return {
      employeesAdd: 'employeesAdd',
      baseData: constantApi,
      dataList: [],
      counts: '',
      requestParameters:{
        page: 1,
        size: 10,
      }    
    }
  },
  methods: {
    // 业务方法
    doQuery(params) {
        list(this.requestParameters)
        .then(res => {
          this.dataList = res.data.data.rows
          this.counts = res.data.data.total
        })
    },
    // 每页显示信息条数
    handleSizeChange(size) {
      this.requestParameters.size = size
      if (this.requestParameters.page === 1) {
        this.doQuery(this.requestParameters)
      }
    },
    // 进入某一页
    handleCurrentChange(val) {
      this.requestParameters.page = val
      this.doQuery()
    },
    // 添加新员工
    handlAdd() {
      this.$refs.addUser.dialogFormVisible=true
    },
    // 删除
    handleDelete(item) {
      this.$confirm(
        `本次操作将删除${item.username}删除后账号将不可恢复,您确认删除吗?`,{
         type: 'warning'
        }
      ).then(() => {
          remove({ id: item.id })
            .then(response => {
              this.$message.success('删除成功' + '!')
              this.doQuery();
            })
        })
    }
  },
  // 创建完毕状态
  created: function() {
    this.doQuery()
  },
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.iconInfo {
  .fa {
    color: #999;
    font-size: 14px;
    cursor: pointer;
  }
  a {
    padding: 0 5px;
  }
}
.serachInput {
  .el-input--medium {
    width: 150px;
    .el-input__inner {
    }
  }
}
.serachInput .el-input--medium .el-input__inner {
  height: 26px;
  line-height: 26px;
}
</style>

用户详情

配置路由

     {
        path: 'details/:id',
        component: _import('employees/pages/employees-details'),
        // hidden: true // 是否显示在左侧菜单
        name: 'details',
        meta: {
          title: '详情'
       }
     }

完成用户详情页面

<template>
  <div class="dashboard-container">
    <div class="app-container">
      <el-card :style="{minHeight:boxHeight}">
          <el-tabs v-model="activeName" class="infoPosin">
            <el-tab-pane name="first" class="rInfo">
              <span slot="label">登录账户设置</span>
              <component v-bind:is="accountInfo" :objId='objId' ref="user"></component>
            </el-tab-pane>
            <el-tab-pane name="two" class="rInfo">
                <span slot="label">个人详情</span>
            </el-tab-pane>
            <el-tab-pane name="third" class="rInfo">
                <span slot="label">岗位信息</span>
            </el-tab-pane>
        </el-tabs>
      </el-card>
    </div>
  </div>
</template>
<script>
import accountInfo from './../components/details-account-info'
export default {
  name: 'employeesDetails',
  components: { accountInfo},
  data() {
    return {
      accountInfo:'accountInfo',
      activeName: 'first',
      objId: this.$route.params.id,
      dataList: []
   }
 }
}
</script>

用户信息组件

<template>
  <div class="boxInfo">
    <!-- 表单内容 -->
    <div class="formInfo">
      <div>
        <!-- 头部信息  -->
        <div class="userInfo">
             <div class="headInfo clearfix">
               <div class="headText">
                 <el-form ref="formData" :model="formData" label-width="215px">
                     <el-form-item label="姓名:">
                       <el-input v-model="formData.username" placeholder="请输入"
class="inputW"></el-input>
                     </el-form-item>
                     <el-form-item label="密码:">
                       <el-input v-model="formData.password" placeholder="请输入"
class="inputW"></el-input>
                    </el-form-item>
                    <el-form-item label="部门:">
                        <el-input
                          placeholder="请选择"
                          v-model="formData.departmentName"
                          icon="caret-bottom"
                          class="inputW"
                          @click.native="isShowSelect = !isShowSelect">
                        </el-input>
                        <input v-model="formData.departmentId" type="hidden" >
                        <el-tree v-if="isShowSelect"
                         :expand-on-click-node="false"
                         :data="inspectionObjectOptions"
                         :props="{label:'name'}"
                          default-expand-all
                         :filter-node-method="filterNode"
                           @node-click="handleNodeClick"
                          class="objectTree"
                          ref="tree2">
                        </el-tree>
                    </el-form-item>
                      <el-form-item>
                        <el-button type="primary" @click="saveData">更新</el-button>
                        <router-link :to="{'path':'/employees/index'}" class="el-button 
el-button--text el-button--small">
                          取消
                        </router-link>
                      </el-form-item>
                 </el-form>
               </div>
             </div>
        </div>
      </div>
    </div>
    </div>
</template>
<script>
import constantApi from '@/api/constant/employees'
import {detail,update} from "@/api/base/users"
import { organList } from '@/api/base/departments'
export default {
  name: 'accountInfo',
  props: ['objId'],
  data() {
    return {
      baseData: constantApi,
      inspectionObjectOptions: [],
      isShowSelect:false,
      formData: {
        id: this.objId,
     }
   }
 },
  methods: {
    handleNodeClick(data) {
      this.formData.departmentName = data.name
      this.formData.departmentId = data.id
      this.isShowSelect = false
   },
    // 获取详情
    getObjInfo() {
      detail({ id: this.objId }).then(res => {
          this.formData = res.data.data
     })
   },
    saveData(obj) {
      update(this.formData)
       .then(res => {
          this.formData = res.data
          this.$message.success('保存成功!')
          this.getObjInfo()
     })
   },
 },
  // 创建完毕状态
  created: function() {
    this.getObjInfo()
    organList().then(ret => {
      this.inspectionObjectOptions.push(ret.data.data)
   })
 }
}
</script>

用户的新增

和组织机构的增删改查大同小异

作业-角色管理

需求分析

完成角色的基本CRUD操作

后端实现

实体类

package com.ihrm.domain.system;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "pe_role")
@Getter
@Setter
public class Role implements Serializable {
    private static final long serialVersionUID = 594829320797158219L;
    @Id
    private String id;
    /**
     * 角色名
     */
    private String name;
    /**
     * 说明
     */
    private String description;
    /**
     * 企业id
     */
    private String companyId;
    @JsonIgnore
    @ManyToMany(mappedBy="roles")
    private Set<User> users = new HashSet<User>(0);//角色与用户   多对多
    @JsonIgnore
    @ManyToMany
    @JoinTable(name="pe_role_permission",
            joinColumns={@JoinColumn(name="role_id",referencedColumnName="id")},
            inverseJoinColumns=
{@JoinColumn(name="permission_id",referencedColumnName="id")})
    private Set<Permission> permissions = new HashSet<Permission>(0);//角色与模块 多对多
}

持久化层

package com.ihrm.system.dao;
import com.ihrm.system.domain.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
  * 企业数据访问接口
  */
public interface RoleDao extends JpaRepository<Role, String>, 
JpaSpecificationExecutor<Role> {
}

业务逻辑层

package com.ihrm.system.service;
import com.ihrm.common.utils.IdWorker;
import com.ihrm.system.dao.CompanyDao;
import com.ihrm.system.dao.RoleDao;
import com.ihrm.system.dao.UserDao;
import com.ihrm.system.domain.Company;
import com.ihrm.system.domain.Role;
import com.ihrm.system.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 角色操作业务逻辑层
*/
@Service
public class RoleService {
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RoleDao roleDao;
    /**
     * 添加角色
     */
    public void save(Role role) {
        //填充其他参数
        role.setId(idWorker.nextId() + "");
        roleDao.save(role);
   }
    /**
     * 更新角色
     */
    public void update(Role role) {
        Role targer = roleDao.getOne(role.getId());
        targer.setDescription(role.getDescription());
        targer.setName(role.getName());
        roleDao.save(targer);
   }
    /**
     * 根据ID查询角色
     */
    public Role findById(String id) {
        return roleDao.findById(id).get();
   }
    /**
     * 删除角色
     */
    public void delete(String id) {
        roleDao.deleteById(id);
   }
    public Page<Role> findSearch(String companyId, int page, int size) {
        Specification<Role> specification = new Specification<Role>() {
            @Override
            public Predicate toPredicate(Root<Role> root, CriteriaQuery<?> query, 
CriteriaBuilder cb) {
                return cb.equal(root.get("companyId").as(String.class),companyId);
           }
       };
        return roleDao.findAll(specification, PageRequest.of(page-1, size));
   }
}

控制器层

package com.ihrm.system.controller;
import com.ihrm.common.entity.PageResult;
import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;
import com.ihrm.system.domain.Role;
import com.ihrm.system.domain.User;
import com.ihrm.system.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/sys")
public class RoleController {
    @Autowired
    private RoleService roleService;
    //添加角色
    @RequestMapping(value = "/role", method = RequestMethod.POST)
    public Result add(@RequestBody Role role) throws Exception {
        String companyId = "1";
        role.setCompanyId(companyId);
        roleService.save(role);
        return Result.SUCCESS();
   }
    //更新角色
    @RequestMapping(value = "/role/{id}", method = RequestMethod.PUT)
    public Result update(@PathVariable(name = "id") String id, @RequestBody Role role) 
throws Exception {
        roleService.update(role);
        return Result.SUCCESS();
   }
    //删除角色
    @RequestMapping(value = "/role/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable(name = "id") String id) throws Exception {
        roleService.delete(id);
        return Result.SUCCESS();
   }
    /**
     * 根据ID获取角色信息
     */
    @RequestMapping(value = "/role/{id}", method = RequestMethod.GET)
    public Result findById(@PathVariable(name = "id") String id) throws Exception {
        Role role = roleService.findById(id);
        return new Result(ResultCode.SUCCESS,role);
   }
    /**
     * 分页查询角色
     */
    @RequestMapping(value = "/role", method = RequestMethod.GET)
    public Result findByPage(int page,int pagesize,Role role) throws Exception {
        String companyId = "1";
        Page<Role> searchPage = roleService.findSearch(companyId, page, pagesize);
        PageResult<Role> pr = new
PageResult(searchPage.getTotalElements(),searchPage.getContent());
        return new Result(ResultCode.SUCCESS,pr);
   }
}

前端实现

参考资料自行实现

目录
相关文章
|
1月前
|
存储 缓存 监控
怎么更好地设计一个优秀的SaaS系统
设计一个优秀的SaaS系统,需要从架构、性能、安全性、租户隔离、扩展性等多方面进行深思熟虑。根据业务需求选择合适的多租户架构,保证数据隔离的同时提高系统性能。
119 1
|
5月前
|
传感器 小程序 搜索推荐
(源码)java开发的一套(智慧校园系统源码、电子班牌、原生小程序开发)多端展示:web端、saas端、家长端、教师端
通过电子班牌设备和智慧校园数据平台的统一管理,在电子班牌上,班牌展示、学生上课刷卡考勤、考勤状况汇总展示,课表展示,考场管理,请假管理,成绩查询,考试优秀标兵展示、校园通知展示,班级文化各片展示等多种化展示。
91 0
(源码)java开发的一套(智慧校园系统源码、电子班牌、原生小程序开发)多端展示:web端、saas端、家长端、教师端
|
4月前
|
Oracle 安全 关系型数据库
ERP系统的云计算与SaaS模式:实现高效灵活的企业管理
【7月更文挑战第29天】 ERP系统的云计算与SaaS模式:实现高效灵活的企业管理
238 4
|
3月前
|
数据挖掘 BI API
简单了解CRM与SaaS系统
本文介绍了CRM(客户关系管理系统)和SaaS(软件即服务)的概念、应用场景、两者之间的关系以及CRM接口的作用和设置流程,强调了SaaS模式为CRM系统提供了灵活、便捷、经济高效的使用方式,以及CRM接口在数据集成、自动化流程、功能扩展和数据分析方面的重要性。
121 0
|
6月前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
554 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
6月前
|
消息中间件 缓存 Java
java基于云部署的SaaS医院云HIS系统源码 心理CT、B超 lis、电子病历
云HIS系统是一款满足基层医院各类业务需要的健康云产品。该产品能帮助基层医院完成日常各类业务,提供病患预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站和护士工作站等一系列常规功能,还能与公卫、PACS等各类外部系统融合,实现多层机构之间的融合管理。
106 12
|
6月前
|
存储 运维 Java
java云his系统源码一站式诊所SaaS系统Java版云HIS系统 八大特点
HIS系统采用面向技术架构的分析与设计方法,应用多层次应用体系架构设计,运用基于构件技术的系统搭建模式与基于组件模式的系统内核结构。通过建立统一接口标准,实现数据交换和集成共享,通过统一身份认证和授权控制,实现业务集成、界面集成。
86 1
|
6月前
|
Java 云计算
Java智能区域医院云HIS系统SaaS源码
云HIS提供标准化、信息化、可共享的医疗信息管理系统,实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。优化就医、管理流程,提升患者满意度、基层首诊率,通过信息共享、辅助诊疗等手段,提高基层医生的服务能力构建和谐的基层医患关系。
106 2
|
6月前
|
运维 供应链 安全
SaaS模式云HIS数字化医院信息系统源码
云HIS具有可扩展、易共享、易协同、低成本、体验号、更便捷、易维护的优势,重新定义了数字化医院信息系统,实现数字化医院信息系统的转型升级。云 HIS 系统具有功能完善,涵盖临床各业务部门,采集、抽提、汇总、存贮、展现所有的临床诊疗资料(包括:数据、文本、图形、图像、声音等),是医疗机构实现临床信息化的理想信息平台。
95 1
|
6月前
|
数据采集 前端开发 Java
Java医院绩效考核系统源码maven+Visual Studio Code一体化人力资源saas平台系统源码
医院绩效解决方案包括医院绩效管理(BSC)、综合奖金核算(RBRVS),涵盖从绩效方案的咨询与定制、数据采集、绩效考核及反馈、绩效奖金核算到科到组、分配到员工个人全流程绩效管理;将医院、科室、医护人员利益绑定;全面激活人才活力;兼顾质量和效益、长期与短期利益;助力医院降本增效,持续改善、优化收入、成本结构。
85 0

热门文章

最新文章

下一篇
无影云桌面