10. Yunshang Office System – Mitarbeitergenehmigung

Yunshang Office System: Mitarbeitergenehmigung

Direkter Zugang zur Station B [wie Silicon Valley] :
https://www.bilibili.com/video/BV1Ya411S7aT

Dieser Blog-Beitrag wird hauptsächlich im Zusammenhang mit dem Kurs veröffentlicht, enthält einige meiner eigenen Meinungen und bietet relevante Lösungen für die Probleme, die im Lernprozess auftreten. Gemeinsam lernen und gemeinsam Fortschritte machen! ! !

Im Teil zur Mitarbeitergenehmigung sind mir mehrere Probleme und Fehler aufgefallen
1. Im Front-End-Code der Mitarbeiterseite in der Ressource war die Version von Node-Sass zu problematisch. Am Ende wusste ich wirklich nicht, was ich tun sollte, also habe ich die Version von Node (10 oder 14 in der Ressource) herabgestuft, da ich das Haupt-Back-End bin und das Wissen über das Front-End begrenzt sein wird. Ich habe auch im Internet gesucht, um die Version in package.json zu ändern, aber es hat nicht funktioniert. Deshalb habe ich Ihnen bereits beim ersten Hinweis gesagt, dass Sie die Version ändern sollen. Wenn Sie das Projektstartproblem nach der Suche immer noch nicht lösen können, können Sie ein Downgrade durchführen oder die MVN-Verwaltung [selbst
suchen
] 3. Folgendes ist mir aufgefallen: Die Seite wurde auf P98 nicht normal angezeigt. Ich habe immer noch nicht herausgefunden, warum, also habe ich dieses hinzugefügt und die Seite kaum normal angezeigt, etwa 172 Zeilen für (let i = 0; i < Response.data.records.length; i++) { let item = Response.data.records[i]; try { item.formValues ​​​​= JSON.parse(item.formValues); this.list.pus h(item); } Catch (error) { console.error("JSON-Parsing-Fehler: " + error); console.log("Unparsable JSON string: " + item.formValues); } }

Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein











Fügen Sie hier eine Bildbeschreibung ein

Artikelverzeichnis

1. Funktionsbeschreibung

Das Hintergrundmanagement hat die Genehmigung bereits entworfen und Mitarbeiter können den erforderlichen Genehmigungsantrag über das mobile Endgerät einreichen. Der nächste Schritt ist der Kernprozess der Activiti-Genehmigung. Die Genehmigung durch die für die Genehmigung verantwortliche Person umfasst: Genehmigung und Ablehnung der Genehmigung. Nachdem die Genehmigung bestanden wurde, wird sie automatisch zum nächsten Genehmigungsknoten weitergeleitet. Wenn die Genehmigung abgelehnt wird, wird sie direkt zum Endknoten weitergeleitet und der Prozess endet.

2. Mitarbeitergenehmigung

Wenn es Ihnen unangenehm ist, es auf dem PC anzusehen, können Sie es auf F12 ansehen

1. OA-Genehmigung

Die OA-Genehmigung erfolgt auf dem mobilen Endgerät, das von den Mitarbeitern des Unternehmens verwendet wird, wie in der Abbildung dargestellt:

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-B1HDkfmG-1688013713646)(assets/1671502423642.png)]

1.1. Abfragegenehmigungsklassifizierung und Vorlagenschnittstelle

Besorgen Sie sich die Genehmigungsklassifizierung und die entsprechende Genehmigungsvorlage

1.1.1. Definieren Sie die Serviceschnittstelle

Operationsklasse: ProcessTypeService

List<ProcessType> findProcessType();
1.1.2, Implementierung der Serviceschnittstelle
@Autowired
private ProcessTemplateService processTemplateService;
	
@Override
public List<ProcessType> findProcessType() {
    
    
    //1 查询所有审批分类,返回list集合
    List<ProcessType> processTypeList = baseMapper.selectList(null);

    //2 遍历返回所有审批分类list集合
    for (ProcessType processType:processTypeList) {
    
    
        //3 得到每个审批分类,根据审批分类id查询对应审批模板
        //审批分类id
        Long typeId = processType.getId();
        //根据审批分类id查询对应审批模板
        LambdaQueryWrapper<ProcessTemplate> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProcessTemplate::getProcessTypeId,typeId);
        List<ProcessTemplate> processTemplateList = processTemplateService.list(wrapper);

        //4 根据审批分类id查询对应审批模板数据(List)封装到每个审批分类对象里面
        processType.setProcessTemplateList(processTemplateList);
    }
    return processTypeList;
}
1.1.3, Controller-Schnittstelle

Erstellen Sie die Klasse ProcessApiController

@Api(tags = "审批流管理")
@RestController
@RequestMapping(value="/admin/process")
@CrossOrigin  //跨域
public class ProcessApiController {
    
    
    
    @Autowired
    private ProcessTypeService processTypeService;

    @ApiOperation(value = "获取全部审批分类及模板")
    @GetMapping("findProcessType")
    public Result findProcessType() {
    
    
       return Result.ok(processTypeService.findProcessType());
    }
}

1.2. Front-End-Entwicklung

1.2.1. Verweisen Sie auf die Front-End-Entwicklungsumgebung

Importieren Sie das Front-End-Projekt-Framework aus der Ressourcenbibliothek: guigu-oa-web, die statische Ressourcenseiten enthält, die wir direkt verwenden.

Schritt 1: Abhängigkeiten installieren

npm install

Schritt zwei: Beginnen

npm run serve

Schritt 3: Konfiguration ändern

1. Ändern Sie den API-Basispfad der Datei src/utils/request.js

2. Ändern Sie die Token-Informationen der Datei src/utils/request.js.

Verwenden Sie das Token-Tool theoretisch, um ein temporäres Token für die Verwendung zu generieren. Wir werden die WeChat-Autorisierungsanmeldung in Zukunft verbessern

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-IZodpVkX-1688013713649)(assets/1671677816503.png)]

1.2.2. Definieren Sie die API-Schnittstelle

Erstellen Sie src/api/process.js

import request from '@/utils/request'

const api_name = '/admin/process'

export default {
    
    

  findProcessType() {
    
    
    return request({
    
    
      url: `${
      
      api_name}/findProcessType`,
      method: 'get'
    })
  }
}
1.2.3. Routing hinzufügen

Fügen Sie Routing in src/router/index.js hinzu

{
    
    
  path: '/',
  name: 'OA审批',
  component: () =>
    import('../views/index.vue'),
}
1.2.4, Seitenrendering

Ansichten/index.vue-Seite

<template>
  <div>
    <div class="container">
      <van-nav-bar
        title="OA审批"
      />
      <van-collapse v-model="activeNames">
        <van-collapse-item
          v-for="(item,key) in list"
          :title="item.name"
          :name="item.key">
          <van-row>
            <van-col v-for="template in item.processTemplateList" :key="template.id" span="6">
              <div class="item" @click="apply(template.id)">
                <img :src="template.iconUrl"/>
                <span>{
   
   {template.name}}</span>
              </div>
            </van-col>
          </van-row>
        </van-collapse-item>
      </van-collapse>
    </div>
  </div>
</template>
<script>
import api from '@/api/process'
export default {
  name: "process",
  data() {
    return {
      list: [],
      activeNames: [0,1,2,3,4]
    };
  },
  created(){
    this.fetchData();
  },
  methods: {
    fetchData() {
      api.findProcessType().then(response => {
        console.log(response.data);
        this.list = response.data;
        //全部展开
        this.activeNames = []
        this.list.forEach((item,index) => {
          this.activeNames.push(index)
        })
      });
    },
    apply(id) {
      this.$router.push({ path: '/apply/'+id })
    }
  }
}
</script>
<style lang="scss" scoped>
.container {
  padding-bottom: 50px;
  .item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    img {
      width: 40px;
      height: 40px;
      border-radius: 10px;
    }
    span {
      font-size: 12px;
      padding: 8px 4px;
      text-align: center;
    }
  }
}
</style>

2. Genehmigungsantrag

Rendern Sie dynamische Formulare basierend auf Genehmigungsvorlagen und starten Sie Prozessinstanzen basierend auf dynamischen Formularen

2.1. Erhalten Sie Genehmigungsvorlagendaten

Operationsklasse: ProcessApiController

@Autowired
private ProcessTemplateService processTemplateService;

@ApiOperation(value = "获取审批模板")
@GetMapping("getProcessTemplate/{processTemplateId}")
public Result get(@PathVariable Long processTemplateId) {
    
    
   ProcessTemplate processTemplate = processTemplateService.getById(processTemplateId);
   return Result.ok(processTemplate);
}

2.2. Rendering der Seite des Genehmigungsantrags

2.2.1. Schnittstelle definieren

Fügen Sie die Schnittstelle in der Datei src/api/process.js hinzu

getProcessTemplate(processTemplateId) {
    
    
  return request({
    
    
    url: `${
      
      api_name}/getProcessTemplate/`+processTemplateId,
    method: 'get'
  })
}
2.2.2. Dynamische Formen rendern

Die Initialisierungsumgebung wurde integriert: Mit der Form-Create-Komponente können wir die von der Form-Designer-Komponente gespeicherten Daten direkt rendern

Erstellen Sie src/views/apply.vue

<template>
  <div>
    <van-nav-bar
      title="发起审批"
      left-text="返回"
      left-arrow
      @click-left="() => $router.back()"
    />
    <div style="margin: 10px 10px 0 0;border: 0px solid red;">
    <form-create
      :rule="rule"
      :option="option"
      @submit="onSubmit"
    ></form-create>
    </div>
  </div>
</template>

<script>
import api from "@/api/process";

export default {
  name: "process",

  data() {
    return {
      processTemplateprocessTemplate: null,
      rule: [],
      option: {}
    };
  },

  created() {
    let processTemplateId = this.$route.params.processTemplateId;
    this.fetchData(processTemplateId);
  },

  methods: {
    fetchData(processTemplateId) {
      api.getProcessTemplate(processTemplateId).then(response => {
        console.log(response.data);
        this.processTemplate = response.data;

        this.rule = JSON.parse(this.processTemplate.formProps);
        this.option = JSON.parse(this.processTemplate.formOptions);
      });
    },

    onSubmit(formData) {
		console.log(formData)
    }
  }
};
</script>

<style lang="scss" scoped>
.el-form {
  .el-form-item {
    /deep/ .el-form-item__label {
      font-size: 18px;
      font-weight: 800;
      color: blue;
    }
  }
}
</style>
2.2.3. Testen

Nehmen wir als Beispiel Überstunden, alles andere ist in Ordnung

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-8meBGsQZ-1688013713651)(assets/1671678698916.png)]

Druckdaten übermitteln:

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-czcl9d5y-1688013713652)(assets/1671678754144.png)]

Drucken Sie Daten für unsere benutzerdefinierten Formularattribute und für Eingabewerte.

Die Folgedaten werden auf zwei Arten genutzt:

1. Detaillierte Anzeige der Genehmigung

2. Beurteilen Sie als Prozessinstanzparameter die Prozessrichtung, wie in der folgenden Abbildung dargestellt:

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-acNdEZ0q-1688013713654)(assets/1671678840138.png)]

2.2.4. Daten kapseln und übermitteln
onSubmit(formData) {
    
    
  console.log(formData)
  let formShowData = {
    
    };
  this.rule.forEach(item => {
    
    
    for (let key in formData) {
    
    
      if (key === item.field) {
    
    
        console.log(item.title, formData[key]);
        formShowData[item.title] = formData[key];
      }
    }
  });
  let DATA = {
    
    
    formData: formData,
    formShowData: formShowData
  };
  console.log(DATA);
  let processFormVo = {
    
    
    "processTemplateId": this.processTemplate.id,
    "processTypeId": this.processTemplate.processTypeId,
    "formValues": JSON.stringify(DATA)
  };
  console.log(processFormVo)
}

Druckdaten

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-cXUZpI2q-1688013713656)(assets/1671678899410.png)]

Wir konvertieren die Formulardaten in zwei Teile: formData-Formulardaten und formShowData-Formularanzeigedaten und konstruieren sie in ein formValues-Attribut-JSON-Objekt, das bei späterer Verwendung leicht abgerufen werden kann

2.3. Starten Sie die Prozessinstanz

2.3.1. Ändern Sie den Authentifizierungsfilter

Das Spring-Security-Modul fügt eine Toolklasse hinzu, um die aktuellen Anmeldeinformationen über ThreadLocal aufzuzeichnen

package com.atguigu.security.custom;

/**
 * 获取当前用户信息帮助类
 */
public class LoginUserInfoHelper {
    
    

    private static ThreadLocal<Long> userId = new ThreadLocal<Long>();
    private static ThreadLocal<String> username = new ThreadLocal<String>();

    public static void setUserId(Long _userId) {
    
    
        userId.set(_userId);
    }
    public static Long getUserId() {
    
    
        return userId.get();
    }
    public static void removeUserId() {
    
    
        userId.remove();
    }
    public static void setUsername(String _username) {
    
    
        username.set(_username);
    }
    public static String getUsername() {
    
    
        return username.get();
    }
    public static void removeUsername() {
    
    
        username.remove();
    }
}

Ändern Sie den Filter TokenAuthenticationFilter

Fügen Sie Folgendes hinzu

/**
 * <p>
 * 认证解析token过滤器
 * </p>
 */
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    
    

...................
    
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
    
    
    
        ....................
            
            if (!StringUtils.isEmpty(username)) {
    
    
                //通过ThreadLocal记录当前登录人信息
                LoginUserInfoHelper.setUserId(JwtHelper.getUserId(token));
                LoginUserInfoHelper.setUsername(username);
                
        ....................
            
    }
}
2.3.2. Kapseln Sie das Startprozessobjekt

Für Genehmigungsanwendungsattribute

@Data
@ApiModel(description = "流程表单")
public class ProcessFormVo {
    
    

   @ApiModelProperty(value = "审批模板id")
   private Long processTemplateId;

   @ApiModelProperty(value = "审批类型id")
   private Long processTypeId;

   @ApiModelProperty(value = "表单值")
   private String formValues;

}
2.3.3, Service-Realisierungsfunktion
    @Autowired
    private ProcessTemplateService processTemplateService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    public void startUp(ProcessFormVo processFormVo) {
    
    
        SysUser sysUser = sysUserService.getById(LoginUserInfoHelper.getUserId());

        ProcessTemplate processTemplate = processTemplateService.getById(processFormVo.getProcessTemplateId());
        Process process = new Process();
        BeanUtils.copyProperties(processFormVo, process);
        String workNo = System.currentTimeMillis() + "";
        process.setProcessCode(workNo);
        process.setUserId(LoginUserInfoHelper.getUserId());
        process.setFormValues(processFormVo.getFormValues());
        process.setTitle(sysUser.getName() + "发起" + processTemplate.getName() + "申请");
        process.setStatus(1);
        processMapper.insert(process);

        //绑定业务id
        String businessKey = String.valueOf(process.getId());
        //流程参数
        Map<String, Object> variables = new HashMap<>();
        //将表单数据放入流程实例中
        JSONObject jsonObject = JSON.parseObject(process.getFormValues());
        JSONObject formData = jsonObject.getJSONObject("formData");
        Map<String, Object> map = new HashMap<>();
        //循环转换
        for (Map.Entry<String, Object> entry : formData.entrySet()) {
    
    
            map.put(entry.getKey(), entry.getValue());
        }
        variables.put("data", map);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processTemplate.getProcessDefinitionKey(), businessKey, variables);
        //业务表关联当前流程实例id
        String processInstanceId = processInstance.getId();
        process.setProcessInstanceId(processInstanceId);

        //计算下一个审批人,可能有多个(并行审批)
        List<Task> taskList = this.getCurrentTaskList(processInstanceId);
        if (!CollectionUtils.isEmpty(taskList)) {
    
    
            List<String> assigneeList = new ArrayList<>();
            for(Task task : taskList) {
    
    
                SysUser user = sysUserService.getByUsername(task.getAssignee());
                assigneeList.add(user.getName());

                //推送消息给下一个审批人,后续完善
            }
            process.setDescription("等待" + StringUtils.join(assigneeList.toArray(), ",") + "审批");
        }
        processMapper.updateById(process);
    }

    /**
     * 获取当前任务列表
     * @param processInstanceId
     * @return
     */
    private List<Task> getCurrentTaskList(String processInstanceId) {
    
    
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        return tasks;
    }
2.3.4, Controller-Schnittstelle
@Autowired
private ProcessService processService;

@ApiOperation(value = "启动流程")
@PostMapping("/startUp")
public Result start(@RequestBody ProcessFormVo processFormVo) {
    
    
   processService.startUp(processFormVo);
   return Result.ok();
}

2.4. Aktualisieren Sie die Front-End-Übermittlungsschnittstelle

1. API-Schnittstelle hinzufügen

startUp(processFormVo) {
    
    
  return request({
    
    
    url: `${
      
      api_name}/startUp`,
    method: 'post',
    data: processFormVo
  })
},

2. Übermittlungsschnittstelle aktualisieren

onSubmit(formData) {
    
    
  ...
  console.log(processFormVo)
  api.startUp(processFormVo).then(response => {
    
    
    //调整到已发起列表
    this.$router.push({
    
     path: "/list/2" });
  });
}

2.5. Einreichungsdatensatz aufzeichnen

Daten, die den folgenden ähneln

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-u7xkdxAn-1688013713658)(assets/1671585994063.png)]

Wir müssen das Betriebsverhalten jedes Knotens aufzeichnen

2.5.1, Mapper-Klasse
package com.atguigu.process.mapper;

import com.atguigu.model.process.ProcessRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface ProcessRecordMapper extends BaseMapper<ProcessRecord> {
    
    

}
2.5.2, Serviceschnittstelle
package com.atguigu.process.service;

import com.atguigu.model.process.ProcessRecord;
import com.baomidou.mybatisplus.extension.service.IService;

public interface ProcessRecordService extends IService<ProcessRecord> {
    
    

    void record(Long processId, Integer status, String description);

}
2.5.3, Serviceschnittstelle
package com.atguigu.process.service.impl;

import com.atguigu.model.process.ProcessRecord;
import com.atguigu.model.system.SysUser;
import com.atguigu.process.mapper.ProcessRecordMapper;
import com.atguigu.process.service.ProcessRecordService;
import com.atguigu.security.custom.LoginUserInfoHelper;
import com.atguigu.system.service.SysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@SuppressWarnings({
    
    "unchecked", "rawtypes"})
public class ProcessRecordServiceImpl extends ServiceImpl<ProcessRecordMapper, ProcessRecord> implements ProcessRecordService {
    
    

   @Autowired
   private ProcessRecordMapper processRecordMapper;

   @Autowired
   private SysUserService sysUserService;

   @Override
   public void record(Long processId, Integer status, String description) {
    
    
      SysUser sysUser = sysUserService.getById(LoginUserInfoHelper.getUserId());
      ProcessRecord processRecord = new ProcessRecord();
      processRecord.setProcessId(processId);
      processRecord.setStatus(status);
      processRecord.setDescription(description);
      processRecord.setOperateUserId(sysUser.getId());
      processRecord.setOperateUser(sysUser.getName());
      processRecordMapper.insert(processRecord);
   }

}
2.5.4. Ändern Sie die Startprozessschnittstelle
@Autowired
private ProcessRecordService processRecordService;

public void startUp(ProcessFormVo processFormVo) {
    
    
    ...

    //记录操作行为
    processRecordService.record(process.getId(), 1, "发起申请");
}

3. Ausstehende Liste

Nach dem Starten des Prozesses kann der Genehmiger die Genehmigungsliste in der Liste „Ausstehend“ abrufen

3.1. Serverschnittstelle

3.1.1. Schnittstelle definieren
IPage<ProcessVo> findPending(Page<Process> pageParam);
3.1.2. Schnittstellenimplementierung
@Override
public IPage<ProcessVo> findPending(Page<Process> pageParam) {
    
    
    // 根据当前人的ID查询
    TaskQuery query = taskService.createTaskQuery().taskAssignee(LoginUserInfoHelper.getUsername()).orderByTaskCreateTime().desc();
    List<Task> list = query.listPage((int) ((pageParam.getCurrent() - 1) * pageParam.getSize()), (int) pageParam.getSize());
    long totalCount = query.count();

    List<ProcessVo> processList = new ArrayList<>();
    // 根据流程的业务ID查询实体并关联
    for (Task item : list) {
    
    
        String processInstanceId = item.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
    
    
            continue;
        }
        // 业务key
        String businessKey = processInstance.getBusinessKey();
        if (businessKey == null) {
    
    
            continue;
        }
        Process process = this.getById(Long.parseLong(businessKey));
        ProcessVo processVo = new ProcessVo();
        BeanUtils.copyProperties(process, processVo);
        processVo.setTaskId(item.getId());
        processList.add(processVo);
    }
    IPage<ProcessVo> page = new Page<ProcessVo>(pageParam.getCurrent(), pageParam.getSize(), totalCount);
    page.setRecords(processList);
    return page;
}
3.1.3, Controller-Schnittstelle
@ApiOperation(value = "待处理")
@GetMapping("/findPending/{page}/{limit}")
public Result findPending(
      @ApiParam(name = "page", value = "当前页码", required = true)
      @PathVariable Long page,

      @ApiParam(name = "limit", value = "每页记录数", required = true)
      @PathVariable Long limit) {
    
    
   Page<Process> pageParam = new Page<>(page, limit);
   return Result.ok(processService.findPending(pageParam));
}

3.2. Front-End-Rendering

3.2.1. Definieren Sie die API-Schnittstelle

Fügen Sie eine Schnittstelle in src/api/process.js hinzu

findPending(page, limit) {
    
    
    return request({
    
    
      url: `${
      
      api_name}/findPending/`+page+`/`+ limit,
      method: 'get'
    })
  }
3.2.2. Route hinzufügen

Fügen Sie Routing in src/router/index.js hinzu

Die Liste verfügt über drei Registerkartenschalter. activeIndex stellt die Sequenznummer des Schalters dar: 0: Genehmigung ausstehend, 1: genehmigt, 2: eingeleitet

{
    
    
    path: '/list/:activeIndex',
    name: '审批列表',
    component: () =>
      import('../views/list.vue'),
  },
3.2.3, Seitenrendering

Erstellen Sie src/views/list.vue

<template>
  <div class="container">
    <van-nav-bar
      title="审批列表"
    />
    <van-tabs v-model="activeIndex" @click="tabSwitch">
      <van-tab
        v-for="(item,key) in tabList"
        :key="key"
        :title="item.title"
      >
      </van-tab>
    </van-tabs>

    <div class="list-wrap" >
      <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
      <van-list
        v-model="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
        :immediate-check="false"
      >
        <van-cell v-for="item in list" :key="item.id" @click="info(item.id, item.taskId)">
          <template slot="default">
            <div class="item-wrap">
              <div class="item-header">
                <img src="https://static.dingtalk.com/media/lALOnahFD80CgM0CgA_640_640.png_450x10000q90.jpg" alt="">
                <h3>{
   
   {item.title}}</h3>
                <span>{
   
   {item.createTime}}</span>
              </div>
              <div class="item-block">
                <p v-for="(value,key) in item.formValues.formShowData" v-if="key !== '图片'">{
   
   { key }}:<span v-html="value"></span></p>
              </div>
              <div class="item-status">
                <span :class="item.status === 1 ? '审批中' : item.status === 2 ? 'pass' : 'refused'">{
   
   { item.status === 1 ? '审批中' : item.status === 2 ? '审批通过' : '审批拒绝' }}</span>
              </div>
            </div>
          </template>
        </van-cell>
      </van-list>
      </van-pull-refresh>
    </div>
  </div>
</template>

<script>
import api from '@/api/process'
export default {
  name: "process",

  data() {
    return {
      list: [],
      loading: false,
      finished: false,
      refreshing: false,

      pageNo: 1,
      pageSize: 10,
      pages: 1,

      activeIndex: 0,
      tabList: [
        { title:"待处理", },
        { title:"已处理", },
        { title:"已发起", }
      ]
    };
  },

  created(){
    this.activeIndex = parseInt(this.$route.params.activeIndex);
    this.onLoad()
  },

  methods: {
    tabSwitch() {
      //tab切换,重新初始化数据
      this.list = []
      this.pageNo = 1
      this.finished = false

      //tabs切换时,如果之前的tab已经滚动到底部(list加载到底部),直接点击其他的tab,将再触发一次onload事件。
      //可能调用2次onLoad()方法,延迟执行,通过时间差解决问题
      setTimeout(() => {
        if(!this.finished) {
          this.onLoad();
        }
      }, 500);
    },

    onLoad() {
      if(this.activeIndex === 0) {
        this.findPending()
      }
      if(this.activeIndex === 1) {
        this.findProcessed()
      }
      if(this.activeIndex === 2) {
        this.findStarted()
      }
    },

    onRefresh() {
      // 清空列表数据
      this.finished = false;

      this.pageNo = 1;
      // 重新加载数据
      // 将 loading 设置为 true,表示处于加载状态
      this.loading = true;
      this.onLoad();
    },

    findPending() {
      console.log(this.pageNo)
      api.findPending(this.pageNo, this.pageSize).then(response => {
        console.log(response.data);
        if (this.refreshing) {
          this.list = [];
          this.refreshing = false;
        }
        for (let i=0;i<response.data.records.length;i++) {
          let item = response.data.records[i]
          item.formValues = JSON.parse(item.formValues)
          this.list.push(item);
        }
        this.pages = response.data.pages;

        this.loading = false;
        if(this.pageNo >= this.pages) {
          this.finished = true;
        }

        this.pageNo++;
      });
    },

    findProcessed() {
      
    },

    findStarted() {
      
    },

    info(id, taskId) {
      this.$router.push({ path: '/show/'+id+'/'+taskId })
    }
  }
}
</script>

<style lang="scss" scoped>
/deep/ .van-nav-bar {
  background: #1D1E20;
}
/deep/ .van-nav-bar__title {
  color: #fff;
}
.container {
  padding-bottom: 50px;
  .list-wrap {
    margin-top: 4px;
    border-top: 1px solid #ebedf0;
  }
  .item-wrap {
    font-size: 12px;
    color: #A7A8A9;
    .item-header {
      display: flex;
      align-items: center;
      img {
        width: 20px;
        height: 20px;
        border-radius: 4px;
        margin-right: 4px;
      }
      h3 {
        flex: 1;
        font-size: 15px;
        color: #000;
        padding: 0;
        margin: 0;
      }

    }

    .item-block {
      padding: 4px 0;
      font-size: 14px;
      p {
        padding: 0;
        margin: 0;
        line-height: 20px;
      }
    }
    .item-status {
      .pass {
        color: #4CB971;
      }
      .refused {
        color: #EB8473;
      }
    }
  }
}
</style>
3.2.4. Testen

Fügen Sie hier eine Bildbeschreibung ein

Derzeit ist es vom Abteilungsleiter genehmigt. Wechseln Sie den Token zum Konto des Abteilungsleiters und sehen Sie sich die ausstehende Genehmigung an

Um das Testen zu erleichtern, erstellen wir eine Seite zum Kontowechsel

1. Routing hinzufügen

{
    
    
  path: '/test',
  name: '切换测试账号',
  component: () =>
    import('../views/test.vue'),
}

2. Erstellen Sie eine neue Vue-Seite

Neue Ansichten/test.vue

Beschreibung: Das Token ist möglicherweise abgelaufen und kann einmalig dynamisch über die Klasse JwtHelper.java generiert werden

<template>
  <div>
    <div>账号切换</div>
    <button @click="wjl()" type="default" size="mini">王经理</button>
    <button @click="rsjl()" type="default" size="mini">李人事经理</button>
    <button @click="zzjl()" type="default" size="mini">张总经理</button>
    <button @click="lisi()" type="default" size="mini">李四</button>
    <div>当前token:{
   
   { token }}</div>
  </div>
</template>

<script>
export default {
  name: "Test",

  data() {
    return {
      token: ''
    };
  },

  created(){

  },

  methods: {
    wjl() {
      window.localStorage.setItem('token', '');
      let token = 'eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAKtWKi5NUrJScgwN8dANDXYNUtJRSq0oULIyNDM3tDA3NTQ311EqLU4t8kxRsjKCMPMSc1OBWrIy89JzMoHqofznfd3Pd_c_n9CmVAsAgwZGsFYAAAA.H9lJkVALwz35h4BN1TNCAh1FttynUkIcsSdDJr46sA8O7pHtDZLA2TCNlTiPFI5ifYJ3nEyPdQnlqq1KM_dR3A'
      window.localStorage.setItem('token', token);
      this.token = window.localStorage.getItem('token')
    },

    rsjl() {
      window.localStorage.setItem('token', '');
      let token = 'eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAKtWKi5NUrJScgwN8dANDXYNUtJRSq0oULIyNDM3tDA3NTIz11EqLU4t8kxRsjKGMPMSc1OBWoqKs3KAqqG8Z3P7nuza9WRX9_Pd_c8ntCnVAgAxtvYPWgAAAA.za6RgrrHFBfBFudpawIwHB4EfKloakef0CEmXwITPFpaS7LC2RJ7a2uFw4MwA9FlQS_YTm2xSPmDBI_zDUOQbQ'
      window.localStorage.setItem('token', token);
      this.token = window.localStorage.getItem('token')
    },

    zzjl() {
      window.localStorage.setItem('token', '');
      let token = 'eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAKtWKi5NUrJScgwN8dANDXYNUtJRSq0oULIyNDM3tDA3NTYy1VEqLU4t8kxRsoIy8xJzU4FaqrJygIqhnKd7Fjxr2P18d__zCW1KtQAR8Ch1VgAAAA.szrvYa3nJprMhVjLGcGZ1mptv0Q5nQDOu81l4CtvtMXtEzsSuEUrf3sHL8v9jJF30Iq2qUXUMQYBgD5kYapd_A'
      window.localStorage.setItem('token', token);
      this.token = window.localStorage.getItem('token')
    },

    lisi() {
      window.localStorage.setItem('token', '');
      let token = 'eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAKtWKi5NUrJScgwN8dANDXYNUtJRSq0oULIyNDM3NjA1M7M001EqLU4t8kxRsjKBMPMSc1OBWnIyizOVagG7ronSQQAAAA.Tw_w8JwifsxxQQVPQWTfTiJb3AL8xA2v9DcfZrqxm8R0Lgy3qAA9Sf5NPcVpFsdwip7gWdX31qwzUf10LAnM2w'
      window.localStorage.setItem('token', token);
      this.token = window.localStorage.getItem('token')
    }
  }
}
</script>

3. Zugriffstest

http://localhost:9090/#/test

Wer in Zukunft eine Genehmigung benötigt, wechselt einfach auf diese Seite

4. Einzelheiten zur Genehmigung

Die Genehmigung gliedert sich in 2 Teile:

1. Einzelheiten zur Genehmigung

​ 2. Ausführung der Genehmigung: Genehmigung und Genehmigungsfehler (Prozess direkt beenden)

4.1. Schnittstelle für Genehmigungsdetails

4.1.1, Serviceschnittstelle
Map<String, Object> show(Long id);
4.1.2. Implementierung der Serviceschnittstelle
@Override
public Map<String, Object> show(Long id) {
    
    
    Process process = this.getById(id);
    List<ProcessRecord> processRecordList = processRecordService.list(new LambdaQueryWrapper<ProcessRecord>().eq(ProcessRecord::getProcessId, id));
    ProcessTemplate processTemplate = processTemplateService.getById(process.getProcessTemplateId());
    Map<String, Object> map = new HashMap<>();
    map.put("process", process);
    map.put("processRecordList", processRecordList);
    map.put("processTemplate", processTemplate);
    //计算当前用户是否可以审批,能够查看详情的用户不是都能审批,审批后也不能重复审批
    boolean isApprove = false;
    List<Task> taskList = this.getCurrentTaskList(process.getProcessInstanceId());
    if (!CollectionUtils.isEmpty(taskList)) {
    
    
        for(Task task : taskList) {
    
    
           if(task.getAssignee().equals(LoginUserInfoHelper.getUsername())) {
    
    
               isApprove = true;
           }
        }
    }
    map.put("isApprove", isApprove);
    return map;
}
4.1.3, Controller-Schnittstelle
@ApiOperation(value = "获取审批详情")
@GetMapping("show/{id}")
public Result show(@PathVariable Long id) {
    
    
   return Result.ok(processService.show(id));
}

4.2. Front-End-Rendering

4.2.1. Definieren Sie die API-Schnittstelle

Fügen Sie eine Schnittstelle in src/api/process.js hinzu

show(id) {
    
    
    return request({
    
    
      url: `${
      
      api_name}/show/`+id,
      method: 'get'
    })
  },
4.2.2. Routing hinzufügen

Fügen Sie Routing in src/router/index.js hinzu

Beim Ausführen von Aufgaben wird die aktuelle Aufgaben-ID verwendet: taskId

{
    
    
    path: '/show/:id/:taskId',
    name: '审批详情',
    component: () =>
      import('../views/show.vue'),
  },
4.2.3, Seitenrendering

Erstellen Sie src/views/show.vue

<template>
  <div class="container">
    <van-nav-bar
      title="审批详情"
      left-text="返回"
      left-arrow
      @click-left="() => $router.back()"
    />
    <van-list>
      <van-cell>
        <template slot="default">
          <div class="header-warp">
            <h4>{
   
   { process.title }}</h4>
            <p>{
   
   { process.createTime }}</p>
            <span class="pass" v-if="process.status === 1">审批中</span>
            <div class="seal-wrap" v-if="process.status === 2">
              <seal-avatar></seal-avatar>
            </div>
            <div class="seal-wrap" v-if="process.status === -1">
              <seal-avatar title="已拒绝" color="#EB8473"></seal-avatar>
            </div>
          </div>
        </template>
      </van-cell>
      <van-cell>
        <template slot="default">
          <div class="detail-wrap">
            <div class="item" v-for="(value,key) in formValues.formShowData">
              <h5>{
   
   { key }}</h5>
              <p v-html="value"></p>
            </div>
          </div>
        </template>
      </van-cell>

      <van-cell>
        <template slot="default">
          <div class="result">
            <h3>流程</h3>
            <van-steps direction="vertical" :active="processRecordList.length - 1">
              <van-step v-for="item in processRecordList">
                <h4>{
   
   { item.operateUser }} {
   
   { item.description }}</h4>
                <p>{
   
   { item.createTime }}</p>
              </van-step>
            </van-steps>

          </div>
        </template>
      </van-cell>
    </van-list>

    <div class="notice" v-if="isApprove">
      <van-icon name="bullhorn-o" />
      <p>{
   
   { process.title }}</p>
      <span class="pass">{
   
   { process.status === 1 ? '审批中' : process.status === 2 ? '审批通过' : '审批拒绝' }}</span>
    </div>

    <div class="footer" v-if="taskId != 0">
      <div class="left-action">
        <div class="action back" @click="() => $router.back()">
          <van-icon name="revoke" />
          <span>返回</span>
        </div>
      </div>
      <div class="right-button">
        <van-button @click="approve(-1)" type="default" size="small">审批拒绝</van-button>
        <span style="margin: 0 4px"></span>
        <van-button @click="approve(1)" type="info" size="small">审批通过</van-button>
      </div>
    </div>
  </div>
</template>

<script>
import SealAvatar from '../components/Seal.vue';
import api from '@/api/process'
export default {
  name: "process",

  components: {
    SealAvatar,
  },
  props: {
    msg: String
  },

  data() {
    return {
      taskId: 0,
      process: { },
      formValues: {},
      processRecordList: [],
      isApprove: false
    };
  },

  created(){
    this.taskId = this.$route.params.taskId;
    let id = this.$route.params.id;
    this.fetchData(id);
  },

  methods: {
    fetchData(id) {
      api.show(id).then(response => {
        this.process = response.data.process
        this.formValues = JSON.parse(this.process.formValues)
        this.processRecordList = response.data.processRecordList
        this.isApprove = response.data.isApprove
      })
    },

    approve(status) {
      
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  padding-bottom: 86px;
  .header-warp {
    position: relative;
    h4 {
      font-size: 16px;
      margin: 5px;
    }
    p {
      font-size: 16px;
      margin: 5px;
    }
    .pass {
      color: #4CB971;
      margin: 5px;
    }
    .refused {
      color: #EB8473;
      margin: 5px;
    }
  }
  .detail-wrap {
    .item {
      h5 {
        color: #838485;
        margin: 5px;
      }
      p {
        color: #1B1F22;
        font-size: 16px;
        margin: 5px;
      }
    }
  }
  .result {
    font-size: 14px;
    h4, p {
      margin: 5px;
      font-size: 14px;
    }
  }
  .seal-wrap {
    position: absolute;
    top: 20px;
    right: 30px;
  }

  .notice {
    display: flex;
    align-items: center;
    width: 100%;
    font-size: 12px;
    padding: 8px 10px;
    background: #FEFBE8;
    position: fixed;
    bottom: 53px;
    z-index: 10;
    p {
      flex: 1;
      margin: 4px;
    }
    .pass {
      color: #07c160;
      margin-right: 20px;
    }
  }
  .footer {
    // height: 50px;
    padding: 10px;
    background: #F8F8F8;
    display: flex;
    align-items: center;
    position: fixed;
    width: 100%;
    bottom: 0;
    z-index: 10;
    .left-action {
      flex: 1;
      .action {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;

        span {
          font-size: 12px;
          color: #838485;
        }
      }
    }

    .right-button {
      margin-right: 20px;
    }
  }
}

/deep/ .van-cell {
  position: inherit;
  overflow: visible;
}

/deep/ .van-cell__value{
  position: inherit;
  overflow: visible;
}
</style>

5. Genehmigung

5.1. Genehmigungsschnittstelle

5.1.1, Serviceschnittstelle
void approve(ApprovalVo approvalVo);
5.1.2. Implementierung der Serviceschnittstelle

Wenn die Genehmigung nicht bestanden wird, beenden Sie den Prozess direkt (Hinweis: Der parallele Genehmigungsprozess kann nicht erfüllt werden und unser Unternehmen erfordert derzeit keine parallele Verarbeitung.)

public void approve(ApprovalVo approvalVo) {
    
    
    Map<String, Object> variables1 = taskService.getVariables(approvalVo.getTaskId());
    for (Map.Entry<String, Object> entry : variables1.entrySet()) {
    
    
        System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
    }
    String taskId = approvalVo.getTaskId();
    if (approvalVo.getStatus() == 1) {
    
    
        //已通过
        Map<String, Object> variables = new HashMap<String, Object>();
        taskService.complete(taskId, variables);
    } else {
    
    
        //驳回
        this.endTask(taskId);
    }
    String description = approvalVo.getStatus().intValue() == 1 ? "已通过" : "驳回";
    processRecordService.record(approvalVo.getProcessId(), approvalVo.getStatus(), description);

    //计算下一个审批人
    Process process = this.getById(approvalVo.getProcessId());
    List<Task> taskList = this.getCurrentTaskList(process.getProcessInstanceId());
    if (!CollectionUtils.isEmpty(taskList)) {
    
    
        List<String> assigneeList = new ArrayList<>();
        for(Task task : taskList) {
    
    
            SysUser sysUser = sysUserService.getByUsername(task.getAssignee());
            assigneeList.add(sysUser.getName());

            //推送消息给下一个审批人
        }
        process.setDescription("等待" + StringUtils.join(assigneeList.toArray(), ",") + "审批");
        process.setStatus(1);
    } else {
    
    
        if(approvalVo.getStatus().intValue() == 1) {
    
    
            process.setDescription("审批完成(同意)");
            process.setStatus(2);
        } else {
    
    
            process.setDescription("审批完成(拒绝)");
            process.setStatus(-1);
        }
    }
    //推送消息给申请人
    this.updateById(process);
}

private void endTask(String taskId) {
    
    
    //  当前任务
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

    BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
    List endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);
    // 并行任务可能为null
    if(CollectionUtils.isEmpty(endEventList)) {
    
    
        return;
    }
    FlowNode endFlowNode = (FlowNode) endEventList.get(0);
    FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());

    //  临时保存当前活动的原始方向
    List originalSequenceFlowList = new ArrayList<>();
    originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
    //  清理活动方向
    currentFlowNode.getOutgoingFlows().clear();

    //  建立新方向
    SequenceFlow newSequenceFlow = new SequenceFlow();
    newSequenceFlow.setId("newSequenceFlowId");
    newSequenceFlow.setSourceFlowElement(currentFlowNode);
    newSequenceFlow.setTargetFlowElement(endFlowNode);
    List newSequenceFlowList = new ArrayList<>();
    newSequenceFlowList.add(newSequenceFlow);
    //  当前节点指向新的方向
    currentFlowNode.setOutgoingFlows(newSequenceFlowList);

    //  完成当前任务
    taskService.complete(task.getId());
}
5.1.3, Controller-Schnittstelle
@ApiOperation(value = "审批")
@PostMapping("approve")
public Result approve(@RequestBody ApprovalVo approvalVo) {
    
    
   processService.approve(approvalVo);
   return Result.ok();
}

5.2. Front-End-Implementierung

5.2.1. Definieren Sie die API-Schnittstelle

Fügen Sie eine Schnittstelle in src/api/process.js hinzu

approve(approvalVo) {
    
    
    return request({
    
    
      url: `${
      
      api_name}/approve`,
      method: 'post',
      data: approvalVo
    })
  },
5.2.2, Seitenverarbeitung

Ergänzen Sie die Seitengenehmigungsfunktion src/views/show.vue

approve(status) {
    
    
  let approvalVo = {
    
    
    processId: this.process.id,
    taskId: this.taskId,
    status: status
  }
  api.approve(approvalVo).then(response => {
    
    
    this.$router.push({
    
     path: '/list/1' })
  })
}

Fügen Sie hier eine Bildbeschreibung ein

6. Verarbeitet

Fügen Sie hier eine Bildbeschreibung ein

6.1. Verarbeitete Schnittstelle

6.1.1, Serviceschnittstelle
IPage<ProcessVo> findProcessed(Page<Process> pageParam);
6.1.2. Implementierung der Serviceschnittstelle
@Autowired
private HistoryService historyService;

@Override
public IPage<ProcessVo> findProcessed(Page<Process> pageParam) {
    
    
    // 根据当前人的ID查询
    HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().taskAssignee(LoginUserInfoHelper.getUsername()).finished().orderByTaskCreateTime().desc();
    List<HistoricTaskInstance> list = query.listPage((int) ((pageParam.getCurrent() - 1) * pageParam.getSize()), (int) pageParam.getSize());
    long totalCount = query.count();

    List<ProcessVo> processList = new ArrayList<>();
    for (HistoricTaskInstance item : list) {
    
    
        String processInstanceId = item.getProcessInstanceId();
        Process process = this.getOne(new LambdaQueryWrapper<Process>().eq(Process::getProcessInstanceId, processInstanceId));
        ProcessVo processVo = new ProcessVo();
        BeanUtils.copyProperties(process, processVo);
        processVo.setTaskId("0");
        processList.add(processVo);
    }
    IPage<ProcessVo> page = new Page<ProcessVo>(pageParam.getCurrent(), pageParam.getSize(), totalCount);
    page.setRecords(processList);
    return page;
}
6.1.3, Controller-Schnittstelle
@ApiOperation(value = "已处理")
@GetMapping("/findProcessed/{page}/{limit}")
public Result findProcessed(
      @ApiParam(name = "page", value = "当前页码", required = true)
      @PathVariable Long page,
      @ApiParam(name = "limit", value = "每页记录数", required = true)
      @PathVariable Long limit) {
    
    
   Page<Process> pageParam = new Page<>(page, limit);
   return Result.ok(processService.findProcessed(pageParam));
}

6.2. Front-End-Implementierung

6.2.1. Definieren Sie die API-Schnittstelle

Fügen Sie eine Schnittstelle in src/api/process.js hinzu

findProcessed(page, limit) {
    
    
    return request({
    
    
      url: `${
      
      api_name}/findProcessed/`+page+`/`+ limit,
      method: 'get'
    })
  },
6.2.2, Seitenverarbeitung

Fügen Sie die Seitenmethode src/views/list.vue hinzu

findProcessed() {
    
    
  console.log(this.pageNo)
  api.findProcessed(this.pageNo, this.pageSize).then(response => {
    
    
    console.log(response.data);
    if (this.refreshing) {
    
    
      this.list = [];
      this.refreshing = false;
    }
    for (let i=0;i<response.data.records.length;i++) {
    
    
      let item = response.data.records[i]
      item.formValues = JSON.parse(item.formValues)
      this.list.push(item);
    }
    this.pages = response.data.pages;

    this.loading = false;
    if(this.pageNo >= this.pages) {
    
    
      this.finished = true;
    }

    this.pageNo++;
  });
},

7. Initiiert

7.1. Initiierte Schnittstelle

7.1.1, Serviceschnittstelle
IPage<ProcessVo> findStarted(Page<ProcessVo> pageParam);
7.1.2. Implementierung der Serviceschnittstelle
@Override
    public IPage<ProcessVo> findStarted(Page<ProcessVo> pageParam) {
    
    
        ProcessQueryVo processQueryVo = new ProcessQueryVo();
        processQueryVo.setUserId(LoginUserInfoHelper.getUserId());
        IPage<ProcessVo> page = processMapper.selectPage(pageParam, processQueryVo);
        for (ProcessVo item : page.getRecords()) {
    
    
            item.setTaskId("0");
        }
        return page;
    }
7.1.3, Controller-Schnittstelle
@ApiOperation(value = "已发起")
@GetMapping("/findStarted/{page}/{limit}")
public Result findStarted(
      @ApiParam(name = "page", value = "当前页码", required = true)
      @PathVariable Long page,

      @ApiParam(name = "limit", value = "每页记录数", required = true)
      @PathVariable Long limit) {
    
    
   Page<ProcessVo> pageParam = new Page<>(page, limit);
   return Result.ok(processService.findStarted(pageParam));
}

7.2. Front-End-Implementierung

7.2.1. Definieren Sie die API-Schnittstelle

Fügen Sie eine Schnittstelle in src/api/process.js hinzu

findStarted(page, limit) {
    
    
    return request({
    
    
      url: `${
      
      api_name}/findStarted/`+page+`/`+ limit,
      method: 'get'
    })
  },
7.2.2, Seitenverarbeitung

Fügen Sie die Seitenmethode src/views/list.vue hinzu

findStarted() {
    
    
  console.log(this.pageNo)
  api.findStarted(this.pageNo, this.pageSize).then(response => {
    
    
    console.log(response.data);
    if (this.refreshing) {
    
    
      this.list = [];
      this.refreshing = false;
    }
    for (let i=0;i<response.data.records.length;i++) {
    
    
      let item = response.data.records[i]
      item.formValues = JSON.parse(item.formValues)
      this.list.push(item);
    }
    this.pages = response.data.pages;

    this.loading = false;
    if(this.pageNo >= this.pages) {
    
    
      this.finished = true;
    }

    this.pageNo++;
  });
},

[Externer Link zur Bildübertragung ist fehlgeschlagen. Die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-LKV1kJsI-1688013713661) (E:\Typora\images\typora-user-images\image-20230625194152479.png)]

for (let i = 0; i < response.data.records.length; i++) {
  let item = response.data.records[i];
  try {
    item.formValues = JSON.parse(item.formValues);
    this.list.push(item);
  } catch (error) {
    console.error("JSON 解析错误: " + error);
    console.log("无法解析的 JSON 字符串: " + item.formValues);
  }
}

[Externer Link zur Bildübertragung ist fehlgeschlagen. Die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-yI6pTuvR-1688013713663) (E:\Typora\images\typora-user-images\image-20230625194212064.png)]

Drei, meine Güte

1. Grundlegende Informationen

1.1. Grundlegende Informationsschnittstelle

1.1.1, Serviceschnittstelle

Operationsklasse: SysUserService

Map<String, Object> getCurrentUser();
1.1.2, Implementierung der Serviceschnittstelle

Operationsklasse: SysUserServiceImpl

@Autowired
private SysDeptService sysDeptService;

@Autowired
private SysPostService sysPostService;

@Override
	public Map<String, Object> getCurrentUser() {
    
    
		SysUser sysUser = sysUserMapper.selectById(LoginUserInfoHelper.getUserId());
		//SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
		//SysPost sysPost = sysPostService.getById(sysUser.getPostId());
		Map<String, Object> map = new HashMap<>();
		map.put("name", sysUser.getName());
		map.put("phone", sysUser.getPhone());
		//map.put("deptName", sysDept.getName());
		//map.put("postName", sysPost.getName());
		return map;
	}
1.1.3, Controller-Schnittstelle

Operationsklasse: SysUserController

@ApiOperation(value = "获取当前用户基本信息")
@GetMapping("getCurrentUser")
public Result getCurrentUser() {
    
    
    return Result.ok(sysUserService.getCurrentUser());
}

1.2. Front-End-Implementierung

1.2.1. Definieren Sie die API-Schnittstelle

Erstellen Sie src/api/userInfo.js

import request from '@/utils/request'

export default {
    
    

  getCurrentUser() {
    
    
    return request({
    
    
      url: `/admin/system/sysUser/getCurrentUser/`,
      method: 'get'
    })
  },
}
2.2.2. Routing hinzufügen

Fügen Sie Routing in src/router/index.js hinzu

{
    
    
  path: '/user',
  name: '基本信息',
  component: () =>
    import('../views/user.vue'),
},
2.2.4, Seitenrealisierung

Erstellen Sie src/views/user.vue

<template>
  <div class="container">
    <van-nav-bar
      title="基本信息"
    />
    <div class="detail-wrap">
      <div class="item">
        <h5>用户姓名:{
    
    {
    
     user.name }}</h5>
      </div>
      <div class="item">
        <h5>手机号:{
    
    {
    
     user.phone }}</h5>
      </div>
      <div class="item">
        <h5>所在部门:{
    
    {
    
     user.deptName }}</h5>
      </div>
      <div class="item">
        <h5>岗位:{
    
    {
    
     user.postName }}</h5>
      </div>
    </div>

  </div>
</template>

<script>
import api from '@/api/userInfo'
export default {
    
    
  name: "process",

  data() {
    
    
    return {
    
    
      user: {
    
     }
    };
  },

  created(){
    
    
    this.fetchData();
  },

  methods: {
    
    
    fetchData() {
    
    
      // debugger
      api.getCurrentUser().then(response => {
    
    
        this.user = response.data
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
    
    
  padding: 20px;

  .detail-wrap {
    
    
    .item {
    
    
      h5 {
    
    
        color: #838485;
        margin: 10px;
      }

      p {
    
    
        color: #1B1F22;
        margin: 0;
      }
    }
  }
}
</style>

2. Über uns

2.1. Routing hinzufügen

Fügen Sie Routing in src/router/index.js hinzu

{
    
    
  path: '/about',
  name: '关于我们',
  component: () =>
    import('../views/about.vue'),
},

2.2. Seite hinzufügen

<template>
  <div class="container">
    <van-nav-bar
      title="关于我们"
    />
    <div class="detail-wrap">
      <div class="item">
        云尚办公
      </div>
    </div>

  </div>
</template>

<script>
export default {
    
    
  name: "process",

  data() {
    
    
    return {
    
    
    };
  },

  created(){
    
    
  },

  methods: {
    
    
  
  }
}
</script>

<style lang="scss" scoped>
.container {
    
    
  padding: 20px;
  .detail-wrap {
    
    
    .item {
    
    
      color: #838485;
    }
  }
}
</style>

Supongo que te gusta

Origin blog.csdn.net/AN_NI_112/article/details/131454082
Recomendado
Clasificación