苍穹外卖day03——菜品管理业务代码开发

news2024/10/7 4:34:13

目录

公共字段自动填充——问题分析和实现思路

  公共字段自动填充——代码实现(1)

  公共字段自动填充——代码实现完善(2)

新增菜品——需求分析与设计

产品原型

​编辑 接口设计 ​编辑

 数据库设计

新增菜品——代码开发1(文件上传接口)

配置文件

Controller层代码 

前后端联调测试

新增菜品——代码开发2(新增菜品接口)

Controller层中

Service层中

Mapper层中

功能测试

 菜品分页查询——需求分析与设计

产品原型

接口设计

 菜品分页查询——代码开发和功能测试

Controller层

 Service层

Mapper层

功能测试

 删除菜品——需求分析和设计

产品原型​编辑

接口设计

 ​编辑

数据库设计 

 删除菜品——代码实现

Controller层中

在service层中

Mapper层中

修改菜品——需求分析与设计

产品原型

 接口设计 

 修改菜品——代码开发(1):根据id查询

Controller层

Service层

Mapper层

 修改菜品——代码开发(2)修改菜品

Controller中

Service中

Mapper中


公共字段自动填充——问题分析和实现思路

  公共字段自动填充——代码实现(1)

自定义一个注解和一个切面类

/**
 * 自定义注解,用于标识某个方法需要进行功能字段自动填充
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //指定数据库操作的类型,insert update
    OperationType value();

}
/**
 * 自定义切面,实现公共字段自定义填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点:对哪些类的哪些方法进行拦截,这个匹配了所有的类和方法以及所有参数类型以及满足了有AutoFill这个注解
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}

    /**
     * 前置通知,在通知中进行公共字段的赋值
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进行公共字段的自动填充...");
    }
}

在mapper对应insert和update方法上加上对应的注解。

    /**
     * 根据主键动态修改属性
     * @param employee
     */
    @AutoFill(value= OperationType.UPDATE)
    void update(Employee employee);

    @Insert("insert into employee (name,username,password,phone,sex,id_number,create_time,update_time,create_user,update_user,status)" +
            "values "+
            "(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})" )
    @AutoFill(value= OperationType.INSERT)
    void insert(Employee employee);

  公共字段自动填充——代码实现完善(2)

切面类代码完善如下

/**
 * 自定义切面,实现公共字段自定义填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点:对哪些类的哪些方法进行拦截,这个匹配了所有的类和方法以及所有参数类型以及满足了有AutoFill这个注解
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}

    /**
     * 前置通知,在通知中进行公共字段的赋值
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        //获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
        OperationType operationType = autoFill.value();//获得数据库操作类型

        //获取到当前被拦截的方法的参数———实体对象
        Object[] args = joinPoint.getArgs();
        if(args==null||args.length==0)
        {
            return;
        }
        //约定了实体放在第一个参数
        Object entity=args[0];

        //准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        //根据当前不同的操作类型,为对应的属性通过反射赋值
        if(operationType==OperationType.INSERT){
            //为4个公共字段赋值
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //通过反射为对象属性赋值
                setCreateTime.invoke(entity,now);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }else if(operationType==OperationType.UPDATE){
            //为2个公共字段赋值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //通过反射为对象属性赋值
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

在service层中这些公共属性不再需要一个个set了

没有功能测试

新增菜品——需求分析与设计

产品原型

 接口设计 

multipart/form-data是通过浏览器进行文件上传固定的请求头。 

 

 数据库设计

新增菜品——代码开发1(文件上传接口)

配置文件

 这里写了一个配置属性类,加上一个@ConfigurationProperties使得可以读取配置文件的配置项然后封装成java对象。这里类中的属性使用驼峰命名法,配置文件里面使用横线的形式,springboot框架可以实现自动转换,就算不使用横线也是可以。

最终项目上线了有可能开发环境和生产环境用的不同的账号,这里采用引用的方式提供不同环境的配置文件.

再借助一个封装好的aliOSS的工具类

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }
}

 然后对于这个工具类里面的相关属性还要再定义相关的配置类初始化出来

/**
 * 配置类:用于创建AliOssUtil对象
 */
@Configuration
@Slf4j
public class OssConfiguration {

    @Bean
    @ConditionalOnMissingBean//保证整个spring容器只有一个AliOssUtil对象
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
        log.info("开始创建阿里文件上传工具类对象:{}",aliOssProperties);
        return new AliOssUtil(aliOssProperties.getEndpoint(),
                aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret(),
                aliOssProperties.getBucketName());
    }
}

Controller层代码 

为防止文件覆盖,使用UUID进行命名.


/**
 * 通用接口
 */
@RestController
@RequestMapping("/admin/common")
@Api(tags="通用接口")
@Slf4j
public class CommonController {

    @Autowired
    private AliOssUtil aliOssUtil;
    /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file){
        log.info("文件上传:{}",file);


        try {
            //原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取后缀 xxx.jpg
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            //构造新文件名称
            String objectName = UUID.randomUUID().toString()+extension;
            //文件的请求路径
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);
            return Result.success(filePath);
        } catch (IOException e) {
            log.error("文件上传失败:{}",e);
        }
        return Result.error(MessageConstant.UPLOAD_FAILED);
    }
}

前后端联调测试

成功回显。 

新增菜品——代码开发2(新增菜品接口)

Controller层中

新建一个DishController

/**
 * 菜品管理
 */
@RestController
@RequestMapping("/admin/dish")
@Api(tags="菜品相关接口")
@Slf4j
public class DishController {

    @Autowired
    private DishService dishService;
    /**
     * 新增菜品
     * @param dishDTO
     * @return
     */
    @PostMapping
    @ApiOperation("新增菜品")
    public Result save(@RequestBody DishDTO dishDTO){
        log.info("新增菜品:{}",dishDTO);
        dishService.saveWithFlavor(dishDTO);
        return Result.success();
    }
}

Service层中

新建一个DishService接口和DishServiceImpl这个实现类

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    /**
     * 新增菜品和对应的口味数据
     * @param dishDTO
     */
    @Override
    @Transactional//涉及到两个表的操作,要保证事务的一致性,在启动类已经开启了注解方式的事务管理
    public void saveWithFlavor(DishDTO dishDTO) {
        Dish dish=new Dish();

        BeanUtils.copyProperties(dishDTO,dish);
        //向菜品表插入1条数据
        dishMapper.insert(dish);

        //通过主键返回获取insert语句生成的主键值
        Long dishId = dish.getId();

        //向口味表插入n条数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors!=null&&flavors.size()>0){
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishId);
            });
            //向口味表插入n条数据
            dishFlavorMapper.insertBatch(flavors);
        }
    }
}

Mapper层中

因为涉及到两个表,所以新建一个DishMapper和DishFlavorMapper接口,还要新建对应的XML文件用于写动态SQl.这里涉及到主键返回和批量插入用到foreach标签和useGeneratedKeys属性

@Mapper
public interface DishMapper {

    /**
     * 根据分类id查询菜品数量
     * @param categoryId
     * @return
     */
    @Select("select count(id) from dish where category_id = #{categoryId}")
    Integer countByCategoryId(Long categoryId);

    /**
     * 插入菜品数据
     * @param dish
     */
    @AutoFill(value= OperationType.INSERT)
    void insert(Dish dish);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishMapper">

    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        insert into dish (name, category_id, price, image, description, create_time, update_time, create_user, update_user,status)
            values
        (#{name},#{categoryId} ,#{price},#{imape},#{description},#{createTime},#{updateTime},#{createUser},#{updateUser} ,#{status})
    </insert>
</mapper>

@Mapper
public interface DishFlavorMapper {

    /**
     * 批量插入口味数据
     * @param flavors
     */
    void insertBatch(List<DishFlavor> flavors);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishFlavorMapper">

    <insert id="insertBatch">
        insert into dish_flavor (dish_id,name,value) VALUES
        <foreach collection="flavors" item="df" separator=",">
            (#{df.dishId},#{df.name},#{df.value})
        </foreach>
    </insert>
</mapper>

功能测试

前后端联调测试

 数据无误

 菜品分页查询——需求分析与设计

产品原型

 

接口设计

 菜品分页查询——代码开发和功能测试

DTO和VO设计

 

Controller层

在DishController中创建一个新的方法

    /**
     * 菜品分页查询
     * @param dishPageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("菜品分页查询")
    public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
        log.info("菜品分页查询:{}",dishPageQueryDTO);
        PageResult pageResult= dishService.pageQuery(dishPageQueryDTO);
        return Result.success(pageResult);
    }

 Service层

    /**
     * 菜品分页查询
     * @param dishPageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
        Page<DishVO> page=dishMapper.pageQuery(dishPageQueryDTO);
         return new PageResult(page.getTotal(),page.getResult());
    }

Mapper层

    /**
     * 菜品分页查询
     * @param dishPageQueryDTO
     * @return
     */
    Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);


映射文件中涉及到两个表所以做个连接查询

    <select id="pageQuery" resultType="com.sky.vo.DishVO">
        select d.* ,c.name as categoryName from dish d left outer join category c on d.category_id=c.id
        <where>
            <if test="name != null">
                and d.name like concat('%',#{name},'%')
            </if>
            <if test="categoryId != null">
                and d.category_id=#{categoryId}
            </if>
            <if test="status != null">
                and d.status = #{status}
            </if>
        </where>
        order by d.create_time desc
    </select>

功能测试

接口文档测试

 前后端联调测试

 删除菜品——需求分析和设计

产品原型

 

接口设计

 

数据库设计 

 删除菜品——代码实现

Controller层中

这里针对url中的字符串使用一个@RequestParam注解将其转圜为list

    /**
     * 菜品批量删除
     * 通过@RequestParam注解将字符串转换为数组
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("菜品批量删除")
    public Result delete(@RequestParam List<Long> ids){
        log.info("菜品批量删除:{}",ids);
        dishService.deleteBatch(ids);
        return Result.success();
    }

在service层中

设计到三个表的操作

    @Override
    @Transactional
    public void deleteBatch(List<Long> ids) {
        //判断当前菜品是否能删除--是否存在起售中的菜品?
        for(Long id :ids){
            Dish dish=dishMapper.getById(id);
            if(dish.getStatus()== StatusConstant.ENABLE){
                //当前菜品处于起售中,不能删除
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //判断当前菜品是否能删除——是否被套餐关联
        List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
        if(setmealIds!=null&&setmealIds.size()>0){
            //当前菜品被套餐关联
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //删除菜品表中的菜品数据
        for(Long id:ids){
            dishMapper.deleteById(id);
            //删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        }
    }

Mapper层中

DishMapper中

    /**
     * 根据主键查询
     * @param id
     * @return
     */
    @Select("select * from dish where id = #{id}")
    Dish getById(Long id);

    /**
     *根据菜品主键删除菜品数据
     * @param id
     */
    @Delete("delete from dish where id = #{id}")
    void deleteById(Long id);

DishFlavorMapper中

    /**
     * 根据菜品id删除对应的口味数据
     * @param dishId
     */
    @Delete("delete from dish_flavor where dish_id=#{dish_id}")
    void deleteByDishId(Long dishId);

 SetmealDishMapper中

@Mapper
public interface SetmealDishMapper {

    /**
     * 根据菜品id查询套餐id
     * @param dishIds
     * @return
     */
    //select setmeal_id from setmeal_dish where dish_id in (1,2,3,4)
    List<Long> getSetmealIdsByDishIds(List<Long> dishIds);
}

对应的映射文件 

 <select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
        select setmeal_id from setmeal_dish where dish_id in
        <foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
            #{dishId}
        </foreach>
    </select>

功能那个测试就算了

修改菜品——需求分析与设计

产品原型

 接口设计 

 

 修改菜品——代码开发(1):根据id查询

Controller层

    /**
     * 根据id查询菜品
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询菜品")
    public Result<DishVO> getById(@PathVariable Long id){
        log.info("根据id查询菜品:{}",id);
        DishVO dishVO=dishService.getByIdWithFlavor(id);
        return Result.success(dishVO);
    }

Service层

    /**
     * 根据id查询菜平和对应的口味数据
     * @param id
     * @return
     */
    @Override
    public DishVO getByIdWithFlavor(Long id) {
        //根据id查询菜品数据
        Dish dish = dishMapper.getById(id);
        //根据菜品id查询口味数据
       List<DishFlavor> dishFlavors= dishFlavorMapper.getByDishId(id);
        //将查询到的数据封装到VO
        DishVO dishVO=new DishVO();
        BeanUtils.copyProperties(dish,dishVO);
        dishVO.setFlavors(dishFlavors);
        return dishVO;
    }

Mapper层

   /**
     * 根据菜品id查询对应的口味数据
     * @param dishId
     * @return
     */
    @Select("select * from dish_flavor where dish_id=#{dishId}")
    List<DishFlavor> getByDishId(Long dishId);

 修改菜品——代码开发(2)修改菜品

Controller中

    /**
     * 根据id修改菜品基本信息和对应口味信息
     * @param dishDTO
     * @return
     */
    @PutMapping
    @ApiOperation("修改菜品")
    public Result update(@RequestBody DishDTO dishDTO){
        log.info("修改菜品:{}",dishDTO);
        dishService.updateWithFlavor(dishDTO);
        return Result.success();
    }

Service中

    /**
     * 根据id修改菜品基本信息和对应口味信息
     * @param dishDTO
     */
    @Override
    public void updateWithFlavor(DishDTO dishDTO) {
        Dish dish=new Dish();
        BeanUtils.copyProperties(dishDTO,dish);

        //修改菜品表基本信息
        dishMapper.update(dish);

        //删除原有的口味数据
        dishFlavorMapper.deleteByDishId(dishDTO.getId());

        //重新插入口味数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors!=null&&flavors.size()>0){
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishDTO.getId());
            });
            //向口味表插入n条数据
            dishFlavorMapper.insertBatch(flavors);
        }
    }

Mapper中

    /**
     *根据id动态修改菜品
     * @param dish
     */
    @AutoFill(value=OperationType.UPDATE)
    void update(Dish dish);

对应的映射文件

    <update id="update">
        update dish
        <set>
            <if test="name != null">name=#{name},</if>
            <if test="categoryId != null">category_id=#{categoryId},</if>
            <if test="price != null">price=#{price},</if>
            <if test="image != null">image=#{image},</if>
            <if test="description != null">description=#{description},</if>
            <if test="status != null">status=#{status},</if>
            <if test="updateTime != null">update_time=#{updateTime},</if>
            <if test="updateUser != null">update_user=#{updateUser},</if>
        </set>
            where id=#{id}
    </update>

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

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

相关文章

项目名称:智能家居边缘网关项目

一&#xff0c;项目介绍 软件环境: C语言 硬件环境: STM32G030C8TX单片机开发板 开发工具: Linux平台GCC交叉编译环境以及ukeil (1)边缘网关概念 边缘网关是部署在网络边缘侧的网关&#xff0c;通过网络联接、协议转换等功能联接物理和数字世界&#xff0c;提供轻量化的联接管…

大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解

大语言模型的预训练[2]:GPT、GPT2、GPT3、GPT3.5、GPT4相关理论知识和模型实现、模型应用以及各个版本之间的区别详解 1.GPT 模型 1.1 GPT 模型简介 在自然语言处理问题中&#xff0c;可从互联网上下载大量无标注数据&#xff0c;而针对具体问题的有标注数据却非常少&#x…

原型设计用什么比较好?这4款值得体验

无论是UI还是UX设计师&#xff0c;工作中肯定少不了交互设计。在设计原型图时&#xff0c;一款好用的原型设计工具肯定是必不可少&#xff0c;本文就整理了4款为大家推荐&#xff0c;一起来看看吧 即时设计 即时设计是一款更适合国内UI或UX设计师和产品经理使用的原型设计工具…

如何使用Python三方库CCXT

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

<数据结构>NO11.归并排序|递归|非递归|优化

文章目录 归并排序递归写法非递归写法修正方案1.归并一段拷贝一段修正方案2.修正区间 算法优化算法分析 归并排序的应用外排序和内排序 归并排序 递归写法 思路: 如果给出两个有序数组&#xff0c;我们很容易可以将它们合并为一个有序数组。因此当给出一个无序数组时&#xf…

如何解决循环引用的问题

本文已收录于专栏 《Java》 目录 概念说明发现问题解决问题分析问题具体解决注解说明代码实现效果展示 总结提升 概念说明 循环引用是指在对象之间存在相互引用的情况。具体来说&#xff0c;当一个对象A引用了另一个对象B&#xff0c;而对象B又引用了对象A&#xff0c;它们之间…

软件研发开发人员成本计算器

写了个简单的人员工资计算器&#xff0c;用最简单的人天数计算研发投入&#xff0c;其他费用计算稍后补充完善 软件研发成本计算 ——高级工程师中级工程师初级工程师平均日工资项目阶段高级工程师人天中级工程师人天初级工程师人天调研方案产品设计软件开发测试部署培训试运…

操作系统(王道)- 初识操作系统

一、什么是操作系统&#xff1f; 操作系统可以这么理解 操作系统的定义&#xff1a; 操作系统是整个计算机的硬件和软件的管理者&#xff01;&#xff01;&#xff01; 二、操作系统的功能和目标 作为计算机硬件和软件的管理者&#xff0c;操作系统做了什么&#xff1f; 操作系…

安达发|工业系统APS软件与MES软件有哪些区别?

MES 和 APS 有什么区别&#xff1f;MES 是一个制造执行系统&#xff0c;APS 是一个高级计划排程系统系统&#xff0c;两者是互补的关系&#xff0c;APS 和 MES 可以实现计划和车间执行的闭环管理模式。MES 和 APS 有什么区别&#xff1f; mes和aps的区别: MES 是智能化工厂…

【1++的Linux】之进程(一)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;冯诺依曼与操作系统概念1.1 冯诺依曼体系结构1.2 操作系统 二&#xff0c;进程的基本概念 一&#xff0c;冯诺依曼与操作系统概念 1.1 冯诺依曼体系结构 如…

如何关闭网页版【知乎】等页面的登录弹窗(以谷歌浏览器为例)

如何关闭网页版【知乎】等页面的登录弹窗&#xff08;以谷歌浏览器为例&#xff09; 在不登陆知乎的情况下仍然可以正常浏览页面&#xff0c;可是每次打开新页面会重复出现弹窗要求用户登录。如何屏蔽掉这一弹窗呢? 在浏览器中把知乎网址设置为禁止使用javascript 在chrome的…

C#盯盘小工具,“监”

也是一个小工具&#xff0c;用来看大A股票和主要指数行情的。 如果你是一个上班族&#xff0c;同时你也是一颗小韭菜&#xff0c;a股在开市交易盘中时刻惦记着股票是涨了还是跌了&#xff0c;却不能时刻盯着手机看行情&#xff0c;也不能在电脑上开着同花顺来回切窗口&#xff…

4.CSS(一)

目录 一、CSS简介 二、CSS基础选择器 &#xff08;一&#xff09;标签选择器 &#xff08;二&#xff09;类选择器 类选择器-多类名 &#xff08;三&#xff09;id选择器 &#xff08;四&#xff09;通配符选择器 &#xff08;五&#xff09;总结 三、CSS字体属性 &…

Acwing.906 区间分组(贪心)

题目 给定N个闭区间[ai,bi]&#xff0c;请你将这些区间分成若千组&#xff0c;使得每组内部的区间两两之间(包括端点)没有交集&#xff0c;并使得组数尽可能小。 输出最小组数。 输入格式 第一行包含整数N&#xff0c;表示区间数。 接下来N行&#xff0c;每行包含两个整数ai…

【算法基础】2.2 字典树/前缀树 Trie

文章目录 知识点cpp结构体模板 模板例题835. Trie字符串统计❤️❤️❤️❤️❤️143. 最大异或对&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#xff08;Trie树的应用&#xff09; 相关题目练习208. 实现 Trie (前缀树)1804. 实现 Trie &#xff08;…

轮转数组——左旋数组,右旋数组

题目链接&#xff1a;力扣 左旋转字符串&#xff1a;【1234567】—左旋3下—>【4567123】 反转区间为前n的子串【3214567】反转区间为n到末尾的子串【3217654】反转整个字符串【4567123】 右旋转字符串&#xff1a;【1234567】—右旋3下—>【5671234】 反转整个字符…

一图看懂 pandas 模块(1):提供高性能、易用的数据结构和数据分析工具,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pandas 模块&#xff1a;提供高性能、易用的数据结构和数据分析工具&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块图&#x…

SAP-MM-物料版次

业务背景介绍 UF公司其产成品会根据客户需求进行细节上零件变更,每次都需新增物料主数据以及搭建新的BOM和对应的工艺路线进行数据处理(即对客户A0001的产成品从A0010到B0010的变化,但物料描述还是原来的描述) 新增物料编号进行库存管控是较为合理的需求,但是因UF销售业务员…

在LLM的支持下使游戏NPC具有记忆化的方法

问题 使用GPT这样的LLM去处理游戏中的NPC和玩家的对话是个很好的点子&#xff0c;那么如何处理记忆化的问题呢。 因为LLM的输入tokens是有限制的&#xff0c;所以伴随着问题的记忆context是有窗口大小限制的&#xff0c;将所有的记忆输入LLM并不现实。 所以这里看到了stanfo…

Damiler EDI 项目 Excel 方案开源介绍

准备下载和运行 Daimler EDI 到 Excel 使用 Excel 生成一系列 EDI 文档与 Daimler 通信。 下载工作流 下载示例文件 Daimler EDI & Excel 方案简介 本文将继续分享Daimler示例工作流&#xff1a;使用Excel端口和Email端口生成一系列文件&#xff0c;完成与Daimler的…