项目开发记录-CRM

目录

CRM

设置全局请求参数

修改数据表中字段的字符集

多环境同步数据库

前后端时间参数传递

布尔类型参数传递

Excel导入、导出

小程序(服务端)

前期准备

微信支付

微信公众号推送

IDEA

1.cannot find declaration to go to

2.maven依赖冲突

一点小问题(O_O)?

1.BaseModel的用法


        本项目是针对一个商城开发的 微信小程序及后台crm管理系统。包含微信小程序及PC管理系统。

        开发框架:微信小程序-uniApp;前端管理系统-VUE;后台服务-SpringBoot。

CRM

设置全局请求参数

        希望将本系统做成通用的CRM管理系统,添加了projectId参数。其他项目需要复用时,可以通过projectId参数进行区分。前提是数据库中所有业务表都需要记录project_id 字段。

        前端通过请求过滤器,在header中添加参数。

service.interceptors.request.use(config => {
  config.headers['projectId'] = localStorage.getItem('projectId');
  return config
} error => {
  // Do something with request error
  console.log(error) // for debug
  return Promise.reject(error)
})

        服务端通过AOP将controller收到的请求拦截,取出header中的projectId,放入searchParam。

    @Pointcut("execution(public * com.ys.crm.portal.manager.web.rest..*(..))")
    public void controllerPointcut() {
    }

    private static final String PROJECT_ID_KEY ="projectId";

    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        Object[] args = pjp.getArgs();
        for(Object arg :args) {
            if(arg instanceof BaseSearchParam) {
                BaseSearchParam searchParam = (BaseSearchParam) arg;

                //获取请求信息
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();

                String projectId = request.getHeader(PROJECT_ID_KEY);

                //如果对象本身未设置该字段且 header中传入了该字段则从head中插入到对象
                if(ObjectUtils.isEmpty(searchParam.getProjectId()) && StringUtil.isNotNull(projectId)) {
                    searchParam.setProjectId(projectId);
                }

            }
        }
        return pjp.proceed();
    }

修改数据表中字段的字符集

修改某张表的某个字段

ALTER TABLE  mytable MODIFY COLUMN `content` MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci

mysql 插入表情符号 '\xF0\x9F\x8D\xB0</...' 报错的解决方法 - 疯狂008的个人页面 - OSCHINA - 中文开源技术交流社区

left join查询,一对多查询时主表数据重复

        对于left join查询,一直浅显的认为只是以左表为主表,但在主从表关系为一对多时,会出现主表中的数据重复查询的问题。

        可以使用group by  distinct 解决

        1.group by 

    SELECT
	    a.id,
    	a.activity_name,
	    pic.id 
    FROM
	    activity a
    	LEFT JOIN act_picture pic ON a.id = pic.activity_id 
    GROUP BY
    	a.id 

        根据主表id进行分组,对应“多”的从表中,默认保留第一条数据(对应需求:取详情(主表)对应的的第一张图片(从表))

         2.distinct

        3.在select 中添加子查询

	
	SELECT
	    a.id,
    	a.activity_name,
	    (SELECT img_url from act_picture where deleted = 0 and activity_id = a.id order by update_time desc limit 1) pic
    FROM
	    activity a
    GROUP BY
    	a.id
    ORDER BY a.update_time desc

        在select 之后from之前,添加子查询,子查询中添加过滤条件然后排序取值。

多环境同步数据库

一. Navicat

        通过Navicat提供的工具,可以很方便的同步多个环境之间的数据库结构、数据。

        实际使用中结构同步这一操作使用频率较高,主要用于开发、测试、生产等环境之间,在开发环境新增的功能,要先发布到测试环境,再同步到UAT 或生产环境。

        

       

         分别选择连接和数据库,左边是比较新的数据库,需要将左边的表结构同步到右边

         

         点击比对之后会把两个数据库的结构进行比对,并生成相应的修改语句,单击相应的表,可以查看针对某张表的DDL语句,判断哪些表需要同步的,选中之后点击部署即可。

 

 

 

二. MySQLWorkbench

        1.通过逆向工程 Datebase - Reverse Engineer 生成E-R 模型。

        2.选择Datebase - Synchronize Model 选择要同步的数据库连接,选定对应的数据库、表。需要通过SSH隧道访问的可以切换Connection Method 选择Standard TCP / IP over SSH

        continue到选择Schemas 时,记得选源数据库,点击Override Target 再点下一步。

        倒数第二步,会把即将对目标数据库做的修改SQL展示出来预览,可以点击执行,或拿出来在单独执行某条SQL进行修改。 

        

        

前后端时间参数传递

        为前端同事提供接口时,时间参数的传递总是最容易出现400错误的。所以为了降低前后端沟通成本,可以约定统一使用时间戳传递时间参数。

        前端对于时间的格式可以千变万化,如:年月日的前后顺序、分隔符、时区等多种不同的表现形式;而前端框架中的组件,对于时间的格式,可能在某一个框架内部,是统一的,但是框架与框架之间是否统一就不一定咯。

        显然让后端一个接口支持所有时间格式不是好的做法,因此我们选择使用可以表达任意时间,所有前端框架都会支持的时间戳,作为前后端传递时间的统一格式。

布尔类型参数传递

        接口使用boolean/Boolean 类型接收参数时,除了可以正常传入true/ false 以外,还可以传入整数。整数0对应false,其余整数均为true

        tips:逻辑电路 ->

                没有电压时,代表假,也就是0。

                有电压时,而不管电压是多大,均代表真。

                对应的,传入接口的数字只要不是0,服务端的boolean类型就会识别为true

Excel导入、导出

        实现:使用Hutool 工具包

        tips : hutool-5.x的poi-ooxml 版本需高于 4.1.2

 <!-- hutool https://www.hutool.cn/docs/#/ -->
 <dependency>
     <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.7.5</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
 <!-- hutool-5.x的poi-ooxml 版本需高于 4.1.2		-->
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>4.1.2</version>
 </dependency>

小程序(服务端)

前期准备

        1.小程序开发:AppSecret、开发者权限(用于获取AppId、token、设置IP白名单等操作)。

        2.微信支付:商户Id、商户秘钥(v3支付需要v3支付秘钥)、商户证书(退款时验证)。

        3.智慧商圈:

                微信商圈:商圈申请、小程序积分插件、商圈商户号、V3秘钥、证书序列号

                支付宝商圈:卡管套件安装包

微信支付

需求:开通微信支付。

实现:集成 bestPay 开发工具包。

踩坑记录:

        1.开通支付能力

                bestPay 调用的是微信的 统一下单接口(v2),需要开通JSAPI支付能力。由于第一时间进行开发时,直接根据微信官方文档调用接口,返回的 403 forbidden 错误码,官方文档也没有对应的说明,反复查询文档检查参数未果,转而集成了bestPay SDK。集成之后的错误提示清晰明了:

【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试

               

                 至此联系了小程序管理员,开通JSAPI支付能力之后继续开发。

        2.支付回调

微信公众号推送

需求:小程序用户绑定结果、活动通知等需要通过微信向指定用户推送消息。

实现:通过公众号的模板消息实现。            

踩坑记录:

        1.unionId

        原本打算使用订阅消息实现,但需要用户订阅之后才能发送,且小程序所属行业没有长期订阅模板,所以调整为通过公众号的模板消息实现。

        用户入口在小程序,要在公众号推送消息就需要通过用户的unionId 获取到用户在公众号的openId,指定openId 发送模板消息。这里需要注意的是小程序与要推送消息的公众号必须属于同一主体,且绑定在同一个微信开放平台账号下,否则wx.login()获取的code无法换取unionId。

        2.模板消息跳转小程序:

        测试跳转时,发送模板消息报错"errcode":40165,"errmsg":"invalid weapp pagepath rid: 611dcc4c-422de372-62df2e28"。原因是小程序在开发时发布的是体验版,公众号跳转只能转到已经发布过的页面。网上说的将参数中的pagepath或改为page,可以成功推送消息,但本质上等于pagepath="",但无法跳转指定的页面,目前猜测是跳转默认页(小程序未发布)。

IDEA

1.cannot find declaration to go to

        问题描述:早上打开IDEA ,两个定义常量的类无法通过ctrl+左键跳转,点击就提示cannot find ... ,且所有引用爆红提示 IDEA Cannot Resolve Symbol 

        解决方法:清除缓存 并重启 file -> Invalidate Chaches / Restart

2.maven依赖冲突

        问题描述:依赖冲突,pom中未显示声明低版本依赖,需要通过mvn命令查出依赖树。

        解决方法:https://blog.csdn.net/cm15835106905/article/details/107964359        

                在项目所在目录执行命令:

mvn dependency:tree>d:\tree.txt

                将maven依赖树直接输出到D盘,根据groupId 和 artifactId查找冲突的依赖。然后使用<exclusions>标签排除引用。 

一点小问题(O_O)?

1.BaseModel的用法

        公司内部封装的统一返回格式BaseModel

public class BaseModel<T> implements Serializable {
    private static final long serialVersionUID = 8868163258271605343L;
    private String status = "200";
    private String message = "操作成功";
    private static final String errorMessage = "操作失败";
    private T data;
    private PageModel page;

    ...    //get、set、构造方法等
}

        需求:活动签到,根据用户是否参与了指定活动,需要分别返回两种数据结构。第一种是需要返回一个Long类型的ID,第二种需要返回一个对象。

        但是BaseModel类提供的静态方法中,buildSuccess()不支持修改status,buildError()又不支持放入data。问了工作经验比较足的同事,说两种情况都属于操作成功,应该在返回的data中添加状态枚举,再分别添加一个Long和一个结果对象,根据不同的业务结果,为不同的字段赋值,这样方便前端进行请求拦截,对除了status=“200”以外的响应进行统一处理(弹框提示message)。

        疑惑:我的想法是通过返回不同的status进行区分,利用泛型T可以放入任意类型的数据。如果只是为了判断响应结果,status为什么不用boolean类型(只需要判断true或false)?而且当前已经有了一种特殊处理,对于非默认错误码(300)417进行拦截。

        思考:前端的响应拦截-> 应该对需要进行统一处理(弹框提示message)的默认错误码BaseModel.status = 300的响应进行拦截,其余一律放行。然后调用方在响应结果中判断,分别进行不同的处理。

 if(response.data.status =='300'){
     var errMsg = response.data.message?response.data.message:'请求失败'
     Message.error({
    	 message: errMsg,
	     type: 'error',
         duration: 2 * 1000
	 });
	 return Promise.reject(errMsg);
 }
 return response.data;
 MemberApi.login(this.loginParam).then(response =>{
    load.close();
    if(response.status == '200'){
        //登录成功
    }else if (response.status == '417'){
        //未注册
    }
 }).catch(() => {
    load.close();
 });

                如果不通过status进行区分,那封装的意义是什么?用了泛型的data 只是用于指定规定结构体来用吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值