芋道框架审批流如何实现(Cloud+Vue3)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
性能测试 PTS,5000VUM额度
简介: 芋道框架审批流如何实现(Cloud+Vue3)

 审批流的其实就是提交之后发送给你的上级然后让他进行批阅,再进行反馈。实际上的就是发送、接收、改变状态、再发送的一个过程。

芋道框架帮我们集成了这个功能,下面就让我来带大家做一个简易版的审批流。

首先:数据库准备一定要有这四个字段 image.gif 编辑

后端:

实体类:

DO类:

/**
     * 导入批次号
     */
    private String importBatch;
    /**
     * 录入批次号
     */
    private String subBatchNo;
    /**
     * 状态
     */
    private Long status;
    private String processInstanceId;

image.gif

SaveReqVO类:

@Schema(description = "录入批次号", example = "9103")
    private String subBatchNo;
    @Schema(description = "导入批次号", example = "9103")
    private String importBatch;
    @Schema(description = "状态", example = "9103")
    private Long status;
    private String processInstanceId;

image.gif

RespVO类:

private String subBatchNo;
    private Long status;
    private String processInstanceId;

image.gif

提交审核的方法

Service:

 

void examine(List<TbQyyrYrzyjpljlbRespVO> examineReqVO);

image.gif

实现类:

public static final String PROCESS_KEY = "carbon-yr-jcdjpl";
    public static final String prefix = "yr-b-";
    @Resource
    private BpmUtil bpmUtil;
   @Override
    public void examine(List<TbQyyrYrzyjpljlbRespVO> examineReqVO) {
        // 生成提交批次号
        String submitBatchNo = NumberGenerate.generateNumber(prefix);
        // 发送到审批流程
        String processInstanceId = bpmUtil.submitToBpm(submitBatchNo, PROCESS_KEY);
        for(TbQyyrYrzyjpljlbRespVO tbQyyrYrzyjpljlbRespVO : examineReqVO){
            TbQyyrYrzyjpljlbDO updateObj = BeanUtils.toBean(tbQyyrYrzyjpljlbRespVO, TbQyyrYrzyjpljlbDO.class);
            // 每条数据保存提交批次号
            updateObj.setSubBatchNo(submitBatchNo);
            // 每天数据保存审批流 processInstanceId
            updateObj.setProcessInstanceId(processInstanceId);
            updateObj.setStatus(2L);
            tbQyyrYrzyjpljlbMapper.updateById(updateObj);
        }
    }

image.gif

记住这里的PROCESS_KEY和prefix,后面有用,这是唯一的标识。

Controller:

@PostMapping("/examine")
    @Operation(summary = "线缆原材料生产数据采集审核")
    public CommonResult<Boolean> examine(@RequestBody List<TbQyyrYrzyjpljlbRespVO>  examineReqVO ) {
        tbQyyrYrzyjpljlbService.examine(examineReqVO);
        return success(true);
    }

image.gif

generateNumber方法:

package com.todod.carbon.framework.common.util.common;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
public class NumberGenerate {
    public static String generateNumber(String prefix) {
        // 使用当前时间作为随机数生成器的种子
        Random random = new Random(System.currentTimeMillis());
        // 生成一个0到9999之间的随机数
        int randomNumber = random.nextInt(10000);
        String batchNo = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+randomNumber;
        return prefix + batchNo;
    }
}

image.gif

该方法用于生成提交的批次号。

提交方法写完后我们回到页面的工作流程去做一个审批流

image.gif 编辑

image.gif 编辑

这里的流程标识需要和我们定义的PROCESS_KEY是一样的。

image.gif 编辑

按照这个流程,创建之后我们先去修改流程补全信息

image.gif 编辑

这里的表单查看地址对应了一个只能查看的页面用于审批的时候能够看到审批的信息

点击设计流程

image.gif 编辑

按照这样配置,画一个流程审批图

点击保存模型后发布

image.gif 编辑

接下来我们写一个改变状态的方法:

service:

void setStatus(String subNo,Integer status);

image.gif

实现类:

@Override
    public void setStatus(String id, Integer bpmStatus) {
        List<TbQyyrYrzyjpljlbDO> yrzyjpljlbDOS = tbQyyrYrzyjpljlbMapper.selectBpmList(id);
        if (yrzyjpljlbDOS != null && yrzyjpljlbDOS.size()>0){
            yrzyjpljlbDOS.forEach(item->{
                item.setStatus(Long.parseLong(bpmStatus.toString()));
                tbQyyrYrzyjpljlbMapper.updateById(item);
            });
        }
        if (bpmStatus == 3){
            //执行kettle
//            kettleUtils.runKTR(kettleFileName);
        }
    }

image.gif

selectBpmList方法:


default List<TbQyyrYrzyjpljlbDO> selectBpmList (String processInstanceId){
        return selectList(new LambdaQueryWrapperX<TbQyyrYrzyjpljlbDO>()
                .eq(TbQyyrYrzyjpljlbDO::getProcessInstanceId,processInstanceId)
        );
    }

image.gif

这个方法会根据返回的审批id去查找符合条件的数据集合,也就是同一时间审批的那一批数据。

改变状态的方法就写好了,接下来我们去Bpm模块写一个监听方法。

image.gif 编辑

在这里写一个监听类,层级是这样的,大家不要写错了。

package com.todod.carbon.module.bpm.service.oa.listener;
import com.todod.carbon.module.bpm.event.BpmProcessInstanceStatusEvent;
import com.todod.carbon.module.bpm.event.BpmProcessInstanceStatusEventListener;
import com.todod.carbon.module.system.api.user.AdminUserApi;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
@Component
public class YrZyJplListener extends BpmProcessInstanceStatusEventListener {
    public static final String PROCESS_KEY = "carbon-yr-jcdjpl";
    @Resource
    private AdminUserApi adminUserApi;
    @Override
    protected String getProcessDefinitionKey() {
        return PROCESS_KEY;
    }
    @Override
    protected void onEvent(BpmProcessInstanceStatusEvent event) {
        String id = event.getId();
        adminUserApi.setCommonStatus(id,event.getStatus(),"yr-b");
    }
}

image.gif

这里依旧要保证PROCESS_KEY和prefix一致。

这是我自己写的一个改变状态的rpc,大家可以自己写一个,我相信并不难,我放这大家可以参考。

@GetMapping(PREFIX + "/bpmCommonStatus")
    @Operation(summary = "工作流状态")
    @Parameters({
            @Parameter(name = "id", description = "订单id", example = "1", required = true),
            @Parameter(name = "bpmStatus", description = "工作流状态", example = "3", required = true),
            @Parameter(name = "type", description = "对应的工作表", example = "3", required = true)
    })
    void setCommonStatus(@RequestParam("id")String id, @RequestParam("status")Integer status, @RequestParam("type")String type);

image.gif

@Override
    public void setStatus(Long id, Integer bpmStatus) {
        switch (bpmStatus) {
            case 2://通过
                break;
            case 3://未通过
                break;
            case 4://撤回、取消 审批
                break;
        }
    }
    @Override
    public void setCommonStatus(String id, Integer bpmStatus, String type) {
        switch (bpmStatus) {
            case 2://通过
                bpmStatus = 3;
                break;
            case 3://未通过
                bpmStatus = 4;
                break;
            case 4://撤回、取消 审批
                bpmStatus = 1;
                break;
        }
        switch (type){
            //产品信息
            case "xl-a":
                tbXlcpCpxxService.setStatus(id,bpmStatus);
            //原材料生产
            case "xl-b":
                tbXlcpYclscjdService.setStatus(id,bpmStatus);
            //原材料运输
            case "xl-c":
                tbXlcpYclysjdService.setStatus(id,bpmStatus);
            //产品生产
            case "xl-d":
                tbXlcpCpscjdService.setStatus(id,bpmStatus);
            //产品运输
            case "xl-e":
                tbXlcpCpysjdService.setStatus(id,bpmStatus);
            //产品运输
            case "xl-f":
                tbXlcpCpsyjdService.setStatus(id,bpmStatus);
            //产品回收
            case "xl-g":
                tbXlcpCphsjdService.setStatus(id,bpmStatus);
            //楼宇电表
            case "ly-a":
                lyntglAmmeterInfoService.setStatus(id,bpmStatus);
            //楼宇水表
            case "ly-b":
                lyntglWaterinfoService.setStatus(id,bpmStatus);
           //楼宇天然气
            case "ly-c":
                lyntglTrqInfoService.setStatus(id,bpmStatus);
           //楼宇市政热力
            case "ly-d":
                lyntglSzrlInfoService.setStatus(id,bpmStatus);
           //楼宇可再生能源
            case "ly-e":
                lyntglKzsnyInfoService.setStatus(id,bpmStatus);
           //工业园区
            case "gyyq-a":
                tbGyyqGyyqcjService.setStatus(id,bpmStatus);
           //余热-监测点
            case "yr-a":
                tbQyyrJcdbService.setStatus(id,bpmStatus);
            default:
                break;
        }
    }

image.gif

前端:

大家可以那前端做个参考,我就把完整代码放到这里了。

<template>
  <ContentWrap>
    <!-- 搜索工作栏 -->
    <el-form
      class="-mb-15px"
      :model="queryParams"
      ref="queryFormRef"
      :inline="true"
      label-width="130px"
    >
      <el-form-item label="企业名称" prop="ttbQyyrQyname">
        <el-input
          v-model="queryParams.ttbQyyrQyname"
          placeholder="请输入企业名称"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="余热标识" prop="ttbQyyrYrbs">
        <el-input
          v-model="queryParams.ttbQyyrYrbs"
          placeholder="请输入余热标识"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="余热资源类型" prop="ttbQyyrYrzylx">
        <el-input
          v-model="queryParams.ttbQyyrYrzylx"
          placeholder="请输入余热资源类型"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="填报日期" prop="ttbTbDate">
        <el-date-picker
          v-model="queryParams.ttbTbDate"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="daterange"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="创建时间" prop="createTime">
        <el-date-picker
          v-model="queryParams.createTime"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="daterange"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
        <el-button
          type="primary"
          plain
          @click="openForm('create')"
          v-hasPermi="['system:tb-qyyr-yrzyjpljlb:create']"
        >
          <Icon icon="ep:plus" class="mr-5px" /> 新增
        </el-button>
        <el-button
          type="warning"
          plain
          @click="handleImport"
        >
          <Icon icon="ep:upload" /> 导入
        </el-button>
        <el-button
          type="success"
          plain
          @click="handleExport"
          :loading="exportLoading"
          v-hasPermi="['system:tb-qyyr-yrzyjpljlb:export']"
        >
          <Icon icon="ep:download" class="mr-5px" /> 导出
        </el-button>
        <el-button  type="primary" plain @click="examine">
          提交审核
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>
  <!-- 列表 -->
  <ContentWrap>
    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange">
      <el-table-column
        label="序号"
        type="index"
        header-align="center"
        align="center"
        width="60px"
        fixed
      />
      <el-table-column type="selection" :selectable="selectable" width="55" />
      <el-table-column label="企业名称" align="center" prop="ttbQyyrQyname" />
      <el-table-column label="余热标识" align="center" prop="ttbQyyrYrbs" />
      <el-table-column label="余热资源类型" align="center" prop="ttbQyyrYrzylx" width="120px"/>
      <el-table-column label="余热资源等级" align="center" prop="ttbQyyrYrzydj" width="120px"/>
      <el-table-column label="可回收余热资源量" align="center" prop="ttbQyyrKhsyrzyl" width="140px"/>
      <el-table-column label="余热资源回收率" align="center" prop="ttbQyyrYrzyhsl" width="140px"/>
      <el-table-column label="余热资源减排量" align="center" prop="ttbQyyrYrzyjpl" width="140px"/>
      <el-table-column label="余热资源回收总量" align="center" prop="ttbQyyrYrzyhszl" width="140px"/>
      <el-table-column label="备注" align="center" prop="ttbQyyrBz" />
      <el-table-column
        label="填报日期"
        align="center"
        prop="createTime"
        :formatter="dateFormatter2"
        width="180px"
      />
      <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        :formatter="dateFormatter"
        width="180px"
      />
      <el-table-column label="操作" align="center" width="200px">
        <template #default="scope">
          <el-tag type="primary" v-if = "scope.row.status ==1" >草稿  </el-tag>
          <el-tag type="success" v-if = "scope.row.status ==3" >审批通过</el-tag>
          <el-tag type="danger" v-if = "scope.row.status ==4" >审批驳回</el-tag>
          <el-tag type="warning" v-if = "scope.row.status ==2" >审批中</el-tag>
          <el-button
            link
            type="primary"
            @click="openForm('update', scope.row.id)"
            v-if = "scope.row.status ==1 || scope.row.status ==4"
          >
            编辑
          </el-button>
          <el-button
            link
            type="danger"
            @click="handleDelete(scope.row.id)"
            v-if = "scope.row.status ==1 || scope.row.status ==4"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <Pagination
      :total="total"
      v-model:page="queryParams.pageNo"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />
  </ContentWrap>
  <!-- 表单弹窗:添加/修改 -->
  <TbQyyrYrzyjpljlbForm ref="formRef" @success="getList" />
   <!-- 对象导入对话框 -->
   <ImportForm ref="importFormRef" @success="getList" />
  <Examine ref="examineFormRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter,dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { TbQyyrYrzyjpljlbApi, TbQyyrYrzyjpljlbVO } from '@/api/system/tbqyyryrzyjpljlb'
import TbQyyrYrzyjpljlbForm from './TbQyyrYrzyjpljlbForm.vue'
import TbQyyrJcdbForm from './TbQyyrJcdbForm.vue'
import { getIntDictOptions, DICT_TYPE, getDictLabel } from '@/utils/dict'
import Examine from './examine.vue'
import ImportForm from './ImportForm.vue'
/** 余热资源减排量记录 列表 */
defineOptions({ name: 'TbQyyrYrzyjpljlb' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref<TbQyyrYrzyjpljlbVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  ttbQyyrQyname: undefined,
  ttbQyyrYrbs: undefined,
  ttbQyyrYrzylx: undefined,
  ttbQyyrYrzydj: undefined,
  ttbQyyrKhsyrzyl: undefined,
  ttbQyyrYrzyhsl: undefined,
  ttbQyyrYrzyjpl: undefined,
  ttbQyyrYrzyhszl: undefined,
  ttbQyyrBz: undefined,
  ttbTbDate: [],
  createTime: [],
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await TbQyyrYrzyjpljlbApi.getTbQyyrYrzyjpljlbPage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}
/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
  formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await TbQyyrYrzyjpljlbApi.deleteTbQyyrYrzyjpljlb(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
  try {
    // 导出的二次确认
    await message.exportConfirm()
    // 发起导出
    exportLoading.value = true
    const data = await TbQyyrYrzyjpljlbApi.exportTbQyyrYrzyjpljlb(queryParams)
    download.excel(data, '余热资源减排量记录.xls')
  } catch {
  } finally {
    exportLoading.value = false
  }
}
const importFormRef = ref()
const handleImport = () => {
  importFormRef.value.open()
}
const selectList = ref<TbQyyrYrzyjpljlbVO[]>([])
const handleSelectionChange = (val: TbQyyrYrzyjpljlbVO[]) => {
  selectList.value = val
}
const examineFormRef = ref()
const examine =() => {
    if(selectList.value.length > 0)
    {
      examineFormRef.value.open(selectList.value)
    }else{
      message.warning('请选择审核的数据')
    }
}
const selectable = (row: TbQyyrYrzyjpljlbVO) => ![2,3].includes(row.status)
/** 初始化 **/
onMounted(() => {
  getList()
})
</script>

image.gif

examine提交页:

<template>
  <Dialog title="提交审核" v-model="dialogVisible" width="60%">
    <el-table :data="selectList2"  >
      <el-table-column
        label="序号"
        type="index"
        header-align="center"
        align="center"
        width="60px"
        fixed
      />
      <el-table-column label="企业名称" align="center" prop="ttbQyyrQyname" />
      <el-table-column label="余热标识" align="center" prop="ttbQyyrYrbs" />
      <el-table-column label="余热资源类型" align="center" prop="ttbQyyrYrzylx" width="120px"/>
      <el-table-column label="余热资源等级" align="center" prop="ttbQyyrYrzydj" width="120px"/>
      <el-table-column label="可回收余热资源量" align="center" prop="ttbQyyrKhsyrzyl" width="140px"/>
      <el-table-column label="余热资源回收率" align="center" prop="ttbQyyrYrzyhsl" width="140px"/>
      <el-table-column label="余热资源减排量" align="center" prop="ttbQyyrYrzyjpl" width="140px"/>
      <el-table-column label="余热资源回收总量" align="center" prop="ttbQyyrYrzyhszl" width="140px"/>
      <el-table-column label="备注" align="center" prop="ttbQyyrBz" />
      <el-table-column
        label="填报日期"
        align="center"
        prop="createTime"
        :formatter="dateFormatter2"
        width="180px"
      />
      <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        :formatter="dateFormatter"
        width="180px"
      />
      <el-table-column fixed="right" label="操作" align="center" width="120">
            <template #default="scope">
              <el-button
                @click.prevent="deleteRow(scope.$index, selectList2)"
                type="text"
                size="small"
              >
                删除
              </el-button>
            </template>
          </el-table-column>
  </el-table>
  <template #footer>
      <el-button @click="examine" type="primary" >提交审核</el-button>
      <el-button @click="closeDialong">取 消</el-button>
    </template> 
    </Dialog>
</template>
<script lang="ts" setup>
import { dateFormatter,dateFormatter2 } from '@/utils/formatTime'
import { getIntDictOptions, DICT_TYPE, getDictLabel } from '@/utils/dict'
import { TbQyyrYrzyjpljlbApi, TbQyyrYrzyjpljlbVO } from '@/api/system/tbqyyryrzyjpljlb'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const selectList2 = ref<TbQyyrYrzyjpljlbVO[]>([])
/** 打开弹窗 */
const open = async ( selectList: TbQyyrYrzyjpljlbVO[]) => {
  dialogVisible.value = true
  selectList2.value = []
  selectList2.value = selectList
}
const deleteRow = (index, rows) => {
  rows.splice(index, 1)
}
const examine = async () => {
    if(selectList2.value.length > 0)
    {
      await message.confirm( t('你确定要提交审核吗?'))
        await TbQyyrYrzyjpljlbApi.examine(selectList2.value)
        message.success('已提交审核,静等相关人员处理')
        emit('success')
        dialogVisible.value = false
    }else{
      message.warning('请选择审核的数据')
    }
}
const closeDialong = () => {
  dialogVisible.value = false
  emit('success')
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
</script>

image.gif

现在让我们试一下能不能审核成功

image.gif 编辑

选中后提交审核

image.gif 编辑

提交审核成功,状态变为已审核

image.gif 编辑

同时在待办任务里面能看见这一条提交审核记录

image.gif 编辑

点击审批

image.gif 编辑

通过之后,状态变为已通过

image.gif 编辑

这就大功告成了,如果有什么问题,可以和我交流,我的微信是:sxy0802000,谢谢大家浏览。


目录
相关文章
|
4天前
|
弹性计算 双11 开发者
阿里云ECS“99套餐”再升级!双11一站式满足全年算力需求
11月1日,阿里云弹性计算ECS双11活动全面开启,在延续火爆的云服务器“99套餐”外,CPU、GPU及容器等算力产品均迎来了全年最低价。同时,阿里云全新推出简捷版控制台ECS Lite及专属宝塔面板,大幅降低企业和开发者使用ECS云服务器门槛。
|
21天前
|
存储 弹性计算 人工智能
阿里云弹性计算_通用计算专场精华概览 | 2024云栖大会回顾
阿里云弹性计算产品线、存储产品线产品负责人Alex Chen(陈起鲲)及团队内多位专家,和中国电子技术标准化研究院云计算标准负责人陈行、北京望石智慧科技有限公司首席架构师王晓满两位嘉宾,一同带来了题为《通用计算新品发布与行业实践》的专场Session。本次专场内容包括阿里云弹性计算全新发布的产品家族、阿里云第 9 代 ECS 企业级实例、CIPU 2.0技术解读、E-HPC+超算融合、倚天云原生算力解析等内容,并发布了国内首个云超算国家标准。
阿里云弹性计算_通用计算专场精华概览 | 2024云栖大会回顾
|
3天前
|
人工智能 弹性计算 文字识别
基于阿里云文档智能和RAG快速构建企业"第二大脑"
在数字化转型的背景下,企业面临海量文档管理的挑战。传统的文档管理方式效率低下,难以满足业务需求。阿里云推出的文档智能(Document Mind)与检索增强生成(RAG)技术,通过自动化解析和智能检索,极大地提升了文档管理的效率和信息利用的价值。本文介绍了如何利用阿里云的解决方案,快速构建企业专属的“第二大脑”,助力企业在竞争中占据优势。
|
1天前
|
人工智能 自然语言处理 安全
创新不设限,灵码赋新能:通义灵码新功能深度评测
自从2023年通义灵码发布以来,这款基于阿里云通义大模型的AI编码助手迅速成为开发者心中的“明星产品”。它不仅为个人开发者提供强大支持,还帮助企业团队提升研发效率,推动软件开发行业的创新发展。本文将深入探讨通义灵码最新版本的三大新功能:@workspace、@terminal 和 #team docs,分享这些功能如何在实际工作中提高效率的具体案例。
|
8天前
|
负载均衡 算法 网络安全
阿里云WoSign SSL证书申请指南_沃通SSL技术文档
阿里云平台WoSign品牌SSL证书是由阿里云合作伙伴沃通CA提供,上线阿里云平台以来,成为阿里云平台热销的国产品牌证书产品,用户在阿里云平台https://www.aliyun.com/product/cas 可直接下单购买WoSign SSL证书,快捷部署到阿里云产品中。
1851 6
阿里云WoSign SSL证书申请指南_沃通SSL技术文档
|
11天前
|
Web App开发 算法 安全
什么是阿里云WoSign SSL证书?_沃通SSL技术文档
WoSign品牌SSL证书由阿里云平台SSL证书合作伙伴沃通CA提供,上线阿里云平台以来,成为阿里云平台热销的国产品牌证书产品。
1791 2
|
20天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
26天前
|
存储 人工智能 缓存
AI助理直击要害,从繁复中提炼精华——使用CDN加速访问OSS存储的图片
本案例介绍如何利用AI助理快速实现OSS存储的图片接入CDN,以加速图片访问。通过AI助理提炼关键操作步骤,避免在复杂文档中寻找解决方案。主要步骤包括开通CDN、添加加速域名、配置CNAME等。实测显示,接入CDN后图片加载时间显著缩短,验证了加速效果。此方法大幅提高了操作效率,降低了学习成本。
5390 15
|
14天前
|
人工智能 关系型数据库 Serverless
1024,致开发者们——希望和你一起用技术人独有的方式,庆祝你的主场
阿里云开发者社区推出“1024·云上见”程序员节专题活动,包括云上实操、开发者测评和征文三个分会场,提供14个实操活动、3个解决方案、3 个产品方案的测评及征文比赛,旨在帮助开发者提升技能、分享经验,共筑技术梦想。
1151 152
|
21天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1585 14