后端SpringBoot+前端Vue前后端分离的项目(一)

前言:后端使用SpringBoot框架,前端使用Vue框架,做一个前后端分离的小项目,需求:实现一个表格,具备新增、删除、修改的功能。

目录

一、数据库表的设计

二、后端实现

环境配置

数据处理-增删改查

model层

mapper层

XML配置

Service层

controller层

单元测试

三、前后端交互

配置

vite.config.ts文件配置

创建axios实例 

业务请求

四、前端实现

环境配置

Main.vue

interface接口

五、效果展示

六、总结


一、数据库表的设计

设计了一个merchandise表,id是编号,唯一的,类型为int,category是一级类别,type是二级类别,name是商品的名称,sum_quantity是总数量,sold_quantity是售卖的数量。

数据库里的字段名使用的是下划线连接,在java中变量命名一般使用驼峰式,需要在application.properties文件中进行配置

mybatis.configuration.map-underscore-to-camel-case=true

二、后端实现

model层

package com.mrjj.java.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class merchandise {public int id;public String category;public String type;public String name;public String sum_quantity;public String sold_quantity;
}

环境配置

引入需要的依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.19</version></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version></dependency>

 完成application.properties文件的配置,连接mysql

server.port=8888
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mrjj?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.configuration.map-underscore-to-camel-case=true

数据处理-增删改查

model层

映射数据库中的字段

package com.mrjj.java.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Merchandise {public int id;public String merchandiseCategory;public String merchandiseType;public String merchandiseName;public int sumQuantity;public int soldQuantity;
}

返回结果字段

package com.mrjj.java.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {private Integer code;private String msg;private T data;public Result(String msg, Integer code) {this.msg = msg;this.code = code;}public Result(T data) {this.data = data;this.code = 1000;}public static <T> Result<T> success(T data) {Result<T> result = new Result<>(data);result.setCode(200);result.setMsg("请求成功");return result;}public static <T> Result<T> success(String msg, T data) {Result<T> result = new Result<>(data);result.setCode(200);result.setMsg(msg);return result;}public static <T> Result fail(int code, String message, T data) {Result<T> resultData = new Result<>();resultData.setCode(code);resultData.setMsg(message);resultData.setData(data);return resultData;}
}

mapper层

package com.mrjj.java.mapper;import com.mrjj.java.model.Merchandise;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface MerchandiseMapper {@Select("select * from merchandise")List<Merchandise> getMerchandise();@Insert("insert into merchandise values(#{id},#{merchandiseCategory},#{merchandiseType},#{merchandiseName},#{sumQuantity},#{soldQuantity})")int addMerchandise(Merchandise merchandise);@Delete("delete from merchandise where id=#{id}")int deleteOneMerchandise(@Param("id") Long id);int updateMerchandise(List<Merchandise> merchandise);
}

XML配置

注意!!!

要配置上allowMultiQueries=true,才能批量处理!!!这个问题查了蛮久的!!!

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:填写映射当前的Mapper接口,所有的增删改查的参数和返回值类型,就可以直接填写缩写,不区分大小写,直接通过方法名去找类型-->
<mapper namespace="com.mrjj.java.mapper.MerchandiseMapper"><!--    id 对应的是mapper.CaseMapper里的方法名--><delete id="deleteMoreMerchandise">delete from merchandise<where><foreach collection="list" separator="," item="item" open="id in (" close=")">#{item}</foreach></where></delete><update id="updateMerchandise" parameterType="java.util.List"><foreach collection="list" item="item" separator=";">update merchandise<set><if test="#{item.merchandiseCategory}!=null">merchandise_category=#{item.merchandiseCategory},</if><if test="#{item.merchandiseType}!=null">merchandise_type=#{item.merchandiseType},</if><if test="#{item.merchandiseName}!=null">merchandise_name=#{item.merchandiseName},</if><if test="#{item.sumQuantity}!=null">sum_quantity=#{item.sumQuantity},</if><if test="#{item.soldQuantity}!=null">sold_quantity=#{item.soldQuantity},</if></set>where id=#{item.id}</foreach></update>
</mapper>

Service层

package com.mrjj.java.service;import java.util.List;public interface MerchandiseService {int deleteMoreMerchandise(List<Long> ids);
}
package com.mrjj.java.service.impl;import com.mrjj.java.mapper.MerchandiseMapper;
import com.mrjj.java.service.MerchandiseService;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;@Service("MerchandiseService")
public class MerchandiseServiceImpl implements MerchandiseService {@ResourceMerchandiseMapper merchandiseMapper;@Overridepublic int deleteMoreMerchandise(List<Long> ids) {int delCount = 0;for (Long id : ids) {delCount += merchandiseMapper.deleteOneMerchandise(id);}System.out.println("删除了" + delCount + "条用例");return delCount;}
}

controller层

package com.mrjj.java.controller;import com.mrjj.java.mapper.MerchandiseMapper;
import com.mrjj.java.model.Merchandise;
import com.mrjj.java.model.Result;
import com.mrjj.java.service.MerchandiseService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;import javax.annotation.Resource;
import java.util.List;@RestController
@RequestMapping("/mrjjMerchandise")
public class MerchandiseController {@ResourceMerchandiseMapper merchandiseMapper;@ResourceMerchandiseService merchandiseService;@GetMappingpublic Result listMerchandise() {List<Merchandise> Marchandise = merchandiseMapper.getMerchandise();System.out.println("查到的商品是" + Marchandise);return Result.success(Marchandise);}@GetMapping("/view")public ModelAndView showMerchandise() {ModelAndView MarchandiseView = new ModelAndView();List<Merchandise> Marchandise = merchandiseMapper.getMerchandise();MarchandiseView.addObject("mrjjMarchandiseView", Marchandise);MarchandiseView.setViewName("mrjjMarchandise");return MarchandiseView;}@PostMappingpublic Result addMerchandise(@RequestBody Merchandise merchandise) {int i = merchandiseMapper.addMerchandise(merchandise);if (i > 0) {return Result.success(merchandise);} else {return Result.fail(210, "新增商品信息失败", merchandise);}}@PutMappingpublic Result updateMerchandise(@RequestBody List<Merchandise> MerchandiseList) {System.out.println("修改");int i = merchandiseMapper.updateMerchandise(MerchandiseList);if (i > 0)return Result.success("修改商品信息成功");elsereturn Result.fail(230, "修改商品信息失败", MerchandiseList);}@DeleteMapping("/{id}")public Result deleteOneMerchandise(@PathVariable Long id) {System.out.println(id);int i = merchandiseMapper.deleteOneMerchandise(id);System.out.println("删除的结果是:" + i);if (i > 0) {return Result.success("删除商品成功");} else {return Result.fail(240, "删除商品信息用例失败", "删除商品信息失败");}}@DeleteMapping("/ids/{ids}")public int deleteMoreMerchandise(@PathVariable List<Long> ids) {return merchandiseService.deleteMoreMerchandise(ids);}}

单元测试

package com.mrjj.java.controller;import com.mrjj.java.model.Result;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.util.ArrayList;
import java.util.List;@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
@Rollback(value=true)
class MerchandiseControllerTest {@ResourceMerchandiseController merchandiseController;@Testpublic void testQuery() {Result queryData = merchandiseController.listMerchandise();System.out.println(queryData);}@Testpublic void testDelete(){Result deleteData = merchandiseController.deleteOneMerchandise(4L);System.out.println(deleteData);}@Testpublic void testDeleteMore(){List<Long> list1 = new ArrayList<>();list1.add(0,5L);list1.add(1,4L);int deleteMoreData = merchandiseController.deleteMoreMerchandise(list1);System.out.println(deleteMoreData);}
}

三、前后端交互

配置

大致画了个流程图

可以看到在发送请求时,路径以及变了 

vite.config.ts文件配置

target是本地服务的地址和端口号

添加的路径/mrjj

server:{open:true,proxy:{'/mrjj': {target: 'http://localhost:8888',changeOrigin: true,rewrite: (path) => path.replace(/^\/mrjj/, ''),},}}

创建axios实例 

import axios, { type AxiosResponse } from 'axios'
const instance = axios.create({baseURL: '/mrjj',timeout: 30000,headers: { 'Content-Type': 'application/json;charset=utf-8' }
})instance.interceptors.response.use(function (response: AxiosResponse) {const { code } = response.dataif (code === 200) {return response.data}},function (error) {return Promise.reject(error)}
)
export default instance

业务请求

baseURL对应本地服务的接口地址

导出后端服务增删改查方法

import request from '../request'
import axios, { type AxiosPromise } from 'axios'
import type { MrjjMerchandise } from '@/types/merchandises/type'
const instance = axios.create({baseURL: '/mrjjMerchandise',timeout: 30000,headers: { 'Content-Type': 'application/json;charset=utf-8' }
})
export default instanceexport function listMerchandiseApi(): AxiosPromise<MrjjMerchandise[]> {return request({url: '/mrjjMerchandise',method: 'get'})
}export function addMerchandiseApi(data: MrjjMerchandise) {return request({url: '/mrjjMerchandise',method: 'post',data: data})
}export function changeMerchandiseApi(data: MrjjMerchandise) {return request({url: '/mrjjMerchandise',method: 'put',data})
}export function deleteMerchandiseApi(ids: string) {return request({url: '/mrjjMerchandise/ids/' + ids,method: 'delete'})
}

四、前端实现

环境配置

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
import router from './router'
createApp(App).use(router).use(ElementPlus, { locale: zhCn }).use(VXETable).mount('#app')

Main.vue

<template><el-dialog title="添加商品" v-model="isAdd" width="30%"><el-form :model="newMerchandise" ref="form" label-width="80px" :inline="false" size="normal"><el-form-item label="一级分类"><el-input v-model="newMerchandise.merchandiseCategory"></el-input></el-form-item><el-form-item label="二级分类"><el-input v-model="newMerchandise.merchandiseType"></el-input></el-form-item><el-form-item label="商品名称"><el-input v-model="newMerchandise.merchandiseName"></el-input></el-form-item><el-form-item label="总数量"><el-input v-model="newMerchandise.sumQuantity"></el-input></el-form-item><el-form-item label="已售出"><el-input v-model="newMerchandise.soldQuantity"></el-input></el-form-item></el-form><template #footer><span><el-button @click="closeAdder">取消</el-button><el-button type="primary" @click="addMerchandise">确认</el-button></span></template></el-dialog><el-card shadow="always" :body-style="{ padding: '0px' }"><template #header><div><el-row :gutter="16"><el-col :span="4" class="case-title"><span>商品信息</span></el-col><el-col :span="4" :offset="16"><el-button type="success" @click="openMerchandiseAdd"><el-icon><Plus /></el-icon> 新增商品</el-button></el-col><el-button type="primary" size="default" @click="changeMerchandise"><el-icon><Promotion /></el-icon>提交修改</el-button><el-buttontype="danger"size="default"@click="deleteChecked":disable="checkedMoreIds?.length === 0"><el-icon><Delete /></el-icon>删除选中商品</el-button></el-row></div></template><vxe-tableref="merchandiseTable"bordershow-header-overflowshow-overflow@checkbox-all="selectMoreMerchandiseEvent":column-config="{ resizable: true }":data="Merchandises":edit-config="{ trigger: 'dblclick', mode: 'cell' }"><vxe-column type="checkbox" width="60"></vxe-column><vxe-columnfield="merchandiseCategory"title="一级类别":edit-render="{ name: 'input' }"></vxe-column><vxe-columnfield="merchandiseType"title="二级类别":edit-render="{ name: 'input' }"></vxe-column><vxe-columnfield="merchandiseName"title="商品名称":edit-render="{ name: 'input' }"></vxe-column><vxe-column field="sumQuantity" title="总数量" :edit-render="{ name: 'input' }"></vxe-column><vxe-column field="soldQuantity" title="已售出" :edit-render="{ name: 'input' }"></vxe-column><vxe-column field="" title="操作"><template #default="{ row }"><el-button type="primary" size="default" @click="deleteMerchandise(row)" :icon="Delete">删除</el-button></template></vxe-column></vxe-table></el-card>
</template><script setup lang="ts">
import { Delete, Promotion, Plus } from '@element-plus/icons-vue'
import type { VxeTableInstance } from 'vxe-table'
import type { MerchandiseShow, MrjjMerchandise } from '../types/merchandises/type'
import {listMerchandiseApi,addMerchandiseApi,deleteMerchandiseApi,changeMerchandiseApi
} from '../api/merchandise'
import { ref, onMounted, reactive, computed } from 'vue'
onMounted(() => {listMerchandises()
})
let isAdd = ref(false)
let isEdit = ref(false)
let merchandiseTable = ref<VxeTableInstance>()
let Merchandises = ref([])
let emptyMerchandise = {merchandiseCategory: '',merchandiseType: '',merchandiseName: '',sumQuantity: '',soldQuantity: ''
}
let newMerchandise = reactive<MerchandiseShow>({merchandiseCategory: '',merchandiseType: '',merchandiseName: '',sumQuantity: '',soldQuantity: ''
})
const checkedMoreIds = computed(() => {return merchandiseTable.value?.getCheckboxRecords().map((MrjjMerchandise) => {return MrjjMerchandise.id})
})
function closeAdder() {isAdd.value = false
}
function openMerchandiseAdd() {isAdd.value = true
}
function listMerchandises() {console.log('正在发送请求')listMerchandiseApi().then(({ data }) => {Merchandises.value = dataconsole.log('获取到的用例信息是:', Merchandises)}).catch((error: any) => {console.log('报错了', error)})
}
function addMerchandise() {let lastId =Merchandises.value.length > 0 ? Merchandises.value[Merchandises.value.length - 1].id : -1let addMerchandise: MrjjMerchandise = { ...newMerchandise, id: 0 }addMerchandise.id = lastId + 1console.log('要新增的商品是:', addMerchandise)addMerchandiseApi(addMerchandise).then(() => {listMerchandises()})closeAdder()
}function deleteMerchandise(deleteOneMerchandise: MrjjMerchandise) {deleteMerchandiseApi(deleteOneMerchandise.id + '').then(() => {listMerchandises()})
}
function deleteChecked() {console.log('选中的id是', checkedMoreIds.value?.toString())deleteMerchandiseApi(checkedMoreIds.value!.toString()).then(() => {listMerchandises()})
}
function changeMerchandise() {changeMerchandiseApi(Merchandises.value).then(() => {listMerchandises()})
}
</script><style scoped>
.case-title {font-size: large;color: red;font-weight: bolder;
}
</style>

interface接口

export interface MerchandiseShow{merchandiseCategory:string;merchandiseType:string;merchandiseName:string;sumQuantity:number;soldQuantity:number;[key:string]: any;}export interface MrjjMerchandise extends MerchandiseShow{id:number;}export interface MrjjMerchandiseEdit extends MrjjMerchandise{isEdit:boolean;}

五、效果展示

实现了查询、新增、删除、修改的功能

 修改后,数据库里的值也发生了变化

六、总结

通过对数据库表、后端接口设计、前端页面编写,已经实现了一个前后端分离的小项目了,当然还可以进一步完善这个功能,比如新增时可以加上参数校验,可以做一个树形结构的列表,实现数据的拖拽,还可以加上查询、分页、排序等功能,后续博客会对不断进行完善。

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

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

相关文章

C++的纯虚函数和抽象类

在C++中,可以将虚函数声明为纯虚函数,语法格式为: virtual 返回值类型 函数名 (函数参数) = 0; 纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上=0,表明此函数为纯虚函数。 最后的=0并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”。…

MySQL的概述、版本、安装过程

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、MySQL的概述 二、MySQL的版本 三、MySQL的下载与安装 前言 本文将来谈谈MySQL的概述&#xff0c;MySQL的版本&#xff0c;以及它…

Redis 缓存穿透击穿和雪崩

一、说明 Redis 缓存的使用&#xff0c;极大的提升了应用程序的性能和效率&#xff0c;特别是数据查询方面。但同时&#xff0c;它也带来了一些问题。其中&#xff0c;最要害的问题&#xff0c;就是数据的一致性问题&#xff0c;从严格意义上讲&#xff0c;这个问题无解。如果对…

C++11新特性③ | 可变参数模板介绍

目录 1、引言 2、可变参数模板函数 2.1、可变参数模板函数的定义 2.2、参数包的展开 3、可变参数模板类 3.1、继承方式展开参数包 3.2、模板递归和特化方式展开参数包 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff…

js获得相对路径文件,并上传到服务器

如何通过js获得相对路径文件 已知一个相对路径文件&#xff0c;如何使用js将该文件读取为File格式&#xff0c;最后上传到服务器中呢。 1.最简单的解决方案——fetch 代码 import ./index.scss// js通过相对路径获取文件 function FetchGetLocalFile() {const fetchLocalFile …

Python Opencv实践 - Shi-Tomasi角点检测

参考资料&#xff1a;Harris和Shi-tomasi角点检测笔记&#xff08;详细推导&#xff09;_harris焦点检测_亦枫Leonlew的博客-CSDN博客 cv.goodFeaturesToTrack&#xff1a;Shi-Tomasi角点检测-OpenCV-python_独憩的博客-CSDN博客 import cv2 as cv import numpy as np import …

Python入门学习12

一、Python包 什么是Python包 从物理上看&#xff0c;包就是一个文件夹&#xff0c;在该文件夹下包含了一个 __init__.py 文件&#xff0c;该文件夹可用于包含多个模块文件。从逻辑上看&#xff0c;包的本质依然是模块 包的作用: 当我们的模块文件越来越多时,包可以帮助我们管…

如何处理异步编程中的回调地狱问题?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 解决回调地狱问题的方法⭐使用 Promise⭐使用 async/await⭐ 使用回调函数库⭐模块化⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端…

YOLOV8从零搭建一套目标检测系统(修改model结构必看)附一份工业缺陷检测数据集

目录 1.YOLOV8介绍 2.YOLOV8安装 2.1环境配置 3.数据集准备 1.YOLOV8介绍 Yolov8结构图&#xff1a; YoloV8相对于YoloV5的改进点&#xff1a; Replace the C3 module with the C2f module. Replace the first 6x6 Conv with 3x3 Conv in the Backbone. Delete two Convs …

processflow流程图多人协作预热

前言 在线上办公如火如荼的今天&#xff0c;多人协作功能是每个应用绕不开的门槛。processflow在线流程图&#xff08;前身基于drawio二次开发&#xff09;沉寂两年之久&#xff0c;经过长时间设计开发&#xff0c;调整&#xff0c;最终完成了多人协作的核心模块设计。废话不多…

【SpringSecurity】九、Base64与JWT

文章目录 1、base64编码2、Base64Url3、JWT的产生背景4、JWT介绍5、JWT组成5.1 Header5.2 Payload5.3 Signature 6、JWT的使用方式7、JWT的几个特点 1、base64编码 base64是一种编码方式&#xff0c;不是加密方式。 所谓Base64&#xff0c;就是说选出64个字符&#xff1a;小写…

【办公类-19-03】办公中的思考——Python批量制作word单元格照片和文字(小照片系列)

背景需求&#xff1a; 工会老师求助&#xff1a;如何在word里面插入4*8的框&#xff0c;我怎么也拉不到4*8大小&#xff08;她用的是我WORD 文本框&#xff09; 我一听&#xff0c;这又是要手动反复黏贴“文本框”“照片”“文字”的节奏哦 我问&#xff1a;你要做几个人&…

搭建hadoop集群的常见问题及解决办法

问题一: namenode -format重复初始化 出现问题的原因是重复初始化时会重新生成集群ID&#xff0c;而dn还是原先的集群ID&#xff0c;两者不匹配时无法启动相应的dn进程。 怎么查找问题原因&#xff1a;在logs目录下找到对应节点的.log文件&#xff0c;使用tail -200 文件名来查…

远程工作面试:特殊情况下的面试技巧

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Web3 solidity编写cancelorder取消订单函数 并梳理讲述逻辑

上文 Web3 solidity订单池操作 中 我们讲述了订单池的基本概念 并手动编写了创建订单的操作 最近的 我们还是先将 ganache 环境起起来 然后 我们打开项目 上文中 我们写了makeOrder创建订单的函数 但是 也带出一个问题 我们创建之后 如果不要了 怎么干掉呀&#xff1f; js中我…

MongoDB常用的比较符号和一些功能符号

比较符号 results collection.find({age: {$gt: 20}})功能符号 results collection.find({name: {$regex: ^M.*}})

电水壶上要求亚马逊美国站SOR/2016-181和CSA22.1标准?

电水壶作为一种常见的小家电&#xff0c;受到了广大消费者的喜爱。然而&#xff0c;由于安全问题的日益重视&#xff0c;亚马逊加拿大站决定加强对电水壶产品的审核&#xff0c;以确保消费者的安全和权益。 近日&#xff0c;亚马逊平台发布公告&#xff0c;要求在加拿大站销售…

鸿蒙应用程序入口UIAbility详解

一、UIAbility概述 UIAbility是一种包含用户界面的应用组件&#xff0c;主要用于和用户进行交互。UIAbility也是系统调度的单元&#xff0c;为应用提供窗口在其中绘制界面。每一个UIAbility实例&#xff0c;都对应于一个最近任务列表中的任务。一个应用可以有一个UIAbility&am…

java从入门到起飞(八)——循环和递归

文章目录 Java循环1. 什么是循环&#xff1f;1.1 为什么需要循环&#xff1f;1.2 循环的分类 2. Java中的循环结构2.1 for循环2.2 while循环2.3 do-while循环 3. 循环控制语句3.1 break语句3.2 continue语句 4. 总结 Java递归1. 什么是递归2. 递归的原理3. 递归的实现4. 递归的…

【二分答案 dp】 Bare Minimum Difference

分析&#xff1a; 首先我们能够得知这个优秀值具有单调性&#xff1a; 如果一个优秀值 x 1 x1 x1能够满足题目要求&#xff0c;那么任何 x ( x > x 1 ) x(x>x1) x(x>x1)显然都能符合要求 基于这一特性&#xff0c;我们想到二分答案 直接二分这个答案好像难以维护。 …