javaee之黑马乐优商城2

简单分析一下商品分类表的结构

先来说一下分类表与品牌表之间的关系

 再来说一下分类表和品牌表与商品表之间的关系

 面我们要开始就要创建sql语句了嘛,这里我们分析一下字段

用到的数据库是heima->tb_category这个表

现在去数据库里面创建好这张表

 

 下面我们再去编写一个实体类之前,我们去看一下这个类的请求方式,请求路径,请求参数,返回数据都是什么

下面再去编写实体类

实体都是放到 

出现了一个小插曲,开始的时候,我maven项目右边的模块有些是灰色的,导致我导入依赖之后,所有的注解什么都不能用,解决方案如下

然后把依赖重新导入一下

我们先去完成我们商品分类表的一个实体类

 Category.java

package com.leyou.item.pojo;import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;import javax.persistence.Id;
import javax.persistence.Table;/*** Created by Administrator on 2023/8/28.*/
@Table(name="tb_category")
@Data
public class Category {@Id@KeySql(useGeneratedKeys = true)private Long id;private String name;private Long parentId;private Boolean isParent;private Integer sort;
}

然后去到ly-item-service去写具体的业务逻辑,比如mapper,service,web都在这里面

这里来说一个依赖问题

 引入了spring-boot-starter-web这个依赖,也包含了spring的核心依赖

说一下在写这个controller类的时候,我们的路径是什么,路径就是我们访问每一个接口传递过来的url

ResponseEntity这个类是干嘛的

 格式用法有两种

CollectionUtils工具类

 这个是Spring给我们提供的一个工具类

我们可以来做如下检测

 下面我们贴上这个CategoryController的代码

package com.leyou.item.web;import com.leyou.item.pojo.Category;
import com.leyou.item.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** Created by Administrator on 2023/8/29.*/
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 根据父节点的id查询商品分类* @param pid* @return*/@GetMapping("/list")public ResponseEntity<List<Category>> queryCategoryListByPid(@RequestParam("pid")Long pid) {try {if(pid == null || pid.longValue() < 0) {//会返回带着状态码的对象400 参数不合法// return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();//可以做一格优化,下面的类似return ResponseEntity.badRequest().build();}//开始利用service执行查询操作List<Category> categoryList = categoryService.queryCategoryListByParentId(pid);if(CollectionUtils.isEmpty(categoryList)) {//如果结果集为空,响应404return ResponseEntity.notFound().build();}//查询成功,响应200return ResponseEntity.ok(categoryList);//这里才真正放了数据} catch (Exception e) {e.printStackTrace();}//自定义状态码,然后返回//500返回一个服务器内部的错误//这里也可以不返回,程序出错,本身就会返回500return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()}}

下面我们去Service创建queryCategoryListByParentId这个方法

看一下完整代码

package com.leyou.item.service;import com.leyou.item.mapper.CategoryMapper;
import com.leyou.item.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** Created by Administrator on 2023/8/29.*/
@Service
public class CategoryService {@Autowiredprivate CategoryMapper categoryMapper;/*** 根据父节点的id来查询子结点* @param pid* @return*/public List<Category> queryCategoryListByParentId(Long pid) {Category category = new Category();category.setParentId(pid);return categoryMapper.select(category);}}

上面都做完了,现在去数据库操作把分类中的数据给插入一下,类似于如下这些数据

 下面就是在数据中存在的数据

 下面我开始去启动:

我们的数据肯定是去走网关的

网关很明显我们是可以看到数据的

 但是在项目里面点击就出不来

 上面明显就是出现了跨域的问题

跨域我们就是在服务端进行一个配置

说的简单点,服务器就给给我们配置如下信息

我们这里在服务器搭配一个类来配置这些信息就可以了

我们这里用SpringMVC帮我们写的一个cors跨域过滤器来做:CrosFilter

具体代码如下

package com.leyou.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;/*** Created by Administrator on 2023/8/31.*/
@Configuration
public class LeyouCorsConfiguration {@Beanpublic CorsFilter corsFilter() {//1.添加CORS配置信息CorsConfiguration config = new CorsConfiguration();//1) 允许的域,不要写*,否则cookie就无法使用了config.addAllowedOrigin("http://manage.leyou.com");config.addAllowedOrigin("http://www.leyou.com");//2) 是否发送Cookie信息config.setAllowCredentials(true);//3) 允许的请求方式config.addAllowedMethod("OPTIONS");config.addAllowedMethod("HEAD");config.addAllowedMethod("GET");config.addAllowedMethod("PUT");config.addAllowedMethod("POST");config.addAllowedMethod("DELETE");config.addAllowedMethod("PATCH");// 4)允许的头信息config.addAllowedHeader("*");//2.添加映射路径,我们拦截一切请求UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();configSource.registerCorsConfiguration("/**", config);//3.返回新的CorsFilter.return new CorsFilter(configSource);}
}

重新启动一下网关服务器

下面来讲品牌查询 

 

我们现在要做的就是查询出上面的品牌

 我们必须弄明白请求方式,请求路径,请求参数,响应数据决定返回值

一般来说如果页面要展示一个列表的话,就要返回一个List集合对象或者返回一个分页对象

我们就必须定义一个分页对象

分页对象后面大家都要用,我们就放到common里面去

先来把这个分页对象给做了

package com.leyou.common.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** Created by Administrator on 2023/9/2.*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageResult<T> {private Long total;//总条数private Integer totalPage;//总页数private List<T> items;//当前页面数据对象public PageResult(Long total,List<T> items) {this.total = total;this.items = items;}
}

下面我们来做一下前端页面

 先去找这个页面,在menu.js里面,去查看商品的路径在什么位置

上面就是品牌的路径/item/brand,下面我们看组件在哪里

去到下面这个位置

这个位置去找我们的路由页面

 

 

所有的页面组件全部都在pages里面放着

我们这里自己来写一下组件

我们自己定义一个MyBrand1.vue组件

 

我们这个页面主要还是去做一个分页的表格

可以去Vuetify里面查找

我们这里应该去找从服务端就已经分页与排序好的数据

下面我们可以去看到这里面的模板代码

 上面就是我们要用的模板代码

数据脚本当然是你在script里面,可以查看一下

<script>const desserts = [{name: 'Frozen Yogurt',calories: 159,fat: 6.0,carbs: 24,protein: 4.0,iron: '1',},{name: 'Jelly bean',calories: 375,fat: 0.0,carbs: 94,protein: 0.0,iron: '0',},{name: 'KitKat',calories: 518,fat: 26.0,carbs: 65,protein: 7,iron: '6',},{name: 'Eclair',calories: 262,fat: 16.0,carbs: 23,protein: 6.0,iron: '7',},{name: 'Gingerbread',calories: 356,fat: 16.0,carbs: 49,protein: 3.9,iron: '16',},{name: 'Ice cream sandwich',calories: 237,fat: 9.0,carbs: 37,protein: 4.3,iron: '1',},{name: 'Lollipop',calories: 392,fat: 0.2,carbs: 98,protein: 0,iron: '2',},{name: 'Cupcake',calories: 305,fat: 3.7,carbs: 67,protein: 4.3,iron: '8',},{name: 'Honeycomb',calories: 408,fat: 3.2,carbs: 87,protein: 6.5,iron: '45',},{name: 'Donut',calories: 452,fat: 25.0,carbs: 51,protein: 4.9,iron: '22',},]const FakeAPI = {async fetch ({ page, itemsPerPage, sortBy }) {return new Promise(resolve => {setTimeout(() => {const start = (page - 1) * itemsPerPageconst end = start + itemsPerPageconst items = desserts.slice()if (sortBy.length) {const sortKey = sortBy[0].keyconst sortOrder = sortBy[0].orderitems.sort((a, b) => {const aValue = a[sortKey]const bValue = b[sortKey]return sortOrder === 'desc' ? bValue - aValue : aValue - bValue})}const paginated = items.slice(start, end)resolve({ items: paginated, total: items.length })}, 500)})},}export default {data: () => ({itemsPerPage: 5,headers: [{title: 'Dessert (100g serving)',align: 'start',sortable: false,key: 'name',},{ title: 'Calories', key: 'calories', align: 'end' },{ title: 'Fat (g)', key: 'fat', align: 'end' },{ title: 'Carbs (g)', key: 'carbs', align: 'end' },{ title: 'Protein (g)', key: 'protein', align: 'end' },{ title: 'Iron (%)', key: 'iron', align: 'end' },],serverItems: [],loading: true,totalItems: 0,}),methods: {loadItems ({ page, itemsPerPage, sortBy }) {this.loading = trueFakeAPI.fetch({ page, itemsPerPage, sortBy }).then(({ items, total }) => {this.serverItems = itemsthis.totalItems = totalthis.loading = false})},},}
</script>

下面我们去看一下品牌表展示什么样的内容,我们看一下数据库里面的字段,先来创建一张产品表,然后把数据也给插入进去

下面我们把数据给插进去,类似于插入下面这些数据

看一下,很明显这个表的数据就已经存在了

我们表头我们直接可以从下面的位置修改

下面直接展示品牌页面前端所有代码

<template><v-card><v-card-title><v-btn color="primary" @click="addBrand">新增品牌</v-btn><!--搜索框,与search属性关联--><v-spacer/><v-flex xs3><v-text-field label="输入关键字搜索" v-model.lazy="search" append-icon="search" hide-details/></v-flex></v-card-title><v-divider/><v-data-table:headers="headers":items="brands":pagination.sync="pagination":total-items="totalBrands":loading="loading"class="elevation-1"><template slot="items" slot-scope="props"><td class="text-xs-center">{{ props.item.id }}</td><td class="text-xs-center">{{ props.item.name }}</td><td class="text-xs-center"><img v-if="props.item.image" :src="props.item.image" width="130" height="40"><span v-else>无</span></td><td class="text-xs-center">{{ props.item.letter }}</td><td class="justify-center layout px-0"><v-btn flat icon @click="editBrand(props.item)" color="info"><i class="el-icon-edit"/></v-btn><v-btn flat icon @click="deleteBrand(props.item)" color="purple"><i class="el-icon-delete"/></v-btn></td></template></v-data-table><!--弹出的对话框--><v-dialog max-width="500" v-model="show" persistent scrollable><v-card><!--对话框的标题--><v-toolbar dense dark color="primary"><v-toolbar-title>{{isEdit ? '修改' : '新增'}}品牌</v-toolbar-title><v-spacer/><!--关闭窗口的按钮--><v-btn icon @click="closeWindow"><v-icon>close</v-icon></v-btn></v-toolbar><!--对话框的内容,表单 这里是要把获得的brand 数据传递给子组件,使用自定义标签::oldBrand 而父组件值为oldBrand--><v-card-text class="px-5" style="height:400px"><brand-form @close="closeWindow" :oldBrand="oldBrand" :isEdit="isEdit"/></v-card-text></v-card></v-dialog></v-card>
</template><script>// 导入自定义的表单组件,引入子组件 brandformimport BrandForm from './BrandForm'export default {name: "brand",data() {return {search: '', // 搜索过滤字段totalBrands: 0, // 总条数brands: [], // 当前页品牌数据loading: true, // 是否在加载中pagination: {}, // 分页信息headers: [{text: 'id', align: 'center', value: 'id'},{text: '名称', align: 'center', sortable: false, value: 'name'},{text: 'LOGO', align: 'center', sortable: false, value: 'image'},{text: '首字母', align: 'center', value: 'letter', sortable: true,},{text: '操作', align: 'center', value: 'id', sortable: false}],show: false,// 控制对话框的显示oldBrand: {}, // 即将被编辑的品牌数据isEdit: false, // 是否是编辑}},mounted() { // 渲染后执行// 查询数据--搜索后页面还处在第几页,只要搜索,页面渲染后重新查询this.getDataFromServer();},watch: {pagination: { // 监视pagination属性的变化deep: true, // deep为true,会监视pagination的属性及属性中的对象属性变化handler() {// 变化后的回调函数,这里我们再次调用getDataFromServer即可this.getDataFromServer();}},search: { // 监视搜索字段handler() {this.pagination.page =1;this.getDataFromServer();}}},methods: {getDataFromServer() { // 从服务的加载数的方法。// 发起请求this.$http.get("/item/brand/page", {params: {key: this.search, // 搜索条件page: this.pagination.page,// 当前页rows: this.pagination.rowsPerPage,// 每页大小sortBy: this.pagination.sortBy,// 排序字段desc: this.pagination.descending// 是否降序}}).then(resp => { // 这里使用箭头函数this.brands = resp.data.items;this.totalBrands = resp.data.total;// 完成赋值后,把加载状态赋值为falsethis.loading = false;//})},addBrand() {// 修改标记,新增前修改为falsethis.isEdit = false;// 控制弹窗可见:this.show = true;// 把oldBrand变为null,因为之前打开过修改窗口,oldBrand数据被带过来了,导致新增this.oldBrand = null;},editBrand(oldBrand){//test 使用//this.show = true;//获取要编辑的brand//this.oldBrand = oldBrand;//requestParam,相当于把http,url ?name=zhangsan&age=21 传给方法//pathvarable 相当与把url www.emporium.com/1/2 传给方法//如果不需要url上的参数controller不需要绑定数据// 根据品牌信息查询商品分类, 因为前台页面请求是拼接的, data 类似于jquery 里面回显的数据this.$http.get("/item/category/bid/" + oldBrand.id).then(({data}) => {// 修改标记this.isEdit = true;// 控制弹窗可见:this.show = true;// 获取要编辑的brandthis.oldBrand = oldBrand// 回显商品分类this.oldBrand.categories = data;})},closeWindow(){// 重新加载数据this.getDataFromServer();// 关闭窗口this.show = false;}},components:{BrandForm}}
</script><style scoped></style>

 

下面开始写后台逻辑

 

开始写后台,先写一个产品类

 Brand.java

package com.leyou.item.pojo;import lombok.Data;import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;/*** Created by Administrator on 2023/9/2.*/
@Data
@Table(name="tb_brand")
public class Brand {@Id@GeneratedValue(strategy= GenerationType.IDENTITY)private Long id;private String name;//品牌名称private String image;//品牌图片private Character letter;
}

接下来我们写上我们的通用Mapper类

下面我们去写service接口

 下面去写Controller类

分析一下

返回的是什么:当前页的数据(list集合)和总条数 

也就是上面返回的是如下一个分页对象,在ly-common模块里面,如果需要用到这个模块的对象,那么我们就需要把这个模块当成依赖引入到另外一个模块里面

这里是ly-item下面的模块ly-item-service需要用到PageResult对象

下面就是Controller中的代码

下面去完成Service中的方法

package com.leyou.item.service;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.common.pojo.PageResult;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.item.pojo.Brand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;/*** Created by Administrator on 2023/9/2.*/
@Service
public class BrandService {//内部需要一个mapper调用@Autowiredprivate BrandMapper brandMapper;/**** @param page 当前页* @param rows 每页大小* @param sortBy 排序字段* @param desc 是否降序* @param key 搜索关键字* @return*/public PageResult<Brand> queryBrandByPageAndSort(Integer page,Integer rows, String sortBy, Boolean desc, String key) {//开启分页//这个会自动拼接到后面的sql语句上面PageHelper.startPage(page,rows);//传进来一个页码和展示多少行的数据,//过滤Example example = new Example(Brand.class);if(key != null && !"".equals(key)) {//进来有一模糊查询//把这个语句拼接上example.createCriteria().andLike("name","%" + key + "%").orEqualTo("letter",key);}if(sortBy != null && !"".equals(sortBy)) {//根据sortBy字段进行排序String orderByClause = sortBy + (desc ? " DESC " : " ASC ");example.setOrderByClause(orderByClause);}//利用通用mapper进行查询Page<Brand> pageInfo = (Page<Brand>) brandMapper.selectByExample(example);//返回结果//这里面传递总条数和页面信息return new PageResult<>(pageInfo.getTotal(),pageInfo);}
}

说一下,用Autowired注入Mapper的时候,提示注入不了,爆红

 

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

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

相关文章

Unexpected mutation of “xxxx“ prop

原因 是因为子级修改了父级的数据&#xff0c;所以eslint执行的时候报了这个错 修复方式 1 如果是弹窗等组件&#xff0c;可以根据功能进行修改&#xff0c;比如我这块用的 element ui 的 dialog&#xff0c;便可以改成这样 使用 model-value 代替 修复方式 2 新建子组件…

3种等待方式,让你学会Selenium设置自动化等待测试脚本!

一、Selenium脚本为什么要设置等待方式&#xff1f;——即他的应用背景到底是什么 应用Selenium时&#xff0c;浏览器加载过程中无法立即显示对应的页面元素从而无法进行元素操作&#xff0c;需设置一定的等待时间去等待元素的出现。&#xff08;简单来说&#xff0c;就是设置…

CTFSHOW 年CTF

1.除夕 php的弱类型&#xff0c;用小数点绕过 这里后面直接加字母不行 2.初三 error_reporting(0); extract($_GET); include "flag.php"; highlight_file(__FILE__); 这里通过extract将get的参数导入为了变量 $_function($__,$___){return $__$___?$___:$__; }; …

恒运资本:银行股适合定投吗?为什么银行股适合定投?

在股票市场上&#xff0c;出资者能够通过手动不断的买入到达基金定投的效果&#xff0c;那么&#xff0c;银行股适合定投吗&#xff1f;为什么银行股适合定投&#xff1f;下面恒运资本为我们准备了相关内容&#xff0c;以供参考。 银行股适合定投&#xff0c;即通过定投不断的买…

索尼 toio™ 应用创意开发征文|小巧机器,大无限,探索奇妙世界

文章目录 前言微型机器人的未来&#xff1a;toio™小机器人简介toio™小机器人&#xff1a;创新功能一览toio™小机器人&#xff1a;多领域的变革者toio™小机器人贪吃蛇游戏代码实现写在最后 前言 当我们谈到现代科技的创新时&#xff0c;往往会联想到复杂的机器和高级的编程…

Linux CentOS7命令及命令行

Linux CentOS7中命令及命令行是非常重要的概念。对大多数初学者来说是既熟悉又了解甚少。本文初步讨论这方面的内容&#xff0c;与同行者交流。 一、命令 命令又称为指令&#xff0c;&#xff08;英语命令 command&#xff0c;可用简写cmd表示&#xff09;&#xff0c;在终端…

小程序引入高德/百度地图坐标系详解

小程序引入高德/百度地图坐标系详解 官网最近更新时间&#xff1a;最后更新时间: 2021年08月17日 高德官网之在原生小程序中使用的常见问题 链接 目前在小程序中使用 高德地图只支持以下功能 &#xff1a;地址描述、POI和实时天气数据 小结&#xff1a;从高德api中获取数…

不就是G2O嘛

从零开始一起学习SLAM | 理解图优化&#xff0c;一步步带你看懂g2o代码 SLAM的后端一般分为两种处理方法&#xff0c;一种是以扩展卡尔曼滤波&#xff08;EKF&#xff09;为代表的滤波方法&#xff0c;一种是以图优化为代表的非线性优化方法。不过&#xff0c;目前SLAM研究的主…

【学习笔记】C++ 中 static 关键字的作用

目录 前言static 作用在变量上static 作用在全局变量上static 作用在局部变量上static 作用在成员变量上 static 作用在函数上static 作用在函数上static 作用在成员函数上 前言 在 C/C 中&#xff0c;关键字 static 在不同的应用场景下&#xff0c;有不同的作用&#xff0c;这…

老听说企业要做私域运营,那具体如何做呢?

以前企业获得新客户的方式是从各大流量平台进行引流&#xff0c;但现在这些公域平台人力投入和产出的比例不合理&#xff0c;或者费用太高而无法承担。因此&#xff0c;企业需要建立自己的私域流量池&#xff0c;无需付费、随时可接触的私域流量池。 那么&#xff0c;怎么做私域…

NIFI关于Parameter Contexts的使用

说明 nifi版本&#xff1a;1.23.2&#xff08;docker镜像&#xff09; 作用 Parameter Contexts&#xff08;参数上下文&#xff09;&#xff1a;参数上下文由 NiFi 实例全局定义/访问。访问策略可以应用于参数上下文&#xff0c;以确定哪些用户可以创建它们。创建后&#x…

自然语言处理(五):子词嵌入(fastText模型)

子词嵌入 在英语中&#xff0c;“helps”“helped”和“helping”等单词都是同一个词“help”的变形形式。“dog”和“dogs”之间的关系与“cat”和“cats”之间的关系相同&#xff0c;“boy”和“boyfriend”之间的关系与“girl”和“girlfriend”之间的关系相同。在法语和西…

如何让数据成为企业的生产力?

为什么有的企业投入大量的人力、物力、财力做数字化转型建设最终做了个寂寞&#xff01;企业领导没看到数字化的任何价值&#xff01; 如果要问企业数字化转型建设最核心的价值体现是什么&#xff0c;大部分人都会说是&#xff1a;数据&#xff01; 然而&#xff0c;不同的人…

微服务整合Seata1.5.2+Nacos2.2.1+SpringBoot

文章目录 一、Seata Server端1、下载seata server2、客户端配置-application.yml3、初始Mysql数据库4、导入初始配置到nacos5、启动测试 二、Seata Client端搭建1、为示例业务创建表2、业务代码集成 Seata 本文以seata-server-1.5.2&#xff0c;以配置中心、注册中心使用Nacos&…

百度王海峰披露飞桨生态最新成果 开发者数量已达800万

目录 前言文心大模型原生插件机制文心大模型超级助手飞桨开发者数已达800万 模型数超80万星河社区最后 前言 8月16日&#xff0c;由深度学习技术及应用国家工程研究中心举办的WAVE SUMMIT深度学习开发者大会上&#xff0c;位于北京举行。百度的首席技术官兼深度学习技术及应用…

德国金融监管机构网站遭遇大规模DDoS攻击后“瘫痪”

德国波恩的BaFin大楼 BaFin是负责监督和监管德国金融机构和市场的金融监管机构&#xff0c;其职责是确保德国金融体系的稳定性、完整性和透明度。 此外&#xff0c;BaFin 的网站还为企业和消费者提供银行、贷款和财产融资等方面的信息。它还提供消费者帮助热线和举报人信息共…

Java从入门到精通-流程控制(二)

习题讲解&#xff1a; 上次我们给大家留了一些流程控制的问题&#xff0c;这次给大家分析讲解一下&#xff1a; 条件语句练习&#xff1a; 1.编写Java程序&#xff0c;用于接受用户输入的数字&#xff0c;然后判断它是偶数还是奇数&#xff0c;并输出相应的消息。 import ja…

记录使用layui弹窗实现签名、签字

一、前言 本来项目使用的是OCX方式做签字的&#xff0c;因为项目需要转到国产化&#xff0c;不在支持OCX方式&#xff0c;需要使用前端进行签字操作 注&#xff1a;有啥问题看看文档&#xff0c;或者换着思路来&#xff0c;本文仅供参考&#xff01; 二、使用组件 获取jSign…

九章云极DataCanvas公司参与大模型重点项目合作签约,建设产业集聚区

9月3日&#xff0c;2023中国国际服务贸易交易会石景山国际开放合作论坛在石景山首钢园成功举办&#xff0c;北京市委常委、常务副市长夏林茂&#xff0c;商务部服务贸易和商贸服务业司司长王东堂&#xff0c;北京市石景山区委书记常卫出席论坛并致辞。论坛期间正式举行“石景山…