vue3-实战-08-管理后台-SPU模块开发

news2025/2/6 17:30:05

目录

1-列表页面开发

1.1-列表页面需求原型分析

1.2-接口封装和数据类型定义

1.3-组件获取数据

1.4-页面组件动态渲染数据

2-添加修改SPU

2.1-原型需求分析

2.2-接口封装和数据类型定义

2.3-请求服务器获取数据

2.4-收集表单数据提交数据

3-添加SKU

3.1-原型及需求分析

3.2-请求接口和数据类型封装

3.3-组件页面渲染数据和收集数据

 3.4-整理数据提交数据

4-查看sku列表

5-删除spu

6-组件销毁


1-列表页面开发

1.1-列表页面需求原型分析

       列表页面结构和上一个章节 属性管理列表页面结构类似。这里稍微复杂点,操作那边多了两个功能-添加SKU和查看SKU列表;下部分的card结构,需要在添加SPU和添加SKU之间来回切换,所以需要一个变量场景值来控制显示和隐藏。我们可以将添加SPU和添加SKU封装为两个单独的组件。

1.2-接口封装和数据类型定义

我们根据接口文档,定义服务端接口封装和数据结构的定义。
文件:src\api\product\spu\index.ts中定义请求接口相关

import request from '@/utils/request'
import type {HasSpuResponseData} from './type'
enum API {
  //获取已有的SPU的数据
  HASSPU_URL = '/admin/product/',
}
//获取某一个三级分类下已有的SPU数据
export const reqHasSpu = (
  page: number,
  limit: number,
  category3Id: string | number,
) =>
  request.get<any, HasSpuResponseData>(
    API.HASSPU_URL + `${page}/${limit}?category3Id=${category3Id}`,
  )

文件src\api\product\spu\type.ts定义请求响应数据相关

1.3-组件获取数据

       在组件中,我们需要向服务器发送请求获取相关数据,并且需要定义变量接受服务器返回的数据。我们知道,当我们选中了三级分类的时候,我们需求想服务器发送请求获取数据,此时我们需要监听三级分类的id,如果三级分类的id不为空,我们就发送请求获取列表数据。

文件:src\views\product\spu\index.vue中发送请求,获取数据。

 

 

1.4-页面组件动态渲染数据

当我们获取到服务器的数据之后,我们需要在页面动态渲染服务器返回的数据。 

 el-table-column中描述description使用了show-overflow-tooltip属性,当内容过长被隐藏时显示 tooltip

2-添加修改SPU

2.1-原型需求分析

分析一下页面结构,首先上面的三级分类,需要disabled;然后添加SPU组件整体是一个el-form表单组件。有输入框input,还有下拉的,上传图片的,里面还有一个el-table的table组件。我们需要想服务器调用四个接口:
1-获取SPU品牌列表数据用于下拉;
2-获取某一个已有的SPU下全部商品的图片地址(编辑的时候使用)
3-获取某一个已有的SPU拥有多少个销售属性(编辑的时候使用)
4-获取全部的销售属性

2.2-接口封装和数据类型定义

我们整理好新增或者编辑页面需要调用4个接口获取数据。

文件:src\api\product\spu\index.ts 定义请求的接口;

//SPU管理模块的接口
import request from '@/utils/request'
import type {
  AllTradeMark,
  SpuHasImg,
  SaleAttrResponseData,
  HasSaleAttrResponseData,
} from './type'
enum API {
  //获取全部品牌的数据
  ALLTRADEMARK_URL = '/admin/product/baseTrademark/getTrademarkList',
  //获取某个SPU下的全部的售卖商品的图片数据
  IMAGE_URL = '/admin/product/spuImageList/',
  //获取某一个SPU下全部的已有的销售属性接口地址
  SPUHASSALEATTR_URL = '/admin/product/spuSaleAttrList/',
  //获取整个项目全部的销售属性[颜色、版本、尺码]
  ALLSALEATTR_URL = '/admin/product/baseSaleAttrList',
 
}

//获取全部的SPU的品牌的数据
export const reqAllTradeMark = () =>
  request.get<any, AllTradeMark>(API.ALLTRADEMARK_URL)
//获取某一个已有的SPU下全部商品的图片地址
export const reqSpuImageList = (spuId: number) =>
  request.get<any, SpuHasImg>(API.IMAGE_URL + spuId)
//获取某一个已有的SPU拥有多少个销售属性
export const reqSpuHasSaleAttr = (spuId: number) =>
  request.get<any, SaleAttrResponseData>(API.SPUHASSALEATTR_URL + spuId)
//获取全部的销售属性
export const reqAllSaleAttr = () =>
  request.get<any, HasSaleAttrResponseData>(API.ALLSALEATTR_URL)

文件:src\api\product\spu\type.ts定义数据类型【全部数据类型,下面的功能不再贴出来

//服务器全部接口返回的数据类型
export interface ResponseData {
  code: number
  message: string
  ok: boolean
}

//SPU数据的ts类型:需要修改
export interface SpuData {
  category3Id: string | number
  id?: number
  spuName: string
  tmId: number | string
  description: string
  spuImageList: null | SpuImg[]
  spuSaleAttrList: null | SaleAttr[]
}
//数组:元素都是已有SPU数据类型
export type Records = SpuData[]
//定义获取已有的SPU接口返回的数据ts类型
export interface HasSpuResponseData extends ResponseData {
  data: {
    records: Records
    total: number
    size: number
    current: number
    searchCount: boolean
    pages: number
  }
}

//品牌数据的TS类型
export interface Trademark {
  id: number
  tmName: string
  logoUrl: string
}
//品牌接口返回的数据ts类型
export interface AllTradeMark extends ResponseData {
  data: Trademark[]
}

//商品图片的ts类型
export interface SpuImg {
  id?: number
  imgName?: string
  imgUrl?: string
  createTime?: string
  updateTime?: string
  spuId?: number
  name?: string
  url?: string
}
//已有的SPU的照片墙数据的类型
export interface SpuHasImg extends ResponseData {
  data: SpuImg[]
}

//已有的销售属性值对象ts类型
export interface SaleAttrValue {
  id?: number
  createTime?: null
  updateTime?: null
  spuId?: number
  baseSaleAttrId: number | string
  saleAttrValueName: string
  saleAttrName?: string
  isChecked?: null
}
//存储已有的销售属性值数组类型
export type SpuSaleAttrValueList = SaleAttrValue[]

//销售属性对象ts类型
export interface SaleAttr {
  id?: number
  createTime?: null
  updateTime?: null
  spuId?: number
  baseSaleAttrId: number | string
  saleAttrName: string
  spuSaleAttrValueList: SpuSaleAttrValueList
  flag?: boolean
  saleAttrValue?: string
}
//SPU已有的销售属性接口返回数据ts类型
export interface SaleAttrResponseData extends ResponseData {
  data: SaleAttr[]
}

//已有的全部SPU的返回数据ts类型
export interface HasSaleAttr {
  id: number
  name: string
}

export interface HasSaleAttrResponseData extends ResponseData {
  data: HasSaleAttr[]
}

export interface Attr {
  attrId: number | string //平台属性的ID
  valueId: number | string //属性值的ID
}

export interface saleArr {
  saleAttrId: number | string //属性ID
  saleAttrValueId: number | string //属性值的ID
}
export interface SkuData {
  category3Id: string | number //三级分类的ID
  spuId: string | number //已有的SPU的ID
  tmId: string | number //SPU品牌的ID
  skuName: string //sku名字
  price: string | number //sku价格
  weight: string | number //sku重量
  skuDesc: string //sku的描述
  skuAttrValueList?: Attr[]
  skuSaleAttrValueList?: saleArr[]
  skuDefaultImg: string //sku图片地址
}

//获取SKU数据接口的ts类型
export interface SkuInfoData extends ResponseData {
  data: SkuData[]
}

2.3-请求服务器获取数据

       当我们点击添加SPU或者编辑的时候,我们需要在组件加载的时候获取到服务器的数据。当我们获取到数据的时候,我们需要使用接受数据,存储数据。

 

spuForm组件对外暴露,否则父组件spu不能调用

 

点击添加SPU按钮

 

 点击编辑按钮

 

 

2.4-收集表单数据提交数据

       我们获取到相关的服务端数据,我们还需要收集用户输入其他的表单数据,进行数据整理,提交给服务器。

定义收集数据的对象

//存储已有的SPU对象
let SpuParams = ref<SpuData>({
    category3Id: "",//收集三级分类的ID
    spuName: "",//SPU的名字
    description: "",//SPU的描述
    tmId: '',//品牌的ID
    spuImageList: [],
    spuSaleAttrList: [],
});

每个数据项收集分析:
1-spu名称:输入框,直接v-model收集数据就行;
2-spu品牌:下拉列表循环展示品牌列表信息,直接v-model收集数据品牌id,通过el-option的value属性就可收集;
3-SPU描述:输入框,直接v-model收集数据就行;

 
4-SPU图片:重难点-参考element-plus的照片墙demo代码(照片对象里面的key 必须叫name 和 url)



添加spu的时候:图片列表是为空的,当我们上传成功后,图片上传成功信息就收集在 属性 v-model:file-list="imgList"  里面的imgList里面;

在提交的时候,我们需要整理数据,循环遍历imgList,获取里面的元素,拼装接口需要的数据结构。

编辑SPU的时候:我们需要调用接口获取spu的图片信息,因为要展示图片,我们必须返回el-upload组件需要的数据key(name,url

el-upload组件中还定义了on-preview 点击预览图片,on-remove 点击删除图片,before-upload 上传之前对图片做一些校验;

let dialogVisible = ref<boolean>(false);//控制图片预览对话框的显示与隐藏

//照片墙点击预览按钮的时候触发的钩子
const handlePictureCardPreview = (file: any) => {
    dialogImageUrl.value = file.url;
    //对话框弹出来
    dialogVisible.value = true;
}
//照片墙删除文件钩子
const handleRemove = () => {
    //目前不需要做任何处理
    console.log(123);
}
//照片墙上传成功之前的钩子约束文件的大小与类型
const handlerUpload = (file: any) => {
    if (file.type == 'image/png' || file.type == 'image/jpeg' || file.type == 'image/gif') {
        if (file.size / 1024 / 1024 < 3) {
            return true;
        } else {
            ElMessage({type: 'error',message: '上传文件务必小于3M'})
            return false;
        }
    } else {
        ElMessage({type: 'error',message: '上传文件务必PNG|JPG|GIF'})
        return false;
    }
}


5-SPU销售属性:重难点
       这里先要计算当前spu没有选择的销售属性列表unSelectSaleAttr。对于添加SPU,没有选择的销售属性列表就是系统接口返回的全部数据;对于编辑来说,先需要调用获取当前spu已有的销售属性列表saleAttr,然后用全部的数据列表allSaleAttr排除掉之前已经选择平台销售属性。

//计算出当前SPU还未拥有的销售属性
let unSelectSaleAttr = computed(() => {
    //全部销售属性:颜色、版本、尺码;现在已经有颜色和版本,返回结果是尺码
    let unSelectArr = allSaleAttr.value.filter(item => {
        return saleAttr.value.every(item1 => {
            return item.name != item1.saleAttrName;
        });
    })
    return unSelectArr;
})

 

 这里收集的时候,将平台销售属性的id和属性值名称一起收集。

我们可以看到这个table里面销售属性值有tag,input和button(plus)三个组件,首先展示是tag和plus按钮,点击plus按钮,展示input输入框,输入属性值;当表单元素失去焦点的时候,变成tag。需要来回判断展示button还是input输入框,所以我们需要追加一个变量flag来标记。

//表单元素失却焦点的事件回调
const toLook = (row: SaleAttr) => {
    //整理收集的属性的ID与属性值的名字
    const { baseSaleAttrId, saleAttrValue } = row;
    //整理成服务器需要的属性值形式
    let newSaleAttrValue: SaleAttrValue = {
        baseSaleAttrId,
        saleAttrValueName: (saleAttrValue as string)
    }

    //非法情况判断
    if ((saleAttrValue as string).trim() == '') {
        ElMessage({type: 'error',message: '属性值不能为空的'})
        return;
    }
    //判断属性值是否在数组当中存在
    let repeat = row.spuSaleAttrValueList.find(item => {
        return item.saleAttrValueName == saleAttrValue;
    })

    if (repeat) {
        ElMessage({type: 'error',message: '属性值重复'})
        return;
    }
    row.spuSaleAttrValueList.push(newSaleAttrValue);//追加新的属性值对象   
    row.flag = false;//切换为查看模式
}

当我们点击添加销售属性的时候,我们需要向响应式数据saleAttr数组中push一个对象。

//添加销售属性的方法
const addSaleAttr = () => {
    const [baseSaleAttrId, saleAttrName] = saleAttrIdAndValueName.value.split(':');
    //准备一个新的销售属性对象:将来带给服务器即可
    let newSaleAttr: SaleAttr = {
        baseSaleAttrId,
        saleAttrName,
        spuSaleAttrValueList: []
    }
    //追加到数组当中
    saleAttr.value.push(newSaleAttr);
    //清空收集的数据
    saleAttrIdAndValueName.value = '';

}

点击保存按钮,整理数据,调用服务器接口,提交给服务器。

 我们看到如果没有选择销售属性,保存按钮是disabled的状态。

 父组件文件src\views\product\spu\index.vue,绑定自定义事件。

3-添加SKU

3.1-原型及需求分析

        点击SPU操作的添加sku按钮时,需要进行场景切换,切换到SKU组件。form表单组件,除了一些输入框之外,还需要向服务器 获取平台属性-spu的销售属性-当前spu的图片列表信息。图片的table组件里面还有一个设置默认按钮,将图片设置为当前sku的默认图片。

3.2-请求接口和数据类型封装

数据类型定义上一章节以及全部开发完成,此处就不再贴出来;
文件src\api\product\spu\index.ts定义添加sku接口,内容如下:

//SPU管理模块的接口
import request from '@/utils/request'
import type {
  SkuData
} from './type'
enum API {
  //追加一个新增的SKU地址
  ADDSKU_URL = '/admin/product/saveSkuInfo',

}
export const reqAddSku = (data: SkuData) =>
  request.post<any, any>(API.ADDSKU_URL, data)

3.3-组件页面渲染数据和收集数据

       我们在SKU组件页面挂载完成后,需要向服务器 获取平台属性-spu的销售属性-当前spu的图片列表信息数据,动态渲染在组件页面上。此外我们还需要收集服务器需要的添加sku数据信息,调用添加sku接口,提交给服务器。

 

//获取子组件实例SkuForm
let sku = ref<any>();
//添加SKU按钮的回调
const addSku = (row: SpuData) => {
    //点击添加SKU按钮切换场景为2
    scene.value = 2;
    //调用子组件的方法初始化添加SKU的数据
    sku.value.initSkuData(categoryStore.c1Id, categoryStore.c2Id, row);
}

组件文件:src\views\product\spu\skuForm.vue中定义接受数据和收集数据的响应式对象。

import { reqAttr } from '@/api/product/attr';//引入请求API
import { reqSpuImageList, reqSpuHasSaleAttr, reqAddSku } from '@/api/product/spu';
import type { SkuData } from '@/api/product/spu/type'
import { ElMessage } from 'element-plus';
import { ref, reactive } from 'vue';
let attrArr = ref<any>([]);//平台属性
let saleArr = ref<any>([]);//销售属性
let imgArr = ref<any>([]);//照片的数据
let table = ref<any>();//获取table组件实例
//收集SKU的参数
let skuParams = reactive<SkuData>({
    //父组件传递过来的数据
    category3Id: "",//三级分类的ID
    spuId: "",//已有的SPU的ID
    tmId: "",//SPU品牌的ID
    //v-model收集
    skuName: "",//sku名字
    price: "",//sku价格
    weight: "",//sku重量
    skuDesc: "",//sku的描述

    skuAttrValueList: [//平台属性的收集
    ],
    skuSaleAttrValueList: [//销售属性
    ],
    skuDefaultImg: "",//sku图片地址
})

定义父组件需要调用子组件sku的方法initSkuData,并且需要对外暴露,这样父组件就可以调用。

//对外暴露方法
defineExpose({
    initSkuData
});

收集数据:
1-SKU名称,价格(元),重量(g),SKU描述都是input输入框类型,直接v-model收集数据;
2-平台属性:下拉框类型,在el-select标签中使用v-model收集的是el-option中的value属性的数据。
3-销售属性:同理销售销售的数据收集逻辑和平台属性类似。
4-图片:


 

 3.4-整理数据提交数据

       收集到组件页面的数据后,我们需要对数据进行组装和提交接口需要的数据。首先,我们把设置为默认图片handler方法逻辑先处理一下。

 点击保存按钮逻辑处理:

//保存按钮的方法
const save = async () => {
    //整理参数
    //平台属性
    skuParams.skuAttrValueList = attrArr.value.reduce((prev: any, next: any) => {
        if (next.attrIdAndValueId) {
            let [attrId, valueId] = next.attrIdAndValueId.split(':');
            prev.push({attrId,valueId})
        }
        return prev;
    }, []);
    //销售属性
    skuParams.skuSaleAttrValueList = saleArr.value.reduce((prev: any, next: any) => {
        if (next.saleIdAndValueId) {
            let [saleAttrId, saleAttrValueId] = next.saleIdAndValueId.split(':');
            prev.push({saleAttrId, saleAttrValueId})
        }
        return prev;
    }, []);
    //添加SKU的请求
    let result: any = await reqAddSku(skuParams);
    if (result.code == 200) {
        ElMessage({type: 'success',message: '添加SKU成功'});
        //通知父组件切换场景为零
        $emit('changeScene',{flag:0,params:''})
    } else {
        ElMessage({type: 'error',message: '添加SKU失败'})
    }
}
//自定义事件的方法
let $emit = defineEmits(['changeScene']);

4-查看sku列表

       点击页面的查看sku列表,需要展示当前spu下面的所有sku类别信息。业务逻辑比较简单直接上代码。

//存储全部的SKU数据
let skuArr = ref<SkuData[]>([]);
let show = ref<boolean>(false);

//查看SKU列表的数据
const findSku = async (row: SpuData) => {
    let result: SkuInfoData = await reqSkuList((row.id as number));
    if (result.code == 200) {
        skuArr.value = result.data;
        //对话框显示出来
        show.value = true;
    }
}

5-删除spu

当点击删除spu的按钮的时候,需要弹框提示用户,点击确定 调用后台接口删除spu信息。因为业务逻辑比较简单,直接上代码。

//删除已有的SPU按钮的回调
const deleteSpu = async (row: SpuData) => {
    let result: any = await reqRemoveSpu((row.id as number));
    if (result.code == 200) {
        ElMessage({type: 'success',message: '删除成功'});
        //获取剩余SPU数据
        getHasSpu(records.value.length > 1 ? pageNo.value : pageNo.value - 1)
    } else {
        ElMessage({type: 'error',message: '删除失败'})
    }
}

6-组件销毁

当组件路由销毁的时候,我们需要清除仓库三级分类相关的数据。文件:src\views\product\spu\index.vue中需要添加onBeforeUnmount方法的逻辑。

import { ref, watch, onBeforeUnmount } from 'vue';
//路由组件销毁前,情况仓库关于分类的数据
onBeforeUnmount(() => {
    categoryStore.$reset();
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/641367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言交换两个变量的值,不能使用第三个变量。

今天学习了一个新的方法&#xff0c;感觉有必要记录一下&#xff0c;免得自己忘记。 问题是&#xff1a;交换两个变量的值。不能使用第三个变量。 我们正常的做法是&#xff1a;比如有变量a2&#xff0c;变量b3&#xff0c;我们创建变量c&#xff0c;把a的值放到c里面&#x…

ESXi 7.0 U3m NEC (日电) 定制版 OEM Custom Installer CD

VMware ESXi 7.0 Update 3m - 领先的裸机 Hypervisor (All OEM Customized Installer CDs) ESXi 7.0 U3m Standard (标准版) ESXi 7.0 U3m Dell (戴尔) 定制版 OEM Custom Installer CD ESXi 7.0 U3m HPE (慧与) 定制版 OEM Custom Installer CD ESXi 7.0 U3m Lenovo (联想) 定…

MM32F3273G8P火龙果开发板MindSDK开发教程13 - 获取msa311加速器的运动事件

MM32F3273G8P火龙果开发板MindSDK开发教程13 - 获取msa311加速器的运动事件 1、功能描述 msa311在运动时候&#xff0c;会产生一个中断&#xff0c;此时我们读一下09寄存器的02位&#xff0c;如果为1&#xff0c;那么我们可以断定msa311处在运动状态&#xff0c;但是当msa311…

Guideline 1.2 - Safety - User Generated Content

最近被拒很多次这个理由&#xff1a; 有这样&#xff1a;&#xff08;第一种&#xff1a;&#xff09; Guideline 1.2 - Safety - User Generated Content Your app enables users to post content anonymously but does not have the proper precautions in place. Next Ste…

澳大利亚纽扣电池以及含纽扣电池产品测试标准要求

由于在澳大利亚&#xff0c;已有儿童因为误食纽扣电池而导致死亡&#xff0c;且每月至少有一名儿童因吞咽或插入纽扣/硬币电池而严重受伤&#xff0c;导致其中一些儿童永久性损伤&#xff0c;而全世界数以百万计的消费品中都含有纽扣电池&#xff0c;所以澳大利亚出台含纽扣电池…

如何挑选适合自己的项目管理工具?这些选择技巧可以帮到你

选择一款符合您需求的项目管理软件对任何企业的成功都至关重要。由于可用的项目管理工具数量之多&#xff0c;选择一个最适合团队工作流程的工具可能会让人应接不暇。以下是一些选择正确项目管理软件的技巧&#xff1a; 1.确定业务需求 首先&#xff0c;确定您的业务需求至关重…

笔记本电脑开不了机怎么办?3招快速解决!

我是个笔记本电脑的重度用户&#xff0c;几乎每天都需要用到笔记本电脑&#xff0c;但昨天当我想开机时&#xff0c;我的笔记本电脑一点反应都没有&#xff0c;这我应该怎么办呢&#xff1f; 我们在日常生活中&#xff0c;对笔记本电脑的使用越来越多&#xff0c;它给我们带来了…

基于RBAC实现权限系统

RBAC 一&#xff1a;故事背景二&#xff1a;什么是RBAC&#xff08;Role-Based Access Control&#xff09;2.1 概念2.2 关键构成2.3 RBAC 三个著名原则2.3.1 最小权限2.3.2 责任分类2.3.3 数据抽象 2.4 RBAC 的 5种类型2.5 图体现 三&#xff1a;RBAC的优缺点四&#xff1a;通…

useref和useImperativeHandle

1.函数组件中&#xff0c;还可以基于useRef Hook函数&#xff0c;创建一个ref对象 useRef 是 React 提供的一个 Hook 函数&#xff0c;它可以用来在函数式组件内部保存和访问任何可变值&#xff0c;类似于在类组件中使用 this.setState 来保存数据。不同之处在于&#xff0c;u…

Maven创建Web项目

创建 Web 应用 通过使用 Maven 的 maven-archetype-webapp 模板可以创建一个简单的 Web 应用。 例如&#xff0c;在命令行窗口执行以下命令&#xff0c;Maven 会为我们创建一个 JavaWeb 应用。 mvn archetype:generate -DgroupIdnet.biancheng.www -DartifactIdmavenWeb -Darc…

Unity与原生交互之Unity篇——AndroidStudio导出aar/jar包供Unity使用实现交互全流程(4)

序言:此篇介绍使用AndroidStudio导出aar/jar导入unity过程中的注意点 1.处理aar包 *****重要 重要 重要***** 目的是为了剔除之前导入android工程的unity API,这些api unity已经有了 过程建议拷贝一份aar进行处理 方式一: 处理aar包 1)解压aar 2)…

百度沈抖:大模型 产业智能化时代的新引擎

6月9日&#xff0c;2023 NAVIGATE领航者峰会在杭州举办&#xff0c;聚焦数字经济新政策、新技术、新业态带来的蓬勃机遇&#xff0c;探讨ICT行业在AIGC时代将要面临的全新挑战与应对策略。百度集团执行副总裁、百度智能云事业群总裁沈抖出席大会并作题为《大模型 产业智能化时代…

华为OD机试之用户调度问题(Java源码)

用户调度问题 题目描述 在通信系统中&#xff0c;一个常见的问题是对用户进行不同策略的调度&#xff0c;会得到不同的系统消耗和性能。假设当前有n个待串行调度用户&#xff0c;每个用户可以使用A/B/C三种不同的调度策略&#xff0c;不同的策略会消耗不同的系统资源。请你根据…

AI + 非遗文化主题师资培训落地,飞桨持续赋能AI人才培养

随着数字浪潮袭来&#xff0c;人工智能的发展声势浩大&#xff0c;高校人工智能专业建设以及 AI 的人才培养已经提上日程。如何夯实产教融合&#xff0c;加快人工智能研究创新&#xff0c;培养具备 AI 系统能力的拔尖人才&#xff0c;是推进产业智能化升级的迫切课题。6月2日-4…

2023年国内五大 IoT 物联网平台费用对比

五大物联网平台费用对比 随着物联网发展进入成熟期&#xff0c;越来越多企业选择云厂商提供的物联网PaaS服务&#xff0c;以降低运营成本&#xff0c;缩短业务上线周期&#xff0c;释放运维的人力&#xff0c;按需付费动态扩容。笔者基于各云厂商2023年4月的官网报价&#xff0…

【笑小枫系列】Java加密那点事,本文给你讲的明明白白

本文简介 相信大家在日常工作中都遇到过加密的场景吧&#xff0c;像登录密码加密保存、无token接口验签、数据加密传输等等。 本文将详细的介绍一下加密的方式&#xff0c;并分析使用场景&#xff0c;并会以详细的代码完整的介绍如何使用加密&#xff0c;让小伙伴们遇到加密时…

docker-consul服务发现部署

什么是consul consul是google开源的一个使用go语言开发的服务管理软件。支持多数据中心、分布式高可用的、服务发现和配置共享。采用Raft算法&#xff0c;用来保证服务的高可用。内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案&…

Redis 分布式集群操作

文章目录 连接集群写入数据单个key写入批量key操作 集群查询查询 key 的 slot查询 slot 中 key 的数量查询 slot 中的 key 故障转移Master宕机Master 和 Slave 都宕机 集群扩容1.启动两个节点2.添加 master3.分配slot4.添加 slave 集群缩容1.删除 slave 节点2.移出 master 的 s…

【K8SRockyLinux】基于开源操作系统搭建K8S高可用集群(详细版)

文章目录 一、实验节点规划表&#x1f447;二、实验版本说明&#x1f4c3;三、实验拓扑&#x1f4ca;四、实验详细操作步骤&#x1f579;️1. 安装Rocky Linux开源企业操作系统2. 所有主机系统初始化3. 所有master节点部署keepalived4. 所有master节点部署haproxy5. 所有节点配…

睿智医药×企通启动采购与供应链管理项目,加速医药领域数智采购

随着世界经济发展、人口总量增长、人口老龄化程度提高以及人们保健意识增强&#xff0c;新型国家城市化建设的推进和各国医疗保障体制的不断完善&#xff0c;全球医药市场呈持续增长趋势。在政策、资本、技术等因素催化下&#xff0c;我国生物医药行业研发创新实力稳步增强&…