当前位置: 首页 > news >正文

Springboot3 + MyBatis-Plus + MySql + Vue + ProTable + TS 实现后台管理商品分类(最新教程附源码)

Springboot3 + MyBatis-Plus + MySql + Uniapp 商品加入购物车功能实现(针对上一篇sku)

  • 1、效果展示
  • 2、数据库设计
  • 3、后端源码
    • 3.1 application.yml 方便 AliOssUtil.java 读取
    • 3.2 model 层
    • 3.2.1 BaseEntity
    • 3.2.1 GoodsType
    • 3.2.3 GoodsTypeSonVo
    • 3.3 Controller 层
      • 3.3.1 FileUploadController.java 后端上传图片到阿里云OSS
      • 3.3.2 AliOssUtil.java 后端上传图片到阿里云OSS的工具类
      • 3.3.3 GoodsTypeController.java 商品分类接口
    • 3.4 GoodsTypeService 层
    • 3.5 GoodsTypeServiceImpl 层
  • 4、前端代码
    • 4.1 type.Vue
    • 4.2 type.Vue
    • 4.3 addOrEditType.Vue
    • 4.4 supportTypeDialog.Vue

1、效果展示


QQ2024930-15058

在这里插入图片描述

2、数据库设计


/*Navicat Premium Data TransferSource Server         : Test1Source Server Type    : MySQLSource Server Version : 80200Source Host           : localhost:3306Source Schema         : yunshangshequTarget Server Type    : MySQLTarget Server Version : 80200File Encoding         : 65001Date: 30/09/2024 15:08:28
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for goods_type
-- ----------------------------
DROP TABLE IF EXISTS `goods_type`;
CREATE TABLE `goods_type`  (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类名称',`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类描述',`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类图标',`father_id` int NULL DEFAULT NULL COMMENT '如果没有 father_id 则是一级分类',`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用 1 启用 0禁用',`type_sort` int NULL DEFAULT NULL COMMENT '排序',`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',`is_deleted` tinyint NULL DEFAULT NULL COMMENT '逻辑删除',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of goods_type
-- ----------------------------
INSERT INTO `goods_type` VALUES (1, '水果', '所有水果哈哈哈', 'https://yunshangshequ.cn-chengdu.oss.aliyuncs.com/2024.09.30/b648e907-12e1-406d-89cd-d4948b3ed317.png', NULL, '1', 999, NULL, '2024-09-30 15:01:39', 0);
INSERT INTO `goods_type` VALUES (2, '零食', '所有零食', NULL, NULL, '1', 9999, NULL, '2024-09-30 14:48:53', 0);
INSERT INTO `goods_type` VALUES (3, '西瓜', '非常好吃的西瓜', 'https://yunshangshequ.oss-cn-chengdu.aliyuncs.com/icons/icon_3212wanjasr/xiguarang.png', 1, '1', 999999, NULL, '2024-09-30 14:42:36', 0);
INSERT INTO `goods_type` VALUES (4, '葡萄', '非常好吃的葡萄', 'https://yunshangshequ.oss-cn-chengdu.aliyuncs.com/icons/icon_3212wanjasr/putao.png', 1, '1', 20, NULL, NULL, 0);
INSERT INTO `goods_type` VALUES (5, '芒果', '非常好吃的芒果12', 'https://yunshangshequ.oss-cn-chengdu.aliyuncs.com/icons/icon_3212wanjasr/mangguo.png', 1, '1', 5, NULL, '2024-09-30 15:01:17', 1);
INSERT INTO `goods_type` VALUES (6, '坚果', '非常好吃的坚果', NULL, 2, '1', 100, NULL, NULL, 0);
INSERT INTO `goods_type` VALUES (7, '辣条', '非常好吃的辣条', NULL, 2, '1', 20, NULL, NULL, 0);
INSERT INTO `goods_type` VALUES (10, '橘子', '非常好吃的橘子', 'https://yunshangshequ.oss-cn-chengdu.aliyuncs.com/icons/icon_3212wanjasr/juzi.png', 1, '1', 999, '2024-09-30 13:49:02', '2024-09-30 14:36:23', 0);
INSERT INTO `goods_type` VALUES (11, '香蕉', '非常非常好吃的香蕉', 'https://yunshangshequ.cn-chengdu.oss.aliyuncs.com/2024.09.30/404a678d-aae3-4e5b-844f-ba27643d9209.png', 1, '1', 2222, '2024-09-30 13:57:13', '2024-09-30 14:38:53', 1);
INSERT INTO `goods_type` VALUES (12, '火龙果', '非常好吃的火龙果', 'https://yunshangshequ.cn-chengdu.oss.aliyuncs.com/2024.09.30/3c18869e-f0bb-48a7-8c3e-8fd02318bfd5.png', 1, '1', 99999, '2024-09-30 13:58:54', '2024-09-30 14:25:13', 1);
INSERT INTO `goods_type` VALUES (13, '芒果', '非常好吃的芒果', 'https://yunshangshequ.cn-chengdu.oss.aliyuncs.com/2024.09.30/928d56f0-7062-4eaf-a89b-52ba43199322.png', 1, '1', 9999999, '2024-09-30 15:01:33', NULL, 0);SET FOREIGN_KEY_CHECKS = 1;

3、后端源码

3.1 application.yml 方便 AliOssUtil.java 读取

server:port: 8080
spring:servlet:multipart:max-file-size: 40MBmax-request-size: 40MBdatasource:type: com.zaxxer.hikari.HikariDataSourceurl: jdbc:mysql://localhost:3306/yunshangshequ?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2b8username: rootpassword: 123456hikari:connection-test-query: SELECT 1 # 自动检测连接connection-timeout: 60000 #数据库连接超时时间,默认30秒idle-timeout: 500000 #空闲连接存活最大时间,默认600000(10分钟)max-lifetime: 540000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟maximum-pool-size: 12 #连接池最大连接数,默认是10minimum-idle: 10 #最小空闲连接数量pool-name: SPHHikariPool # 连接池名称jackson:time-zone: GMT+8data:redis:host: localhostport: 6379database: 0
#用于打印框架生成的sql语句,便于调试
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:logic-delete-field: isDeleted # 全局逻辑删除的实体字段名logic-delete-value: 1   # 逻辑已删除的值 默认为 1logic-not-delete-value: 0 # 逻辑未删除的值  默认为 0minio:endpoint: http://localhost:9000access-key: minioadminsecret-key: minioadminbucket-name: yunshangshequ
springdoc:default-flat-param-object: truealioss: # 阿里云配置endpoint: "https://cn-chengdu.oss.aliyuncs.com"    # Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。bucketName: ""  # 填写Bucket名称,例如examplebucket。access_key: ""  # 点击头像->Accesskey管理查看 秘钥access_key_secret: "" # 密码

3.2 model 层

3.2.1 BaseEntity


package com.zhong.model.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;import java.io.Serializable;
import java.util.Date;@Data
public class BaseEntity implements Serializable {@Schema(description = "主键")@TableId(value = "id", type = IdType.AUTO)private Long id;@Schema(description = "创建时间")@TableField(value = "create_time", fill = FieldFill.INSERT)@JsonIgnoreprivate Date createTime;@Schema(description = "更新时间")@TableField(value = "update_time", fill = FieldFill.UPDATE)@JsonIgnoreprivate Date updateTime;@Schema(description = "逻辑删除")@TableField("is_deleted")@JsonIgnoreprivate Byte isDeleted;}

3.2.1 GoodsType


package com.zhong.model.entity.goods;import com.zhong.model.entity.BaseEntity;
import lombok.Data;/*** 商品分类* @TableName shop_type*/
@Data
public class GoodsType extends BaseEntity {/**/*** 分类名称*/private String name;/*** 分类描述*/private String description;/*** 排序值*/private Long typeSort;/*** 分类图标*/private String img;/*** 如果没有 father_id 则是一级分类*/private Integer fatherId;/*** 是否启用 1 启用 0禁用*/private Integer status;private static final long serialVersionUID = 1L;
}

3.2.3 GoodsTypeSonVo


package com.zhong.vo.small;import com.zhong.model.entity.goods.GoodsType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;import java.util.List;/*** @ClassName : GoodsTypeVo* @Description :* @Author : zhx* @Date: 2024-09-29 15:08*/
@Data
public class GoodsTypeSonVo {List<GoodsType> fatherType;List<GoodsType> sonType;
}

3.3 Controller 层

3.3.1 FileUploadController.java 后端上传图片到阿里云OSS


package com.zhong.controller.apartment;import com.zhong.result.Result;
import com.zhong.utils.AliOssUtil;
import io.minio.errors.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;@Tag(name = "文件管理")
@RequestMapping("/admin/file")
@RestController
public class FileUploadController {@Autowiredprivate AliOssUtil ossUtil;@Operation(summary = "上传文件")@PostMapping("/upload")public Result<String> upload(@RequestParam MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {// 获取文件原名String originalFilename = file.getOriginalFilename();// 防止重复上传文件名重复String fileName = null;if (originalFilename != null) {fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.indexOf("."));}// 把文件储存到本地磁盘
//        file.transferTo(new File("E:\\SpringBootBase\\ProjectOne\\big-event\\src\\main\\resources\\flies\\" + fileName));String url = ossUtil.uploadFile(fileName, file.getInputStream());System.out.println();return Result.ok(url);}
}

3.3.2 AliOssUtil.java 后端上传图片到阿里云OSS的工具类


package com.zhong.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.zhong.result.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @ClassName : AliOssUtil* @Description : 阿里云上传服务* @Author : zhx* @Date: 2024-03-1 20:29*/
@Component
@Service
public class AliOssUtil {@Value("${alioss.endpoint}")private String ENDPOINT;@Value("${alioss.bucketName}")private String BUCKETNAME;@Value("${alioss.access_key}")private String ACCESS_KEY;@Value("${alioss.access_key_secret}")private String ACCESS_KEY_SECRET;public String uploadFile(String objectName, InputStream inputStream) {String url = "";// 创建OSSClient实例。System.out.println(ACCESS_KEY);OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY, ACCESS_KEY_SECRET);try {// 创建PutObjectRequest对象。// 生成日期文件夹路径,例如:2022/04/18SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");String dateStr = dateFormat.format(new Date());PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKETNAME, dateStr + "/" + objectName, inputStream);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);url = "https://" + BUCKETNAME + "." + ENDPOINT.substring(ENDPOINT.lastIndexOf("/") + 1) + "/" + dateStr + "/" + objectName;} 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();}}return url;}public  Result deleteFile(String objectName) {System.out.println(objectName);// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY, ACCESS_KEY_SECRET);try {// 删除文件。System.out.println(objectName);System.out.println(objectName.replace(",", "/"));ossClient.deleteObject(BUCKETNAME, objectName.replace(",", "/"));return Result.ok("删除成功!");} 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();}}return Result.fail(555,"上传失败!");}
}

3.3.3 GoodsTypeController.java 商品分类接口


package com.zhong.controller.small;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhong.model.entity.enums.BaseStatus;
import com.zhong.model.entity.goods.GoodsType;
import com.zhong.result.Result;
import com.zhong.service.small.GoodsTypeService;
import com.zhong.vo.small.GoodsTypeSonVo;
import com.zhong.vo.small.GoodsTypeVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** @ClassName : ShopSpecsController* @Description :  商品分类* @Author : zhx* @Date: 2024-09-28 15:07*/
@Slf4j
@RestController
@Tag(name = "后台商品分类管理")
@RequestMapping("/admin/goods/type")
public class GoodsTypeController {@Autowiredprivate GoodsTypeService service;@Operation(summary = "分页获商品分类信息")@GetMapping("page")private Result<IPage<GoodsType>> page(@RequestParam long current, @RequestParam long size, GoodsTypeVo goodsTypeVo) {Page<GoodsType> goodsTypePage = new Page<>(current, size);Page<GoodsType> page = service.pageItem(goodsTypePage, goodsTypeVo);return Result.ok(page);}@Operation(summary = "获所有商品二级分类信息")@GetMapping("page/son")private Result<GoodsTypeSonVo> pageSon(@RequestParam long id) {GoodsTypeSonVo page = service.list(id);return Result.ok(page);}@Operation(summary = "获所有商品分类信息")@GetMapping("list")private Result<List<GoodsType>> page() {List<GoodsType> page = service.list();return Result.ok(page);}@Operation(summary = "根据ID修改商品分类")@PostMapping("saveOrUpdate")public Result saveOrUpdateType(@RequestBody GoodsType goodsType) {goodsType.setIsDeleted((byte) 0);service.saveOrUpdate(goodsType);return Result.ok();}@DeleteMapping("deleteById")@Operation(summary = "根据id删除商品分类")public Result removeById(@RequestParam Long id) {service.removeById(id);return Result.ok();}}

3.4 GoodsTypeService 层


package com.zhong.service.small;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zhong.model.entity.goods.GoodsType;
import com.zhong.vo.small.GoodsTypeSonVo;
import com.zhong.vo.small.GoodsTypeVo;import java.util.List;/**
* @author zhong
* @description 针对表【shop_type(商品分类)】的数据库操作Service
* @createDate 2024-09-15 18:18:13
*/
public interface GoodsTypeService extends IService<GoodsType> {Page<GoodsType> pageItem(Page<GoodsType> goodsTypePage, GoodsTypeVo goodsTypeVo);GoodsTypeSonVo list(long id);}

3.5 GoodsTypeServiceImpl 层


package com.zhong.service.small.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.zhong.mapper.small.GoodsTypeMapper;
import com.zhong.model.entity.goods.GoodsSku;
import com.zhong.model.entity.goods.GoodsType;
import com.zhong.service.small.GoodsTypeService;
import com.zhong.vo.small.GoodsTypeSonVo;
import com.zhong.vo.small.GoodsTypeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** @author zhong* @description 针对表【shop_type(商品分类)】的数据库操作Service实现* @createDate 2024-09-15 18:18:13*/
@Service
public class GoodsTypeServiceImpl extends ServiceImpl<GoodsTypeMapper, GoodsType>implements GoodsTypeService {@Autowiredprivate GoodsTypeMapper mapper;@Overridepublic Page<GoodsType> pageItem(Page<GoodsType> goodsTypePage, GoodsTypeVo goodsTypeVo) {LambdaQueryWrapper<GoodsType> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.isNull(GoodsType::getFatherId).eq(GoodsType::getIsDeleted, 0);if (goodsTypeVo.getName() != null) {queryWrapper.like(GoodsType::getName, goodsTypeVo.getName());}if (goodsTypeVo.getId() != null) {queryWrapper.like(GoodsType::getId, goodsTypeVo.getId());}queryWrapper.orderByDesc(GoodsType::getTypeSort);return mapper.selectPage(goodsTypePage, queryWrapper);}@Overridepublic GoodsTypeSonVo list(long id) {GoodsTypeSonVo goodsTypeSonVo = new GoodsTypeSonVo();// 获取父分类LambdaQueryWrapper<GoodsType> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(GoodsType::getIsDeleted, 0).eq(GoodsType::getId, id);List<GoodsType> goodsTypes = mapper.selectList(queryWrapper);goodsTypeSonVo.setFatherType(goodsTypes);// 获取子分类LambdaQueryWrapper<GoodsType> sonQueryWrapper = new LambdaQueryWrapper<>();sonQueryWrapper.eq(GoodsType::getIsDeleted, 0).eq(GoodsType::getFatherId, id).orderByDesc(GoodsType::getTypeSort);List<GoodsType> sonGoodsTypes = mapper.selectList(sonQueryWrapper);goodsTypeSonVo.setSonType(sonGoodsTypes);return goodsTypeSonVo;}
}

4、前端代码

4.1 type.Vue


<template><el-uploadv-bind="$attrs":action="UPLOAD_IMG_URL":on-preview="handlePictureCardPreview":headers="{ 'access-token': useUserStore().token }"><el-icon><Plus /></el-icon></el-upload><el-dialog v-model="dialogVisible"><el-image :src="dialogImageUrl" fit="fill" /></el-dialog>
</template>
<script setup lang="ts">
import { UPLOAD_IMG_URL } from '@/api/upload'
import { ref } from 'vue'
import { UploadFile } from 'element-plus/es/components/upload/src/upload'
import { useUserStore } from '@/store/modules/user'const dialogImageUrl = ref('')
const dialogVisible = ref(false)
function handlePictureCardPreview(uploadFile: UploadFile) {dialogImageUrl.value = uploadFile.url!dialogVisible.value = true
}
</script>
<style scoped lang="scss"></style>

4.2 type.Vue


<template><div><ProTable ref="proTable" :dataCallback="dataCallback" :columns="columns" :requestApi="getTypeListPageApi":initParam="initParam"><template #tableHeader><el-button type="primary" icon="Plus" @click="addHandle">添加</el-button></template><!-- 表格操作 --><template #operation="scope"><el-button type="primary" link icon="Edit" @click="editHandle(scope.row)">编辑</el-button><el-button type="primary" link icon="Delete" @click="handleDelete(scope.row)">删除</el-button></template></ProTable><PostDialog ref="DialogRef" /></div>
</template><script setup lang="tsx">
import { reactive, ref } from 'vue'
import { ColumnProps } from '@/components/ProTable/src/types'
import { useHandleData } from '@/hooks/useHandleData'
import { useRouter } from 'vue-router'
const router = useRouter();
import {getTypeListPageApi,// addGoodsTypeApi,// // updateGoodsTypeStatusApi,// updateGoodsTypeApi
} from '@/api/goodsType'import { PostInterfacesRes } from '@/api/goodsType/types'// *获取 ProTable 元素,调用其获取刷新数据方法
const proTable = ref()// *查询参数
const initParam = reactive({})// 处理返回的数据格式
const dataCallback = (data: any) => {return {list: data?.records,total: data?.total,}
}// 新增商品
// 新增
const addHandle = () => {router.push({path: '/small/type/addOrEditGoods',})
}
// 查看
const editHandle = (row: PostInterfacesRes) => {console.log(row)router.push({path: '/small/type/addOrEditGoods',query: {id: row.id,},})
}
// *根据id删除用户
const handleDelete = async (row: PostInterfacesRes) => {// await useHandleData(deleteSysPostById, row.id, `删除${row.id}`)proTable.value?.getTableList()
}// *表格配置项
const columns: ColumnProps[] = [{ type: 'index', label: '序号', width: 100 },{prop: 'id',label: '分类ID',search: { el: 'input', props: { placeholder: '请输入分类编码' } },},{prop: 'name',label: '分类名称',search: { el: 'input', props: { placeholder: '请输入分类名称' } },},{prop: 'description',label: '分类描述',},{prop: 'typeSort',label: '分类排序',},{prop: 'status',label: '状态',width: 100,enum: [{ label: '正常', value: 1 },{ label: '停用', value: 0 },],render: ({ row }) => {return (<el-switchactive-value={1}inactive-value={0}v-model={row.status}onChange={() => updateGoodsTypeStatusApi(row.id, row.status)}></el-switch>)},},{ prop: 'operation', label: '操作', fixed: 'right', width: 280 },
]
</script>

4.3 addOrEditType.Vue


<!--* @Date: 2024-08-17 14:18:14* @LastEditors: zhong* @LastEditTime: 2024-09-30 14:57:38* @FilePath: \admin\src\views\small\type\components\addOrEditType.vue
-->
<template><el-card><template #header><div class="card-header"><span>{{ formData.id ? '修改' : '新增' }}商品分类</span></div></template><el-card><template #header><div class="card-header"><span>{{ formData.id ? '修改' : '新增' }}商品一级分类</span></div></template><div style="display: flex;align-items: center;"><div style="flex: 1;"><el-form ref="typeFormRef" :model="formData" :rules="rules" label-width="120px" style="max-width: 660px"status-icon><el-form-item label="分类名称" prop="name"><el-input v-model="formData.name" /></el-form-item><el-form-item label="分类简介" prop="description"><el-input type="textarea" v-model="formData.description" /></el-form-item><el-form-item label="分类排序" prop="typeSort"><el-input v-model="formData.typeSort" /></el-form-item><el-form-item label="是否启用" prop="status"><el-radio-group v-model="formData.status" class="ml-4"><el-radio :label="UserStatus.DISABLED">{{getLabelByValue(UserStatusMap,UserStatus.DISABLED,)}}</el-radio><el-radio :label="UserStatus.NORMAL">{{getLabelByValue(UserStatusMap,UserStatus.NORMAL,)}}</el-radio></el-radio-group></el-form-item></el-form></div><!-- 上传操作 --><div style="width: 200px;display: flex;flex-direction: column;padding-bottom: 60px;"><text label="商品主图" /><upload-img v-model:file-list="formData.img" :on-success="uploadSuccessHandle" :on-remove="uploadRemoveHandle"list-type="picture-card" :limit="1" :class="listLengthTag === 1 ? 'hide_box' : ''"></upload-img></div></div></el-card><el-card class="m-t-20"><template #header><div class="card-header"><span>{{ formData.id ? '修改' : '新增' }}商品二级分类</span></div></template><el-row class="container"><el-col :span="2" class="text-center">二级分类</el-col><el-col :span="22" class="item-container"><el-popconfirm v-for="item in goodsTypeList || []" :key="item.id" width="220" confirm-button-text="删除"cancel-button-text="修改" cancel-button-type="warning" confirm-button-type="danger"@confirm="deleteFacilityHandle(item)" @cancel="editTypeHandle(item)" :title="`修改或直接删除${item.name}`"><template #reference><div class="item m-r-10 m-t-10 pointer"><el-image style="width: 30px; height: 30px" :src="item.img" /><span>{{ item.name }}</span></div></template></el-popconfirm><el-icon class="item m-r-10 m-t-5 pointer" :size="35" color="#567722" @click="addTypeDialog(formData)"><CirclePlus /></el-icon></el-col></el-row><!--   商品二级分类信息修改弹窗管理--><SupportTypeDialog ref="supportTypeDialog" :updateFacility="getTypeListHandle"></SupportTypeDialog></el-card><!--  --><!-- 底部保存或取消按钮 --><div class="flex-center m-t-20"><el-button style="width: 150px" type="info" @click="router.back()">取消</el-button><el-button style="width: 150px" type="primary" @click="submitHandle">{{ formData.id ? '保存' : '新增' }}</el-button></div></el-card>
</template><script setup lang="ts">
import { onMounted, ref, reactive, computed } from 'vue'
import { FacilityInfoInterface } from '@/api/apartmentManagement/types'
// import { PageResponseInterface } from '@/api/type/types'
import {deleteGoodsTypeByIdApi,getTypeSonListApi,saveOrUpdateGoodsTypeApi,} from '@/api/goodsType'import {getLabelByValue,UserStatus,UserStatusMap
} from '@/enums/constEnums'import { UploadFile } from 'element-plus/es/components/upload/src/upload'
import UploadImg from '@/components/uploadImg/uploadImg.vue'
import SupportTypeDialog from "./supportTypeDialog.vue"
import { ElMessage, FormInstance, UploadFiles } from 'element-plus'import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()type typeFromData = {id: stringname: stringdescription: stringtypeSort: stringstatus: stringimg: any[]
}// 父类分类信息
const formData = ref<typeFromData>({id: "",name: "",description: "",typeSort: "",status: "",img: []
})const typeFormRef = ref<FormInstance>()
// 清空表单数据的函数
const clearFormData = () => {formData.value.id = "";formData.value.name = "";formData.value.description = "";formData.value.typeSort = "";formData.value.status = "";formData.value.img = [];
};
// 表单验证规则
const rules = reactive({name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],description: [{ required: true, message: '请输入分类介绍', trigger: 'blur' },],typeSort: [{ required: true, message: '请输入分类排序数值越大越靠前', trigger: 'blur' }],
})// 图片上传成功
function uploadSuccessHandle(response: any,uploadFile: UploadFile,uploadFiles: UploadFiles,) {console.log(uploadFile);formData.value.img = uploadFiles?.map((item) => {return {...item,url: (item?.response as any)?.data.url || item.url,}})console.log(formData.value.img);
}
// TODO 控制上传图片数量隐藏上传按钮
const listLengthTag = computed(() => {return formData.value.img.length;
});
// 移除图片
const uploadRemoveHandle = (uploadFiles: UploadFiles, uploadFile: UploadFile) => {console.log(uploadFiles);console.log(uploadFile);
}const supportTypeDialog = ref<any>()// 修改后刷新数据
const getTypeListHandle = () => {if (route.query?.id) {getGoodsInfoList(route.query.id as string)}
}// 子类分类信息
const goodsTypeList = ref<any>([])// 获取分类信息
async function getGoodsInfoList(id: string | number) {try {const { data } = await getTypeSonListApi(id);console.log(data);formData.value = data.fatherType?.[0];formData.value.img = [{ name: formData.value.name, url: formData.value.img }];console.log(formData.value);goodsTypeList.value = data.sonType;} catch (error) {console.log(error)}
}// 删除分类
const deleteFacilityHandle = async (item: any) => {console.log('删除分类', item)try {await deleteGoodsTypeByIdApi(item.id)await getTypeListHandle()ElMessage.success('操作成功')} catch (error) {console.log(error)}
}
// 编辑分类
const editTypeHandle = (item: typeFromData) => {console.log('编辑分类', item)supportTypeDialog.value?.show(item)
}
// 添加分类
const addTypeDialog = (item: any) => {console.log('添加分类', item)supportTypeDialog.value?.show({ type: item.id })
}// 新增或更新商品分类信息
async function addOrUpdateTypeHandle() {try {console.log(formData.value);let res = JSON.parse(JSON.stringify(formData.value));// 判断图片改变没有if (res.img?.[0]?.response) {res.img = res.img[0].response.data;} else {res.img = res.img[0].url;}await saveOrUpdateGoodsTypeApi(res);clearFormData();ElMessage.success('操作成功')router.back()} catch (error) {console.log(error)}
}
// 提交
function submitHandle() {typeFormRef.value?.validate(async (valid) => {if (valid) {await addOrUpdateTypeHandle()} else {ElMessage.error('表单填写有误,请检查')return false}})
}
onMounted(() => {if (route.query?.id) {getGoodsInfoList(route.query.id as string)}
})
</script><style scoped lang="scss">
::v-deep(.hide_box .el-upload.el-upload--picture-card) {display: none !important;
}.card-header {font-size: 18px;font-weight: bold;
}.text-center {display: flex;align-items: center;justify-content: flex-start;text-align: center;
}.container:not(:first-child) {margin-top: 20px;
}.item-container {display: flex;flex-wrap: wrap;align-items: center;justify-content: flex-start;width: 100%;padding: 10px 15px;background-color: #efefef;border-radius: 20px;.item {position: relative;display: flex;flex-direction: column;align-items: center;justify-content: center;// width: 50px;}
}
</style>

4.4 supportTypeDialog.Vue

<!--* @Date: 2024-09-29 19:45:25* @LastEditors: zhong* @LastEditTime: 2024-09-30 15:00:22* @FilePath: \admin\src\views\small\type\components\supportTypeDialog.vue
-->
<template><el-dialog v-model="dialogFormVisible" :close-on-press-escape="true" :destroy-on-close="true" :title="title"style="max-width: 700px"><div style="display: flex;align-items: center;"><div style="flex: 1;"><el-form ref="formRef" :model="formData" :rules="rules" label-width="120px" style="max-width: 660px"status-icon><el-form-item label="分类名称" prop="name"><el-input v-model="formData.name" /></el-form-item><el-form-item label="分类简介" prop="description"><el-input type="textarea" v-model="formData.description" /></el-form-item><el-form-item label="分类排序" prop="typeSort"><el-input v-model="formData.typeSort" /></el-form-item><el-form-item label="是否上架" prop="status"><el-radio-group v-model="formData.status" class="ml-4"><el-radio :label="UserStatus.DISABLED">{{getLabelByValue(UserStatusMap,UserStatus.DISABLED,)}}</el-radio><el-radio :label="UserStatus.NORMAL">{{getLabelByValue(UserStatusMap,UserStatus.NORMAL,)}}</el-radio></el-radio-group></el-form-item></el-form></div><!-- 上传操作 --><div style="width: 200px;display: flex;flex-direction: column;padding-left: 60px;padding-bottom: 70px;"><text label="商品主图" prop="mainImage" /><upload-img v-model:file-list="formData.img" :on-success="uploadSuccessHandle" :on-remove="uploadRemoveHandle"list-type="picture-card" :limit="1" :class="listLengthTag === 1 ? 'hide_box' : ''"></upload-img></div></div><template #footer><span class="dialog-footer"><el-button @click="close">取消</el-button><el-button type="primary" @click="submitHandle">确定</el-button></span></template></el-dialog></template>
<script setup lang="ts">
import ids from 'virtual:svg-icons-names'
import { computed, ref } from 'vue'
import { FacilityInfoInterface } from '@/api/apartmentManagement/types'
import { ElMessage, FormInstance, FormRules, UploadFiles } from 'element-plus'
import { saveOrUpdateFacilityInfo } from '@/api/apartmentManagement'
import { UploadFile } from 'element-plus/es/components/upload/src/upload'
import UploadImg from '@/components/uploadImg/uploadImg.vue'
import {getLabelByValue,UserStatus,UserStatusMap
} from '@/enums/constEnums'
import {saveOrUpdateGoodsTypeApi,
} from '@/api/goodsType'
const props = defineProps({updateFacility: {type: Function,default: () => ({}),},
})
const defaultFormData = {id: '',description: '',name: '',status: "",fatherId: "",typeSort: "",img: [],
}const formRef = ref<FormInstance>()const dialogFormVisible = ref(false)
const formData = ref<any>({...defaultFormData,
})
// 清空表单数据的函数
const clearFormData = () => {formData.value.id = "";formData.value.name = "";formData.value.description = "";formData.value.typeSort = "";formData.value.status = "";formData.value.img = [];
};
// 表单验证规则
const rules = ref<FormRules>({name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],description: [{ required: true, message: '请选择分类描述', trigger: 'change' }],typeSort: [{ required: true, message: '请输入分类排序数值越大越靠前', trigger: 'change' }],
})const title = computed(() => {return ((formData.value.id ? '修改' : '新增') + formData.value.name + '二级分类详情')
})// 图片上传成功
// TODO 控制上传图片数量隐藏上传按钮
const listLengthTag = computed(() => {return formData.value.img.length;
});
function uploadSuccessHandle(response: any,uploadFile: UploadFile,uploadFiles: UploadFiles,) {console.log(uploadFile);formData.value.img = uploadFiles?.map((item) => {return {...item,url: (item?.response as any)?.data.url || item.url,}})console.log(formData.value.img);
}
// 移除图片
const uploadRemoveHandle = (uploadFiles: UploadFiles, uploadFile: UploadFile) => {console.log(uploadFiles);console.log(uploadFile);
}
const isEdit = ref(false);
// 展示方法
const show = (data: Partial<any> = defaultFormData) => {console.log('show', data)if (data.fatherId != null) {formData.value = Object.assign({}, defaultFormData, data)formData.value.img = [{ name: data.name, url: data.img }];} else {formData.value.fatherId = data.type;formData.value.status = 1;isEdit.value = true;}dialogFormVisible.value = true
}
// 关闭方法
const close = () => {dialogFormVisible.value = false
}// 提交方法
const submitHandle = () => {formRef.value?.validate(async (valid) => {if (valid) {let res = JSON.parse(JSON.stringify(formData.value));if (isEdit && res.img?.[0]?.response) {res.img = res.img[0].response.data;} else {res.img = res.img[0].url;}await saveOrUpdateGoodsTypeApi(res)clearFormData();await props.updateFacility()ElMessage.success('操作成功')close()} else {ElMessage.error('表单填写有误,请检查')return false}})
}
// 对外暴露
defineExpose({show,close,
})
</script><style scoped lang="scss">
::v-deep(.hide_box .el-upload.el-upload--picture-card) {display: none !important;
}.icon-option {display: flex;align-items: center;
}
</style>

相关文章:

Springboot3 + MyBatis-Plus + MySql + Vue + ProTable + TS 实现后台管理商品分类(最新教程附源码)

Springboot3 MyBatis-Plus MySql Uniapp 商品加入购物车功能实现&#xff08;针对上一篇sku&#xff09; 1、效果展示2、数据库设计3、后端源码3.1 application.yml 方便 AliOssUtil.java 读取3.2 model 层3.2.1 BaseEntity3.2.1 GoodsType3.2.3 GoodsTypeSonVo3.3 Controll…...

消费电子制造企业如何使用SAP系统提升运营效率与竞争力

在当今这个日新月异的消费电子市场中&#xff0c;企业面临着快速变化的需求、激烈的竞争以及不断攀升的成本压力。为了在这场竞赛中脱颖而出&#xff0c;消费电子制造企业纷纷寻求数字化转型的突破点&#xff0c;其中&#xff0c;SAP系统作为业界领先的企业资源规划(ERP)解决方…...

算法记录——树

二叉树 3.1二叉树的最大深度 思路&#xff1a;二叉树的最大深度 根节点的最大高度。因此本题可以转换为求二叉树的最大高度。 而求高度的时候应该采用后序遍历。遍历顺序为&#xff1a;左右中。每次遍历的节点按后序遍历顺序&#xff0c;先收集左右孩子的最大高度&#xff0c;…...

单片机在控制和自动化任务中的应用场景广泛

单片机在控制和自动化任务中的应用场景广泛&#xff0c;以下是一些具体示例&#xff1a; 1. 家电控制 洗衣机&#xff1a;单片机用于控制洗衣周期、温度和水位。微波炉&#xff1a;控制加热时间、功率和用户界面。 2. 工业自动化 生产线监控&#xff1a;单片机用于控制传送…...

UEFI EDK2框架学习(三)——protocol

一、Protocol协议 搜索支持特定Protocol的设备&#xff0c;获取其Handle gBS->LocateHandleBuffer 将内存中的Driver绑定到给定的ControllerHandle gBS->OpenProtocol 二、代码实现 Protocol.c #include <Uefi.h> #include <Library/UefiLib.h> #includ…...

PostgreSQL的字段存储类型了解

PostgreSQL的字段存储类型了解 在 PostgreSQL 中&#xff0c;每个字段&#xff08;列&#xff09;都有其存储类型&#xff0c;这些存储类型决定了数据库如何存储和处理该字段的数据。了解和适当地利用这些存储类型&#xff0c;可以提高数据库的性能和存储效率。 主要的存储类…...

CTFshow 命令执行 web29~web36(正则匹配绕过)

目录 web29 方法一&#xff1a;include伪协议包含文件读取 方法二&#xff1a;写入文件 方法三&#xff1a;通识符 web30 方法一&#xff1a;filter伪协议文件包含读取 方法二&#xff1a;命令执行函数绕过 方法三&#xff1a;写入文件 web31 方法一&#xff1a;filter伪…...

【顺序表使用练习】发牌游戏

【顺序表使用练习】发牌游戏 1. 介绍游戏2. 实现52张牌3. 实现洗牌4. 实现发牌5. 效果展示 1. 介绍游戏 首先先为大家介绍一下设计要求 实现52张牌&#xff08;这里排除大小王&#xff09;洗牌——打乱牌的顺序发牌——3个人&#xff0c;1人5张牌 2. 实现52张牌 创建Code对象创…...

1.7 编码与调制

欢迎大家订阅【计算机网络】学习专栏&#xff0c;开启你的计算机网络学习之旅&#xff01; 文章目录 前言前言1 基本术语2 常用的编码方法2.1 不归零编码2.2 归零编码2.3 反向归零编码2.4 曼彻斯特编码2.5 差分曼彻斯特编码 3 常用的调制方法3.1 调幅&#xff08;AM&#xff09…...

004集—— txt格式坐标写入cad(CAD—C#二次开发入门)

如图所示原始坐标格式&#xff0c;xy按空格分开&#xff0c;将坐标按顺序在cad中画成多段线&#xff1a; 坐标xy分开并按行重新输入txt&#xff0c;效果如下&#xff1a; 代码如下 &#xff1a; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; us…...

CSS中的font-variation-settings:探索字体的可变性

随着Web字体的发展&#xff0c;设计师们不再局限于传统的字体样式。现代Web字体支持可变字体&#xff08;Variable Fonts&#xff09;&#xff0c;这种字体允许开发者在单一的字体文件中包含多种字形样式。通过使用CSS中的font-variation-settings属性&#xff0c;我们可以控制…...

组合优化与凸优化 学习笔记5 对偶拉格朗日函数

有的时候约束条件有点难搞&#xff0c;我们可以把它放到目标函数里面。 记得之前凸函数的时候的结论吗&#xff1f;一大堆函数&#xff0c;每一段都取最大的&#xff0c;最后会得到一个凸函数。同理&#xff0c;每一段都取最小的&#xff0c;得到的是一个凹函数。就这样&#x…...

监控易监测对象及指标之:Exchange邮件服务器监测

在现代企业运营中&#xff0c;邮件服务器的作用至关重要&#xff0c;它不仅承载着企业内外的信息传递&#xff0c;还是协同工作的重要工具。为了确保邮件服务器的稳定运行&#xff0c;以及邮件的顺畅收发&#xff0c;采用高效的监控系统是不可或缺的。监控易作为一款专业的监控…...

【机器学习基础】Transformer学习

Transformer学习 梯度消失FeedForward层激活函数的主要作用是在网络中加入非线性变换 梯度消失 梯度爆炸 FeedForward层 Transformer结构: Transformer结构主要分为两大部分: 一是Encoder层结构:Encoder 的输入由 Input Embedding 和 Positional Embedding 求和输入Multi…...

mysql如何不使用窗口函数,去统计出入库情况

mysql如何不使用窗口函数&#xff0c;去统计出入库情况 你把这个表看做 进出库表&#xff0c;每个物料把时间正序后 依次累加数量 &#xff0c;看这个物料的时间线上 是否会出现负数&#xff0c;1号进货5个 2号出库3个 3号你不能出库3个 最多俩个 不然就是负库存&#xff0c;…...

uni-app canvas文本自动换行

封装 支持单行文本超出换行。多行文本顺位排版 // 填充自动换行的文本function fillFeedText({ctx, text, x, y, maxWidth, lineHeight, color, size}) {// 文本配置ctx.setFontSize(size);ctx.setFillStyle(color);// 计算文本换行宽高&#xff0c;换行逻辑const words text…...

【设计模式-职责链】

定义 职责链模式是一种行为设计模式&#xff0c;**它通过将请求发送给链上的多个处理者来避免请求发送者与处理者之间的紧密耦合。每个处理者可以选择处理请求或将其传递给链中的下一个处理者。**这样&#xff0c;可以将处理请求的责任链式组织&#xff0c;从而实现更灵活的请…...

Prompt:在AI时代,提问比答案更有价值

你好&#xff0c;我是三桥君 随着AI技术的飞速发展&#xff0c;我们进入了一个信息爆炸的时代。在这个时代&#xff0c;只要你会提问&#xff0c;AI就能为你提供满意的答案。这种现象让很多人开始思考&#xff1a;在这个答案触手可及的时代&#xff0c;答案的价值是否还像以前…...

whatis命令:关于命令的简短描述

一、命令简介 ​whatis​ 命令用于查询命令、函数、文件等的基本用途&#xff0c;查询结果只是一句简短的描述。 例如 $ whatis ls ls (1) - list directory contents返回关于 ls 命令的简短描述。这个结果实质是来自于man手册的一个章节&#xff0c;在较新的L…...

ICM20948 DMP代码详解(54)

接前一篇文章:ICM20948 DMP代码详解(53) 上一回解析了inv_icm20948_compass_dmp_cal函数的大部分代码,本回继续讲解inv_icm20948_compass_dmp_cal函数的余下内容。为了便于理解和回顾,再次贴出inv_icm20948_compass_dmp_cal函数代码,在EMD-Core\sources\Invn\Devices\Dri…...

RabbitMQ的应用问题

一、幂等性保障 幂等性是数学和计算机科学中某些运算的性质, 它们可以被多次应⽤, ⽽不会改变初始应⽤的结果 数学上的幂等性&#xff1a; f(x)f(f(x)) |x| 数据库操作幂等性&#xff1a; 数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性…...

C++14:通过make_index_sequence实现将tuple转换为array

如何将vector转换为array呢 #include <iostream> #include <tuple> #include <array> using namespace std;template <typename V, typename... Types, size_t... I> constexpr auto do_tuple_to_array(tuple<V, Types...>&& tuple, in…...

Linux中修改MySQL密码

Linux中MySQL的密码操作 1、给用户设置/更新密码 mysqladmin -u用户名 -p原密码 password "新密码"该命令在终端直接执行&#xff0c;不需要进入mysql视图 该命令适用于以下情况&#xff1a; 用户的密码为空&#xff0c;为用户设置密码用户密码需要更新&#xff0c…...

华为OD真题机试-英文输入法(Java)

华为OD机试真题中的“英文输入法”题目主要考察的是字符串处理、单词提取、以及基于前缀的单词联想功能。以下是对该题目的详细解析&#xff1a; 题目描述 主管期望你来实现英文输入法单词联想功能。具体需求如下&#xff1a; 依据用户输入的单词前缀&#xff0c;从已输入的…...

【React 】入门Day01 —— 从基础概念到实战应用

目录 一、React 概述 二、开发环境创建 三、JSX 基础 四、React 的事件绑定 五、React 组件基础使用 六、组件状态管理 - useState 七、组件的基础样式处理 快速入门 – React 中文文档 一、React 概述 React 是什么 由 Meta 公司开发&#xff0c;是用于构建 Web 和原生…...

2024年9月总结及随笔之丢卡

1. 回头看 日更坚持了639天。 读《软件开发安全之道&#xff1a;概率、设计与实施》更新完成读《软件设计的要素》开更并更新完成读《构建可扩展分布式系统&#xff1a;方法与实践》开更并更新完成读《数据湖仓》开更并持续更新 2023年至2024年9月底累计码字1555996字&#…...

sql语法学习 sql各种语法 sql增删改查 数据库各种操作 数据库指令

sql语法学习 sql各种语法 sql增删改查 数据库各种操作 数据库指令 学习SQL语法时&#xff0c;理解其基本结构和用法是关键。下面是SQL语法的详细学习指南&#xff0c;涵盖了SQL的主要部分&#xff0c;包括查询、插入、更新、删除、表操作等。 1. 基本查询语法 SQL 的查询语句…...

鸡兔同笼,但是线性代数

灵感来自&#xff1a;bilibili&#xff0c;巨佬&#xff01; 我们有 14 14 14 个头&#xff0c; 32 32 32 只脚&#xff0c;所有鸡和兔都没有变异&#xff0c;头和脚都完整&#xff0c;没有数错。还有什么 Bug 吗 小学奥数 假设全是鸡&#xff0c;则有 14 2 28 14 \time…...

01---java面试八股文——springboot---10题

01-你是怎么理解Spring Boot 的约定优于配置 约定优于配置是一种软件设计的范式&#xff0c;它的核心思想是减少软件开发人员对于配置项的维护&#xff0c;从而让开发人员更加聚焦在业务逻辑上。Spring Boot 就是约定优于配置这一理念下的产物&#xff0c;它类似于 Spring 框架…...

计算机毕业设计 二手图书交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…...

兴国做网站/上首页seo

小程序的视图与渲染 组件的基本使用 在官方文档当中&#xff0c;我们可以找到组件一栏&#xff0c;在那里就可以学习到基本组件的使用了。 数据绑定 在.wxss中通过{{}}就可以定义数据的变量名称&#xff0c;而在.js文件中的data就可以对数据进行初始化&#xff0c;这就完成…...

苏州网站制作/青岛百度推广优化

玩手机&#xff0c;玩相机&#xff0c;一直是从大学毕业以来每天的必想。我的手机生涯从毕业第三年开始&#xff0c;一晃快十年了&#xff0c;友人网是我常去的地方&#xff0c;当初注册的 “ 常来看看 ” 把后来的未来预测的很准。从玩手机到研究手机&#xff0c;现在集中自有…...

用c 做网站设计系统的项目作业/成都网站seo排名优化

关于Debug和Release之本质区别的讨论本文主要包含如下内容&#xff1a;1. Debug 和 Release 编译方式的本质区别2. 哪些情况下 Release 版会出错2. 怎样“调试” Release 版的程序 一、Debug 和 Release 编译方式的本质区别Debug 通常称为调试版本&#xff0c;它包含调试信息&a…...

网站建设资费/谷歌搜索引擎入口

搜索引擎之中文分词实现&#xff08;java版&#xff09;前几天读到google研究员吴军的数学之美系列篇&#xff0c;颇有感触。而恰好自己前段时间做了个基于统计语言模型的中文切分系统的课程项目&#xff0c;于是乎&#xff0c;帖出来与大家共同学习。分词技术在搜索引擎&#…...

广州商城网站建设/百度关键词查询工具

问题&#xff1a; 有位来自日本的用户发邮件&#xff0c;请求我们在Spotfire报表&#xff08;趋势分析报告&#xff09; 网页上添加一个“Edit”按钮。说是以前是有的&#xff0c;现在的版本中找不到了。她需要对Spotifre的报表做一些优化&#xff0c;再报告给相关试验的CRA们…...

做网站需要什么执照/百度推广平台

查询mysql数据库时&#xff0c;同样的输入需要不止一次获取值或者一个查询需要做大量运算时&#xff0c;很容易会想到使用redis缓存。但是如果查询并发量特别大的话&#xff0c;请求redis服务也会特别耗时&#xff0c;这种场景下&#xff0c;将redis迁移到本地减少查询耗时是一…...