1.项目架构

2.config配置

JdbcConfig

public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager ds = new DataSourceTransactionManager(dataSource);
        return ds;
    }

}

 MyBatisConfig

public class MyBatisConfig {

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setTypeAliasesPackage("cn.itaxu.domain");
        factoryBean.setDataSource(dataSource);
        return factoryBean;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("cn.itaxu.dao");
        return msc;
    }

}

ServletConfig

public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    // 加载spring配置
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    // 加载springMVC配置
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    // 设置哪些方法归属springMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 处理POST请求中文乱码问题
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter("UTF-8");
        return new Filter[]{filter};
    }

}

SpringConfig

@Configuration
@ComponentScan("cn.itaxu.service")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}

SpringMvcConfig

@Configuration
@ComponentScan({"cn.itaxu.controller","cn.itaxu.config"})
@EnableWebMvc
public class SpringMvcConfig {
}

SpringMvcSupport

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/img/**").addResourceLocations("/img/");
    }
}

3.controller控制

BrandController

@RestController
@RequestMapping("/brands")
public class BrandController {

    @Autowired
    private BrandService brandService;

    @PostMapping
    public Result save(@RequestBody Brand brand){
        boolean flag = brandService.save(brand);
        return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
    }

    @DeleteMapping("/{id}")
    public Result deleteById(@PathVariable Integer id){
        boolean flag = brandService.deleteById(id);
        return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
    }

    @DeleteMapping
    public Result deleteMultiply(@RequestBody int[] ids){
        boolean flag = brandService.deleteMultiply(ids);
        return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
    }

    @PutMapping
    public Result update(@RequestBody Brand brand){
        System.out.println(brand);
        boolean flag = brandService.update(brand);
        return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id){
        Brand brand = brandService.getById(id);
        Integer code =brand != null ? Code.GET_OK:Code.GET_ERR;
        String msg = brand != null ? "success":"fail";
        return new Result(code,brand,msg);
    }

    @GetMapping
    public Result getAll(){
        List<Brand> brandList = brandService.getAll();
        Integer code = brandList != null ? Code.GET_OK:Code.GET_ERR;
        String msg = brandList != null ? "success":"fail";
        return new Result(code,brandList,msg);
    }
    
    @PostMapping("/{currentPage}/{pageSize}")
    public Result selectByPageAndCondition(@PathVariable int currentPage,@PathVariable int pageSize,
                                           @RequestBody Brand brand) {
        PageBean<Brand> pageBean = brandService.selectByPageAndCondition(currentPage, pageSize, brand);
        Integer code = pageBean != null ? Code.GET_OK:Code.GET_ERR;
        String msg = pageBean != null ? "success":"fail";
        return new Result(code,pageBean,msg);
    }
}

Code 响应状态码

public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;

    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;

    public static final Integer BUSINESS_ERR = 60002;
}
ProjectExceptionAdvice 项目异常通知
@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex){
        // 记录日志
        // 发送消息给运维
        // 发送消息给开发人员,ex对象发送给开发人员
        return new Result(ex.getCode(),"null","系统异常");
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex){
        return new Result(ex.getCode(),"null","业务异常");
    }


    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
        // 记录日志
        // 发送消息给运维
        // 发送消息给开发人员,ex对象发送给开发人员
        return new Result(Code.SYSTEM_UNKNOW_ERR,"null","系统繁忙,请稍后再试!");
    }
}

Result 统一格式数据

public class Result {
    private Object data;
    private Integer code;
    private String  msg;

    public Result() {
    }

    public Result(Integer code,Object data) {
        this.data = data;
        this.code = code;
    }

    public Result(Integer code, Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}

4.exception 细化异常

BusinessException 业务异常

public class BusinessException extends RuntimeException{
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}
SystemException 系统异常
public class SystemException extends RuntimeException{
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}

5.service

BrandService接口

@Transactional
public interface BrandService {

    /**
     * 添加数据
     * @param brand
     * @return
     */
    public boolean save(Brand brand);

    /**
     * 根据id删除
     * @param id
     * @return
     */
    public boolean deleteById(Integer id);

    /**
     * 根据ids批量删除
     * @param ids
     * @return
     */
    public boolean deleteMultiply(@Param("ids") int[] ids);

    /**
     * 修改数据
     * @param brand
     * @return
     */
    public boolean update(Brand brand);

    /**
     * 查询单条
     * @param id
     * @return
     */
    public Brand getById(Integer id);

    /**
     * 查询所有
     * @return
     */
    public List<Brand> getAll();

    /**
     * 分页查询
      * @param currentPage
     * @param pageSize
     * @return
     */
    PageBean<Brand> selectByPage(int currentPage, int pageSize);

    /**
     * 分页条件查询
     * @param currentPage
     * @param pageSize
     * @param brand
     * @return
     */
    PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand);
}

BrandServiceImpl

@Service
public class BrandServiceImpl implements BrandService {
    @Autowired
    private BrandDao brandDao;
    
    @Override
    public boolean save(Brand brand) {
        return brandDao.save(brand) > 0;
    }

    @Override
    public boolean deleteById(Integer id) {
        return brandDao.deleteById(id) > 0;
    }

    @Override
    public boolean deleteMultiply(int[] ids) {
        return brandDao.deleteMultiply(ids) > 0;
    }

    @Override
    public boolean update(Brand brand) {
        return brandDao.update(brand) > 0;
    }

    @Override
    public Brand getById(Integer id) {
        return brandDao.getById(id);
    }

    @Override
    public List<Brand> getAll() {
        return brandDao.getAll();
    }

    @Override
    public PageBean<Brand> selectByPage(int currentPage, int pageSize) {
        int begin = (currentPage-1) * pageSize;
        int size = pageSize;
        List<Brand> rows = brandDao.selectByPage(begin, size);
        int totalCount = brandDao.selectTotalCount();
        PageBean<Brand> pageBean = new PageBean<Brand>();
        pageBean.setRows(rows);
        pageBean.setTotalCount(totalCount);
        return pageBean;
    }

    @Override
    public PageBean<Brand> selectByPageAndCondition(int currentPage, int pageSize, Brand brand) {
        int begin = (currentPage-1) * pageSize;
        int size = pageSize;

        // 处理模糊查询
        String brandName = brand.getBrandName();
        if (brandName!=null&&brandName.length()>0){
            brand.setBrandName("%"+brandName+"%");
        }
        String companyName = brand.getCompanyName();
        if (companyName!=null&&companyName.length()>0){
            brand.setCompanyName("%"+companyName+"%");
        }

        // 查询当前页数据
        List<Brand> brandList = brandDao.selectByPageAndCondition(begin, size, brand);
        // 查询当前页总记录条数
        int totalCount = brandDao.selectTotalCountByCondition(brand);

        // 封装PageBean
        PageBean<Brand> pageBean = new PageBean<>(brandList,totalCount);
        return pageBean;
    }

}

6.前端代码

<div id="app">
        <!--    导航菜单-->
        <el-menu
                :default-active="activeIndex2"
                class="el-menu-demo"
                mode="horizontal"
                @select="handleSelect"
                background-color="#545c64"
                text-color="#fff"
                active-text-color="#ffd04b">
            <template>
                <h3 align="center"><img src="../img/E-commerce.png" width="50" height="50" align="center">
                    电商后台数据模型
                </h3>
            </template>
            <el-menu-item index="1">处理中心</el-menu-item>
            <el-submenu index="2">
                <template slot="title">我的工作台</template>
                <el-menu-item index="2-1">后台品牌模型</el-menu-item>
            </el-submenu>
            <el-menu-item index="3" disabled>消息中心</el-menu-item>
            <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
        </el-menu>

<!--    搜索表单-->
    <el-form :inline="true" :model="brand" class="demo-form-inline">

        <el-form-item label="当前状态">
            <el-select v-model="brand.status" placeholder="当前状态">
                <el-option label="启用" value="1"></el-option>
                <el-option label="禁用" value="0"></el-option>
            </el-select>
        </el-form-item>

        <el-form-item label="企业名称">
            <el-input v-model="brand.companyName" placeholder="企业名称"></el-input>
        </el-form-item>

        <el-form-item label="品牌名称">
            <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input>
        </el-form-item>

        <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
    </el-form>

<!--    按钮-->
    <el-row style="margin-left: 20%">
        <el-button type="danger" plain @click="deleteBrandByIds">批量删除</el-button>
        <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>
    </el-row>

<!--    添加数据的对话框表单-->
    <el-dialog
            title="编辑品牌"
            :visible.sync="dialogVisible"
            width="30%"
    >

        <el-form ref="form" :model="brand_add" label-width="80px">
            <el-form-item label="品牌名称">
                <el-input v-model="brand_add.brandName"></el-input>
            </el-form-item>

            <el-form-item label="企业名称">
                <el-input v-model="brand_add.companyName"></el-input>
            </el-form-item>

            <el-form-item label="排序">
                <el-input v-model="brand_add.ordered"></el-input>
            </el-form-item>

            <el-form-item label="备注">
                <el-input type="textarea" v-model="brand_add.description"></el-input>
            </el-form-item>

            <el-form-item label="状态">
                <el-switch
                        v-model="brand_add.status"
                        active-value="1"
                        inactive-value="0"
                >
                </el-switch>
            </el-form-item>

            <el-form-item>
                <el-button type="primary" @click="addBrand">提交</el-button>
                <el-button @click="cancelAdd">取消</el-button>
            </el-form-item>
        </el-form>

    </el-dialog>

<!--    修改数据的对话框表单-->
    <el-dialog
            title="修改数据"
            :visible.sync="updateDialogVisible"
            width="30%">
   <el-form ref="form" :model="update" label-width="80px">
  <el-form-item label="品牌名称">
    <el-input v-model="update.brandName"></el-input>
  </el-form-item>
  <el-form-item label="企业名称">
       <el-input v-model="update.companyName"></el-input>
  </el-form-item>
  <el-form-item label="排序">
    <el-input v-model="update.ordered"></el-input>
  </el-form-item>
  <el-form-item label="备注">
    <el-input type="textarea" v-model="update.description"></el-input>
  </el-form-item>
  <el-form-item label="状态">
      <el-switch
              v-model="update.status"
              active-value="1"
              inactive-value="0">
      </el-switch>
  </el-form-item>
       <el-form-item>
           <el-button type="primary" @click="updateBrand">提交</el-button>
           <el-button @click="cancel">取消</el-button>
       </el-form-item>
  </el-form>

    </el-dialog>

    <h4 align="center"><img src="../img/product.png" width="50" height="50" align="center"><font color="gray">产品列表
    </font></h4>

    <!--    表格-->
    <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
            @selection-change="handleSelectionChange"
    >
        <el-table-column
                type="selection"
                width="55"
        >
        </el-table-column>
        <el-table-column
                type="index"
                width="50">
        </el-table-column>
        <el-table-column
                prop="brandName"
                label="品牌名称"
                align="center"
                >
        </el-table-column>
        <el-table-column
                prop="companyName"
                label="企业名称"
                align="center"
                >
        </el-table-column>
        <el-table-column
                prop="ordered"
                label="排序"
                align="center"
        >
        </el-table-column>
        <el-table-column
                prop="description"
                label="备注"
                align="center"
        >
        </el-table-column>
        <el-table-column
                prop="statusStr"
                label="当前状态"
                align="center"
        >
        </el-table-column>
        <el-table-column
                prop="address"
                label="操作"
                align="center"
        >
            <el-row>
                <el-button type="primary" @click="modify">修改</el-button>
                <el-button type="danger" @click="deleteById">删除</el-button>
            </el-row>
        </el-table-column>
    </el-table>
    </template>

<!--    分页工具条-->
    <div class="block">
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage"
                :page-sizes="[5, 10, 15, 20]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="totalCount">
        </el-pagination>
    </div>
</div>

js

<script src="https://cdn.jsdelivr.net/npm/vue@2.7.13/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/1.1.3/axios.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.10/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://cdn.staticfile.org/element-ui/2.15.10/index.js"></script>
<script>
    new Vue({
        el:"#app",
        mounted(){
            //当页面加载完毕后,发送异步请求
           this.selectAll();
        },
        methods: {
            // 查询所有品牌数据
            selectAll(){
               axios({
                   method:"post",
                   url:`/brands/${this.currentPage}/${this.pageSize}`,
                   data:this.brand,
                   headers: {
                       'Content-Type': 'application/json;charset=UTF-8'
                   }
               }).then((resp)=>{
                   if (resp.data.code == 20041) {
                       this.tableData = resp.data.data.rows;
                       this.totalCount = resp.data.data.totalCount
                   }else if (resp.data.code == 20040){
                       this.$message.error('获取数据失败!').center = true;
                   }else {
                       this.$message.error(resp.data.msg).center = true;
                   }
               })
            },
            resetForm(formName) {
                this.$refs[formName].resetFields();
            },
            cancelAdd(){
                this.dialogVisible = false;
                // 用户点击了取消按钮
                this.$message({
                    showClose: true,
                    message: '您取消了添加数据!',
                    center:true
                });
            },
            modify(){
                for (let i = 0; i < this.multipleSelection.length; i++) {
                    var selectionElement = this.multipleSelection[i];
                    this.update.id = selectionElement.id;
                }
                if (this.update.id == '' || this.update.id == null){
                        this.$message({
                            showClose: true,
                            message: '请选中您要修改的数据!',
                            type: 'error',
                            center:true,
                        });
                        return;
                }
                  axios.get(`/brands/${this.update.id}`).then((resp)=>{
                     if (resp.data.code==20041){
                         this.update = resp.data.data;
                         this.updateDialogVisible = true;
                     }
                  });
                },
            cancel(){
                this.updateDialogVisible = false;
                this.$message({
                    showClose: true,
                    message: '您已取消修改',
                    center:true
                });
            },

            tableRowClassName({row, rowIndex}) {
                if (rowIndex === 1) {
                    return 'warning-row';
                } else if (rowIndex === 3) {
                    return 'success-row';
                }
                return '';
            },
            // 复选框选中后执行的方法
            handleSelectionChange(val) {
                this.multipleSelection = val;
            },
            // 查询的方法
            onSubmit() {
                this.selectAll();
            },
            // 添加数据
            addBrand(){
                axios({
                    method:'post',
                    url:'/brands',
                    data:this.brand_add,
                    headers:{
                        'Content-Type':'application/json;charset=UTF-8'
                    }
                }).then( (resp) => {
                    if (resp.data.code==20011){
                        // 关闭添加数据对话框表单
                        this.dialogVisible = false;
                        // 弹出提示信息
                        this.$message({
                            message: '添加数据成功!',
                            type: 'success',
                            center: true
                        });
                    }else if (resp.data.code==20010){
                        this.$message.error("添加数据失败!").center = true;
                    }else {
                        this.$message.error(resp.data.msg).center = true;
                    }
                }).finally(()=>{
                    // 重新查询数据
                    this.selectAll();
                    this.resetForm(this.brand_add)
                })
            },
            // 更新数据
            updateBrand(){
                axios.put("/brands",this.update).then(resp=>{
                    if (resp.data.code == 20031) {
                        this.updateDialogVisible = false;
                        this.$message({
                            showClose: true,
                            message: '更新数据成功!',
                            type: 'success',
                            center: true
                        });
                    }else if (resp.data.code == 20030){
                        this.$message.error("更新数据失败!").center = true
                    }else {
                        this.$message.error(resp.data.msg).center = true
                    }
                }).finally(()=>{
                    this.selectAll();
                });
                this.update.id = '';
            },
            // 批量删除
            deleteBrandByIds(){
                // 弹出确认提示框
                this.$confirm('此操作将永久删除数据, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {

                    // 1.创建id数组,从this.multipleSelection中获取
                    for (let i = 0; i < this.multipleSelection.length; i++) {
                        let selectionElement = this.multipleSelection[i];
                        this.selectedIds[i] = selectionElement.id
                    }
                  if (this.selectedIds.length < 1){
                      this.$message({
                          showClose: true,
                          message: '请选中您要删除的数据!',
                          type: 'error',
                          center:true,
                      });
                      return;
                  }
                    // 2.发送ajax请求
                    axios({
                        method: 'delete',
                        url: '/brands',
                        data:this.selectedIds,
                        headers:{
                            'Content-Type':'application/json;charset=utf-8'
                        }
                    }).then( (resp) => {
                        if (resp.data.code == 20021) {
                            // 重新查询数据
                            this.selectAll();
                            this.$message({
                                type: 'success',
                                message: '删除成功!',
                                center: true
                            });
                        }else if (resp.data.code == 20020){
                            this.$message.error("删除失败!").center = true
                        }else {
                            this.$message.error(resp.data.msg).center = true
                        }
                    });
                }).catch(() => {
                    // 用户点击取消按钮
                    this.$message({
                        type: 'info',
                        message: '您已取消删除',
                        center:true
                    });
                });
                // 清除数组
                this.selectedIds = [];
            },


            // 删除单条数据
            deleteById(){
                for (let i = 0; i < this.multipleSelection.length; i++) {
                    var selectionElement = this.multipleSelection[i];
                    this.selectedId = selectionElement.id;
                }
                if (this.selectedId == '' || this.selectedId == null){
                    this.$message({
                        showClose: true,
                        message: '请选中您要删除的数据!',
                        type: 'error',
                        center:true,
                    });
                    return;
                }
                axios.delete(`/brands/${this.selectedId}`)
                    .then(resp=>{
                            this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {
                                confirmButtonText: '确定',
                                cancelButtonText: '取消',
                                type: 'warning'
                            }).then(() => {
                                if (resp.data.code == 20021) {
                                    this.$message({
                                        type: 'success',
                                        message: '删除成功!',
                                        center: true
                                    });
                                }else if (resp.data.code == 20020){
                                    this.$message.error("删除失败!").center = true
                                }else {
                                    this.$message.error(resp.data.msg).center = true
                                }
                            }).catch(() => {
                                this.$message({
                                    type: 'info',
                                    message: '您已取消删除',
                                    center:true,
                                });
                            });
                    }).finally(()=>{
                    // 重新查询数据
                    this.selectAll();
                });
                // 清空selectedId
                this.selectedId = ''
            },
            // 分页
            handleSizeChange(val) {
                // 重新设置每页显示条数
                this.pageSize = val;
                this.selectAll();
            },
            handleCurrentChange(val) {
                // 重新设置当前页码
                this.currentPage = val;
                this.selectAll();
            }
        },
        data() {
            return {
                // 被选中的单个id
                selectedId:'',
                // 总记录条数
                totalCount:'',
                // 每页显示条数
                pageSize:10,
                // 修改数据表单显示状态
                updateDialogVisible:false,
                // 当前页码
                currentPage:1,
                // 控制添加数据对话框表单是否显示
                dialogVisible: false,
                // 品牌模型数据
                brand: {
                    companyName: '',
                    status: '',
                    brandName:'',
                    id:'',
                    ordered:'',
                    description:'',
                },
                // 更新模型数据
                update: {
                    companyName: '',
                    status: '',
                    brandName:'',
                    id:'',
                    ordered:'',
                    description:'',
                },
                // 添加模型数据
                 brand_add: {
                    companyName: '',
                    status: '',
                    brandName:'',
                    id:'',
                    ordered:'',
                    description:'',
                },
                // 复选框选中数据集合
                multipleSelection:[],
                // 被选中的id数组
                selectedIds:[],
                // 表格数据
                tableData: []
            }
        },

    })
</script>

7.页面展示

 

 

 

结语:

希望这些能够帮助到你的学习!!! 如果有需要源码的私信我

Logo

前往低代码交流专区

更多推荐