电商平台spu和sku的完整设计

一、关于数据库表的设计

  • 1、商品属性表

    比如一个衣服有颜色、尺码、款式这个叫属性表

    -- ------------------------
    -- 商品属性表
    -- ------------------------
    DROP TABLE IF EXISTS `attribute`;
    CREATE TABLE `attribute` (`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT  COMMENT '主键id',`name` varchar(50) not null  COMMENT '属性名',`status` tinyint(4) DEFAULT 0 COMMENT '状态,0表示正常,1表示禁用',`remark` varchar(100) default  null comment '备注',`created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',`updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',`deleted_at` timestamp(6) NULL DEFAULT NULL COMMENT '软删除时间',UNIQUE KEY `UK_name_deleted_at` (`name`,`deleted_at`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT = "商品属性表";
    
  • 2、商品属性值表

    上面说的颜色,可能是红色、黄色、绿色,尺码可能是S、M、L

    -- ------------------------
    -- 商品属性值表
    -- ------------------------
    DROP TABLE IF EXISTS `attribute_value`;
    CREATE TABLE `attribute_value` (`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT  COMMENT '主键id',`attribute_id` int(11) not null comment '关联到attribute表主键id',`name` varchar(50) not null  COMMENT '属性值',`status` tinyint(4) DEFAULT 0 COMMENT '状态,0表示正常,1表示禁用',`remark` varchar(100) default  null comment '备注',`created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',`updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',`deleted_at` timestamp(6) NULL DEFAULT NULL COMMENT '软删除时间',UNIQUE KEY `UK_attribute_id_name_deleted_at` (`attribute_id`,`name`,`deleted_at`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT = "商品属性值表";
    
  • 3、spu表,或者直接叫商品表也可以的

    spu表比如我们说的苹果手机、华为手机、戴尔笔记本这样的叫spu

    -- ------------------------
    -- 商品spu表
    -- ------------------------
    DROP TABLE IF EXISTS `spu`;
    CREATE TABLE `spu` (`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT  COMMENT '主键id',`name` varchar(50) not null  COMMENT '商品名称',`keyword` varchar(50) not null  COMMENT '关键词',`introduction` varchar(100) not null  COMMENT '简介',`category_id` int(11) not null  COMMENT '关联到category表主键id',`brand_id` int(11) default null comment  '关联到brand表主键id',`pic_url` varchar(200) default  null comment  '封面图',`video_url` varchar(200) default  null comment  '视频地址',`slider_pic_urls` varchar(500) default null COMMENT '商品轮播图地址',`unit` int(11) default  null comment  '单位,关联到dict表主键id',`spec_type` tinyint(4) default 0 comment '单双规格,0表示单规格,1表示多规格(sku)',`price` decimal(10,2) default '0.00' comment '商品单价',`market_price` decimal(10,2) default '0.00' comment '商品市场价',`discount_price` decimal(10,2) default '0.00' comment '商品折扣价',`vip_price` decimal(10,2) default '0.00' comment '商品vip价',`cost_price` decimal(10,2) default '0.00' comment '商品成本价',`stock` int(11) default 0 comment '库存(如果是多规格求和)',`sort` int(11) DEFAULT 1 COMMENT '排序',`status` tinyint(4) DEFAULT 0 COMMENT '状态,0表示正常,1表示禁用',`is_hot` tinyint(4) DEFAULT 0 COMMENT '是否热销,0表示不是,1表示是',`is_benefit` tinyint(4) DEFAULT 0 COMMENT '是否优惠推荐,0表示不是,1表示是',`is_best` tinyint(4) DEFAULT 0 COMMENT '是否精品,0表示不是,1表示是',`is_new` tinyint(4) DEFAULT 0 COMMENT '是否新品,0表示不是,1表示是',`is_good` tinyint(4) DEFAULT 0 COMMENT '是否优品推荐,0表示不是,1表示是',`give_integral` int(11) DEFAULT 0 COMMENT '赠送积分',`sales_count` int(11) DEFAULT 0 COMMENT '销量',`browse_count` int(11) DEFAULT 0 COMMENT '浏览数',`content` text NOT NULL COMMENT '商品详情',`attribute` varchar(1000) default null COMMENT '销售属性数组,JSON 格式',`remark` varchar(100) default  null comment '备注',`created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',`updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',`deleted_at` timestamp(6) NULL DEFAULT NULL COMMENT '软删除时间',UNIQUE KEY `UK_name_deleted_at` (`name`,`deleted_at`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT = "商品spu表";
    
  • 4、sku

    上面说的苹果手机,可能是【黄色-128GB-大陆版】,【白色-256GB-港版】这样的叫sku

    -- ------------------------
    -- 商品sku表
    -- ------------------------
    DROP TABLE IF EXISTS `sku`;
    CREATE TABLE `sku` (`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT  COMMENT '主键id',`spu_id` int(11) NOT NULL comment '关联到spu主键id',`attribute_value` varchar(200) default null comment '销售属性值:用英文,拼接',`price` decimal(10,2) default '0.00' comment '商品单价',`market_price` decimal(10,2) default '0.00' comment '商品市场价',`discount_price` decimal(10,2) default '0.00' comment '商品折扣价',`vip_price` decimal(10,2) default '0.00' comment '商品vip价',`cost_price` decimal(10,2) default '0.00' comment '商品成本价',`bar_code` varchar(64)  DEFAULT NULL COMMENT 'SKU 的条形码',`pic_url` varchar(200)  NOT NULL COMMENT '图片地址',`stock` int DEFAULT NULL COMMENT '库存',`weight` double DEFAULT NULL COMMENT '商品重量,单位:kg 千克',`volume` double DEFAULT NULL COMMENT '商品体积,单位:m^3 平米',`sales_count` int DEFAULT NULL COMMENT '商品销量',`created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',`updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',`deleted_at` timestamp(6) NULL DEFAULT NULL COMMENT '软删除时间'
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT = "商品sku表";
    

二、前端选择销售属性

  • 1、最后效果图

    在这里插入图片描述

  • 2、上面的数据提前手动插入到数据库中的

在这里插入图片描述


在这里插入图片描述

  • 3、后端提供一个接口先查询全部的商品属性,在根据商品属性的id去查询商品属性值,这块可以自己见代码

三、选择商品属性生成SKU

  • 1、效果展示

在这里插入图片描述

  • 2、由销售属性来生成下面的表格的方法

    const checkPropertyList = ref([]);/*** 生成sku数据* @param {*} skuAttribute 选中的商品属性*/const generateSku = (skuAttribute) => {console.log(JSON.stringify(skuAttribute));const attrValue = [];// 获取选中的属性const checkList = [];for (const item of skuAttribute) {attrValue.push(item.attributeItem.filter((it) => item.checkList.includes(it.id)));checkList.push(item.id); // 选中的主键id}checkPropertyList.value = checkList;console.log(attrValue, '???');if (attrValue.length == 0) {tableData.value = [];return;}// 处理添加一个属性的时候表格置空if (!attrValue[attrValue.length - 1].length) {return;}// 循环组成sku数据const skuList = attrValue.reduce((pre, cur) => {let res = [];for (const item of pre) {for (const it of cur) {let t = item.name + ',' + it.name;res.push({name: t,url: item.url || it.url || '',});}}return res;}).map((it) => {const oldData = afterSku.value.find((item) => item.name == it.name);return {...it,id: oldData ? oldData.id : '',price: oldData ? oldData.price : '', // 单价stock: oldData ? oldData.stock : '', // 库存};});tableData.value = skuList;};
    
  • 3、在什么时候调用上面这个方法呢?,直接监听销售属性的变化就可以

    watch(() => skuAttributes.value,(newValue) => {generateSku(cloneDeep(newValue));},{deep: true,}
    );
    // 监听sku表格的变化,并将当前sku进行备份
    const afterSku = ref([]);
    watch(() => tableData.value,(value) => {afterSku.value = cloneDeep(value);},{ deep: true }
    );
    
  • 4、点击按钮提交数据给后端

    const submitHandler = async () => {ElMessage.success('请查看浏览器控制台');console.log('销售属性:', JSON.stringify(skuAttributes.value));console.log('表格数据:', JSON.stringify(tableData.value));const postData = {name: '苹果13',keyword: '苹果手机',introduction: 'laboris sint in',categoryId: 10,brandId: 50,picUrl: 'http://dummyimage.com/400x400',videoUrl: 'http://voanozyj.vg/suuadzgv',sliderPicUrls: 'http://dummyimage.com/400x400',unit: 25,specType: 79,price: 90,marketPrice: 11,discountPrice: 82,vipPrice: 32,costPrice: 87,stock: 19,sort: 33,isHot: 0,isBenefit: 0,isBest: 0,isNew: 0,isGood: 0,giveIntegral: 43,content: '手机详情',remark: 'magna eu laboris',// 过滤掉没有选择的sku属性attribute: JSON.stringify(skuAttributes.value),skuList: tableData.value.map((item) => {return {...item,attributeValue: item.name,barCode: item.name,discountPrice: item.price,costPrice: item.price,picUrl: 'http://dummyimage.com/400x400',vipPrice: item.price,volume: 85,marketPrice: 26,weight: 50,};}),};console.log(JSON.stringify(postData), '提交数据');const data = await SkuService.createSpuApi(postData);console.log(data);};
    
  • 5、完整代码如下

    <template><div class="sku"><el-card shadow="never"><el-form><el-form-item label="销售属性"><el-cardshadow="never"v-for="(item, index) of skuAttributes":key="index":gutter="20"class="sku-row"><el-button type="danger" class="delete-row-btn" @click="deleteRowHandler(index)">删除</el-button><el-row :gutter="10"><el-col :span="2">属性名称:</el-col><el-col :span="8"><el-selectv-model="item.id"placeholder="请选择属性"@change="changeAttributeHandler"><el-optionv-for="item in attributeItem":key="item.id":label="item.name":value="item.id":disabled="checkPropertyList.includes(item.id)"/></el-select></el-col></el-row><el-row :gutter="10"><el-col :span="2"> 属性值: </el-col><el-col :span="22"><el-checkbox-group v-model="item.checkList"><el-checkbox:label="value.id"v-for="(value, i) of item.attributeItem":key="i">{{ value.name }}</el-checkbox></el-checkbox-group></el-col></el-row></el-card><div><el-button type="primary" @click="addSkuAttrHandler">增加销售属性</el-button></div></el-form-item></el-form></el-card><!-- 下面表格 --><el-card shadow="never" style="margin-top: 20px"><el-table :data="tableData" style="width: 100%" border><el-table-column prop="name" label="销售规格" width="180" /><el-table-column prop="price" label="单价"><template #default="scope"><el-input v-model="scope.row.price" placeholder="单价"></el-input></template></el-table-column><el-table-column prop="stock" label="库存"><template #default="scope"><el-input v-model="scope.row.stock" placeholder="库存"></el-input></template></el-table-column></el-table><el-button type="primary" style="margin-top: 20px" @click="submitHandler">提交数据</el-button></el-card></div>
    </template><script setup>import { SkuService } from '@/services';import { ref, onMounted, watch } from 'vue';import { cloneDeep } from 'lodash';import { ElMessage } from 'element-plus';const skuAttributes = ref([]);// 添加属性const addSkuAttrHandler = () => {skuAttributes.value.push({id: null,attributeItem: [],checkList: [],});};// 删除const deleteRowHandler = (index) => {skuAttributes.value.splice(index, 1);};// 1.获取全部的销售属性const attributeItem = ref([]);const getAllAttrApi = async () => {const data = await SkuService.getAttributeListApi();attributeItem.value = data.result;};// 切换的时候const changeAttributeHandler = async (item) => {let currentItem = skuAttributes.value.find((it) => it.id == item);const currentIndex = skuAttributes.value.findIndex((it) => it.id == item);const data = await SkuService.getAttributeValueByAttributeIdApi(item);currentItem.attributeItem = data.result;currentItem.name = attributeItem.value.find((it) => it.id == item)?.name;// 替换之前的skuAttributes.value.splice(currentIndex, 1, currentItem);};// 表格数据const tableData = ref([]);const submitHandler = async () => {ElMessage.success('请查看浏览器控制台');console.log('销售属性:', JSON.stringify(skuAttributes.value));console.log('表格数据:', JSON.stringify(tableData.value));const postData = {name: '苹果13',keyword: '苹果手机',introduction: 'laboris sint in',categoryId: 10,brandId: 50,picUrl: 'http://dummyimage.com/400x400',videoUrl: 'http://voanozyj.vg/suuadzgv',sliderPicUrls: 'http://dummyimage.com/400x400',unit: 25,specType: 79,price: 90,marketPrice: 11,discountPrice: 82,vipPrice: 32,costPrice: 87,stock: 19,sort: 33,isHot: 0,isBenefit: 0,isBest: 0,isNew: 0,isGood: 0,giveIntegral: 43,content: '手机详情',remark: 'magna eu laboris',// 过滤掉没有选择的sku属性attribute: JSON.stringify(skuAttributes.value),skuList: tableData.value.map((item) => {return {...item,attributeValue: item.name,barCode: item.name,discountPrice: item.price,costPrice: item.price,picUrl: 'http://dummyimage.com/400x400',vipPrice: item.price,volume: 85,marketPrice: 26,weight: 50,};}),};console.log(JSON.stringify(postData), '提交数据');const data = await SkuService.createSpuApi(postData);console.log(data);};watch(() => skuAttributes.value,(newValue) => {generateSku(cloneDeep(newValue));},{deep: true,});// 监听sku表格的变化,并将当前sku进行备份const afterSku = ref([]);watch(() => tableData.value,(value) => {afterSku.value = cloneDeep(value);},{ deep: true });const checkPropertyList = ref([]);/*** 生成sku数据* @param {*} skuAttribute 选中的商品属性*/const generateSku = (skuAttribute) => {console.log(JSON.stringify(skuAttribute));const attrValue = [];// 获取选中的属性const checkList = [];for (const item of skuAttribute) {attrValue.push(item.attributeItem.filter((it) => item.checkList.includes(it.id)));checkList.push(item.id); // 选中的主键id}checkPropertyList.value = checkList;console.log(attrValue, '???');if (attrValue.length == 0) {tableData.value = [];return;}// 处理添加一个属性的时候表格置空if (!attrValue[attrValue.length - 1].length) {return;}// 循环组成sku数据const skuList = attrValue.reduce((pre, cur) => {let res = [];for (const item of pre) {for (const it of cur) {let t = item.name + ',' + it.name;res.push({name: t,url: item.url || it.url || '',});}}return res;}).map((it) => {const oldData = afterSku.value.find((item) => item.name == it.name);return {...it,id: oldData ? oldData.id : '',price: oldData ? oldData.price : '', // 单价stock: oldData ? oldData.stock : '', // 库存};});tableData.value = skuList;};onMounted(() => {getAllAttrApi();});
    </script><style lang="scss" scoped>.sku-row {width: 100%;margin-bottom: 10px;position: relative;.delete-row-btn {position: absolute;right: 10px;top: 10px;cursor: pointer;z-index: 30;}.sku-value-item {margin-bottom: 10px;position: relative;.close-icon {position: absolute;right: 0;top: 0;z-index: 10;cursor: pointer;opacity: 0;}&:hover {.close-icon {opacity: 1;}}}}
    </style>
    

四、前端实现sku选择

  • 1、效果图如下

    在这里插入图片描述

  • 2、实现代码见如下

    <template><div class="sku"><h3>iphone 13</h3><div v-for="(item, index) of processAttribute" :key="index"><div class="title" style="margin-bottom: 10px; margin-top: 10px">{{ item.title }}</div><template v-for="(item1, index1) of item.attributeItem" :key="index1"><el-tagtype="success":class="[{active: item1.activity,disabled: item1.disabled,},]"style="margin-right: 10px; cursor: pointer"@click="skuClickHandler(index, index1)">{{ item1.name }}</el-tag></template></div><div>当前选中的库存:{{ stock }}</div><div>价格范围:<span v-if="minPrice == maxPrice">{{ maxPrice }}</span><span v-else>{{ minPrice }}-{{ maxPrice }}</span></div></div>
    </template><script setup>import { onMounted } from 'vue';import { SkuService } from '@/services';import { useRoute } from 'vue-router';const route = useRoute();const skuAttribute = ref([]);const skuList = ref([]);const processAttribute = ref([]);const processSkuMap = ref({});const initData = () => {for (const item of skuAttribute.value) {let temp = {id: item.id,title: item.title,};temp.attributeItem = item.attributeItem.filter((it) => item.checkList.includes(it.id)) // 过滤有的属性.map((it) => {return {...it,activity: false,disabled: itemquantity(it.name) <= 0, // 判断当前是否小于0的库存stock: itemquantity(it.name),};});processAttribute.value.push(temp);}// 对 skuList 数据进行加工,并存入 processSkuMap 中for (const item of skuList.value) {let combArr = arrayCombine(item.attributeValue.split(','));for (let j = 0; j < combArr.length; j++) {var key = combArr[j].join(',');if (processSkuMap.value[key]) {// 库存累加,价格添加进数组processSkuMap.value[key].stock += +item.stock;processSkuMap.value[key].prices.push(item.price);} else {processSkuMap.value[key] = {stock: +item.stock,prices: [item.price],};}}}// 计算下// skuCheck();};// 计算当前sku的库存const itemquantity = (item) => {let quantity = 0;skuList.value.forEach((element) => {var skuArr = element.attributeValue.split(',');if (skuArr.indexOf(item) != -1) {quantity += +element.stock;}});return quantity;};const arrayCombine = (targetArr) => {let resultArr = [];for (var n = 0; n <= targetArr.length; n++) {var flagArrs = getFlagArrs(targetArr.length, n);while (flagArrs.length) {var flagArr = flagArrs.shift();var combArr = Array(targetArr.length);for (var i = 0; i < targetArr.length; i++) {if (flagArr[i]) {combArr[i] = targetArr[i];}}resultArr.push(combArr);}}return resultArr;};const getFlagArrs = (m, n) => {let flagArrs = [];let flagArr = [];let isEnd = false;for (let i = 0; i < m; i++) {flagArr[i] = i < n ? 1 : 0;}flagArrs.push(flagArr.concat());// 当n不等于0并且m大于n的时候进入if (n && m > n) {while (!isEnd) {var leftCnt = 0;for (var i = 0; i < m - 1; i++) {if (flagArr[i] == 1 && flagArr[i + 1] == 0) {for (var j = 0; j < i; j++) {flagArr[j] = j < leftCnt ? 1 : 0;}flagArr[i] = 0;flagArr[i + 1] = 1;var aTmp = flagArr.concat();flagArrs.push(aTmp);if (aTmp.slice(-n).join('').indexOf('0') == -1) {isEnd = true;}break;}flagArr[i] == 1 && leftCnt++;}}}return flagArrs;};// 点击skuconst skuClickHandler = (key1, key2) => {console.log(key1, key2, '点击了', processAttribute.value[key1]);// 如果不是被禁用的时候才执行if (!processAttribute.value[key1].attributeItem[key2].disabled) {// 选择和取消选中processAttribute.value[key1].attributeItem.map((item, index) => {item.activity = index == key2 ? !item.activity : false;});// 检查当前的sku是否有库存skuCheck();// 每次点击的时候判断禁用getStockPrice();}};// 当前选中的sku的库存机最小单价最大单价const stock = ref(0);const minPrice = ref(null);const maxPrice = ref(null);const skuCheck = () => {let sku = [];processAttribute.value.map((attr) => {let name = '';attr.attributeItem.map((item) => {console.log(item, '111');if (item.activity) {name = item.name;}});sku.push(name);});console.log(sku, '选中的的值', sku.join(','));stock.value = processSkuMap.value[sku.join(',')].stock;minPrice.value = Math.min.apply(Math, processSkuMap.value[sku.join(',')].prices);maxPrice.value = Math.max.apply(Math, processSkuMap.value[sku.join(',')].prices);};// 点击的时候判断库存禁用const getStockPrice = () => {processAttribute.value.map((attr) => {attr.attributeItem.map((item) => {item.disabled = itemquantity(item.name) <= 0;});});let count = 0;let i = 0;processAttribute.value.map((attr, index) => {let flag = false;attr.attributeItem.map((item) => {if (item.activity) {flag = true;}});if (!flag) {count += 1;i = index;}});// 当只有一组规格没选时if (count == 1) {processAttribute.value[i].attributeItem.map((item) => {let sku = [];let text = item.name;processAttribute.value.map((attr, index) => {if (index != i) {attr.attributeItem.map((item2) => {if (item2.activity) {sku.push(item2.name);}});} else {sku.push(text);}});if (processSkuMap.value[sku.join(',')].stock == 0) {item.disabled = true;}});}// 当所有规格都有选时if (count == 0) {processAttribute.value.map((attr, index) => {let i = index;processAttribute.value[index].attributeItem.map((item) => {if (!item.activity) {let sku = [];let text = item.name;processAttribute.value.map((list, index) => {if (index != i) {list.attributeItem.map((item2) => {if (item2.activity) {sku.push(item2.name);}});} else {sku.push(text);}});if (processSkuMap.value[sku.join(',')].stock == 0) {item.disabled = true;}}});});}};const initSkuData = async () => {const { result } = await SkuService.getSkuByIdApi(route.query.id);// console.log(data);console.log(result.skuAttribute, '111');skuAttribute.value = result.skuAttribute;skuList.value = result.skuList;};onMounted(async () => {await initSkuData();initData();});
    </script><style lang="scss" scoped>.sku {.active {background: skyblue;color: #fff;border: none;}.disabled {background: #ddd;}}
    </style>

五、具体代码见

  • 1、[后端代码](shuiping.kuang/sku_demo (gitee.com))
  • 2、[前端代码](shuiping.kuang/vue3-sku (gitee.com))

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法】队列+bfs算法 解决树的相关算法题(C++)

文章目录 1. 前言2. 算法题429.N叉树的层序遍历103.二叉树的锯齿形层序遍历662.二叉树最大宽度515.在每个树行中找最大值 1. 前言 队列 与 宽度优先算法&#xff08;BFS&#xff09;是解决很多算法问题的常见工具。 BFS通过逐层遍历图或树的节点来寻找解决问题的最短路径或最…

【不用找素材】ECS 游戏Demo制作教程(3) 1.17

一、生成墓碑 新建脚本如下&#xff1a; using Unity.Entities; using Unity.Mathematics;namespace ECSdemo {public struct GraveyardRandom : IComponentData{public Random Value;}}扩充GraveyardMono如下&#xff1a; using Unity.Entities; using Unity.Mathematics; …

AI 的未来是开源的

想象一下&#xff0c;在未来&#xff0c;人工智能不会被锁在公司的金库里&#xff0c;而是由全球创新者社区一砖一瓦地在开放中构建的。协作&#xff0c;而不是竞争&#xff0c;推动进步&#xff0c;道德考虑与原始绩效同等重要。这不是科幻小说&#xff0c;而是人工智能发展核…

Git怎么将文件夹上传至github,全过程

小白建议参考github文件上传全流程-新手入门系列&#xff08;超详细&#xff01;&#xff01;&#xff01;&#xff09; 中间可能会有报错 $ ssh -T gitgithub.com ssh: connect to host github.com port 22: Connection timed out 这时&#xff0c;参考&#xff0c;如何解决&a…

汽车芯片「新变量」

编者按&#xff1a;汽车行业的格局重构和技术革新&#xff0c;也在推动芯片赛道进入变革周期。不同商业模式的博弈&#xff0c;持续升温。 对于智能汽车来说&#xff0c;过去几年经历了多轮硬件和软件的性能迭代&#xff0c;甚至是革新&#xff0c;如今&#xff0c;市场正在进…

JNPF低代码开发平台总体架构介绍

目录 一、JNPF介绍 二、团队能力 三、技术选型 1.后端技术栈 2.前端技术栈 3.数据库支持 四、JNPF界面示意图 五、开发环境 一、JNPF介绍 JNPF是一款企业级低代码开发平台。基于Springboot、Vue技术&#xff0c;采用微服务、前后端分离架构&#xff0c;基于可视化数据建…

C++PythonC# 三语言OpenCV从零开发(1):环境配置

文章目录 前言课程选择环境配置PythonC#COpenCV官网下载新建C项目测试运行Csharp版Python版 gitee仓库总结 前言 由于老王我想转机器视觉方向的上位机行业&#xff0c;我就打算开始从零学OpenCV。但是目前OpenCV有两个官方语言&#xff0c;C和Pyhont。C# 有大佬做了对应的Open…

nginx+lua配置,一个域名配置https,docker集群使用

没安装kua的先安装lua 没有resty.http模块的&#xff0c;许配置 nginxlua配置&#xff0c;一个域名配置https&#xff0c;docker集群使用&#xff0c;一个域名配置https管理整个集群 lua做转发&#xff08;方向代理&#xff09; 1、ad_load.lua文件 ngx.header.content_typ…

五、基础篇 vue列表渲染

在v-for里使用对象用 v-for 把一个数组对应为一组元素 我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in list形式的特殊语法&#xff0c;其中 list是源数据数组&#xff0c;而 item 则是被迭代的数组元素的别名。 <template><div clas…

WebRTC入门:基础的核心协议与概念(二十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

k8s云原生环境搭建笔记——第二篇

目录 1、使用普通方式安装prometheus和grafana1.1、安装kube-state-metrics容器1.1.1、下载并修改yaml文件1.1.2、导入kube-state-metrics镜像1.1.3、执行yaml文件目录 1.2、安装node-exploer1.2.1、创建名称空间prometheus1.2.2、执行yaml 1.3、安装prometheus1.3.1、创建集群…

「 典型安全漏洞系列 」03.跨站请求伪造CSRF详解

引言&#xff1a;CSRF&#xff08;Cross-Site Request Forgery&#xff0c;跨站请求伪造&#xff09;是一种攻击技术&#xff0c;通过使用用户的身份进行不诚实地操作&#xff0c;恶意用户可以在受害者&#xff08;目标&#xff09;的机器上执行一些未授权的操作。这可能会危及…