购物车组件文档

购物车组件

购物车组件是基于一级购物车、二级购物车、行业专区购物车等页面代码抽取的组件,该组件提供了获取普通购物车/行业专区Fragment、跳转到普通/行业专区二级购物车页面、刷新购物车图标数量、加入购物车等等服务。

一、使用方式

1、添加依赖

api project(':shoppingcart')

2、调用方式

ServiceFactory.getShoppingCartService().xxx();
//如: 获取购物车Fragment.
ServiceFactory.getShoppingCartService().getShoppingCartFragment();

二、功能介绍

1、获取用于首页展示的Fragment;

   /**
     * 获取一级购物车Fragment
     * @return ShoppingCartFragment.
     */
    EmptyShoppingCartFragment getShoppingCartFragment();

2、获取用于行业专区展示的Fragment;

   /**
     * 获取行业专区一级购物车Fragment
     * @return IndustryShoppingCartFragment.
     */
    EmptyShoppingCartFragment getIndustryShoppingCartFragment();

3、刷新购物车图标数量;

   /**
     * 刷新购物车图标数量
     */
    void refreshShoppingCartIcon();   

4、刷新行业专区购物车图标数量;

   /**
     * 刷新行业专区购物车图标数量
     */
    void refreshIndustryShoppingCartIcon();   

5、跳转到二级购物车页面;

   /**
     * 跳转到二级购物车页面
     */
    void startShoppingCartActivity();

6、跳转到行业专区二级购物车页面;

   /**
     * 跳转到行业专区二级购物车页面
     */
    void startIndustryAreaShoppingCart();

7、添加商品到购物车;

   /**
     * 添加商品到购物车
     * @param ydBaseView LifecycleView.
     * @param requestEntity goodsInfo.
     * @param listener response.
     */
    void addGoodsToShoppingCart(YDBaseView ydBaseView, ShoppingCartRequestEntity requestEntity, UpdateShoppingCartListener listener);

三、组件架构

该组件使用星链友店项目统一架构:MVP+VM实现

1、组件包结构

组件包结构

2、组件架构图

组件架构图

四、购物车页面设计思路

购物车作为一个业务逻辑非常复杂的页面,从编写之初就考虑如何拆分它,主要从两个方面着手:1、页面UI层面,把购物车列表拆分成店铺标题信息栏、满减活动信息栏以及商品信息栏这三个不同ItemType的Item,修改其中某一Item,而不影响其他Item;2、业务
逻辑上把大的业务逻辑拆分成小的业务逻辑,小的业务逻辑封装到一个个函数,把计算包邮、满减价格的复杂逻辑抽取到一个函数,使整个页面多个需要计算包邮、满减价格的地方调用的是同一个函数,便于维护。

页面UI拆分对应代码中的ViewModel

页面UI拆分对应代码中的ViewModel

五、购物车页面数据加载流程

1、在ShoppingCartPresenter类的onAttachView()调用refreshShoppingCartGoodsList()执行接口请求购物车列表数据;

Step1

2、通过Retrofit+RxJava发起接口请求得到数据源:Json字符串–解析–>ShoppingCartEntity实体类;

Step2

3、把ShoppingCartEntity实体类通过ShoppingCartFunction转化成ViewModel;

Step3

4、把ViewModel通过DataBinding绑定到View上;

Step4

六、购物车页面主要交互逻辑代码

1、请求购物车页面商品列表数据;

   /**
     * 请求购物车页面商品列表数据
     */
    private void requestShoppingCartGoodsList() {
        if(isRunningRefresh){
            return;
        }
        isRunningRefresh = true;
        mRequestModel.getShoppingCartGoodsList(source, String.valueOf(pageNum))
                .compose(new LifecycleTransformer<ShoppingCartEntity>(this))
                .map(mShoppingCartFunction)
                .subscribe(new YDLoadingSubscriber<ShoppingCartViewObject>(mShoppingCartView) {
                    @Override
                    public void onNext(ShoppingCartViewObject viewObject) {
                        isRunningRefresh = false;
                        isLastPage = viewObject.isLastPage;
                        mShoppingCartView.requestComplete();
                        if (viewObject.list.isEmpty() && isRefresh) {
                            if (!mShoppingCartVM.getIsNormalModel()) {
                                onClickTopActionButton(mShoppingCartVM);
                            }
                            mShoppingCartVM.setToolbarActionTextVisible(View.GONE);
                            mShoppingCartView.showErrorPage(EmptyPageType.EMPTY_PAGE);
                        } else {
                            mShoppingCartView.showNormalView();
                            mShoppingCartVM.setToolbarActionTextVisible(View.VISIBLE);
                            mShoppingCartView.setShoppingCartGoodsList(viewObject.list, isRefresh);
                        }
                        checkNumberInCart(viewObject.allNumberInCart);
                    }

                    @Override
                    public void onError(int code, String message) {
                        super.onError(code, message);
                        isRunningRefresh = false;
                        mShoppingCartView.requestComplete();
                        mShoppingCartVM.setToolbarActionTextVisible(View.GONE);
                        mShoppingCartVM.setBottomLayoutVisible(View.GONE);
                        mShoppingCartView.showErrorPage(EmptyPageType.SERVER_ERROR, ShoppingCartPresenter.this);
                    }
                });
    }

2、右上角编辑/完成点击事件;

   /**
     * 点击右上角编辑/完成按钮
     *
     * @param shoppingCartVM layout viewModel
     */
    public void onClickTopActionButton(ShoppingCartVM shoppingCartVM) {
        shoppingCartVM.setIsNormalModel(!shoppingCartVM.getIsNormalModel());
        boolean isNormalModel = shoppingCartVM.getIsNormalModel();
        if (isNormalModel) {
            int checkedSize = 0;
            int goodsItemSize = 0;
            int size = mViewObject.list.size();
            for (int i = 0; i < size; i++) {
                BindingAdapterItemType bindingAdapterItemType = mViewObject.list.get(i);
                if (bindingAdapterItemType instanceof ShoppingCartGoodsItemVM) {
                    ShoppingCartGoodsItemVM shoppingCartGoodsItemVM = (ShoppingCartGoodsItemVM) bindingAdapterItemType;
                    String uniqueId = shoppingCartGoodsItemVM.getUniqueId();
                    Boolean checkBoxEnable = shoppingCartVM.getEnabledMap().get(uniqueId);
                    if(checkBoxEnable != null) {
                        shoppingCartGoodsItemVM.setCheckBoxEnable(checkBoxEnable);
                    }
                    Boolean checkBoxIsChecked = shoppingCartVM.getCheckedMap().get(uniqueId);
                    shoppingCartGoodsItemVM.setCheckBoxIsChecked(checkBoxIsChecked != null ? checkBoxIsChecked : false);
                    if (shoppingCartGoodsItemVM.getCheckBoxEnable()) {
                        goodsItemSize++;
                        if (shoppingCartGoodsItemVM.getCheckBoxIsChecked()) {
                            checkedSize++;
                        }
                    }
                } else if(bindingAdapterItemType instanceof GoodsKindViewModel){
                    GoodsKindViewModel goodsKindViewModel = (GoodsKindViewModel) bindingAdapterItemType;
                    goodsKindViewModel.setCheckBoxEnable(goodsKindViewModel.getCheckBoxRealEnable());
                    goodsKindViewModel.setCheckBoxIsChecked(goodsKindViewModel.getCheckBoxRealChecked());
                    goodsKindViewModel.setIsFreePostage(TextUtils.equals(goodsKindViewModel.getPlatformFullFlag(), "1"));
                    goodsKindViewModel.setPostageVisibility(goodsKindViewModel.getIsFreePostage() ? View.VISIBLE : View.GONE);
                } else if(bindingAdapterItemType instanceof FullReduceViewModel){
                    ((FullReduceViewModel) bindingAdapterItemType).setRightVisibility(View.VISIBLE);
                }
            }
            shoppingCartVM.getEnabledMap().clear();
            shoppingCartVM.getCheckedMap().clear();

            //更新合计金额、总额、立省金额
            shoppingCartVM.setAllSelectCbEnable(shoppingCartVM.getRealAllSelectCbEnable());
            shoppingCartVM.setAllSelectCbChecked(checkedSize == goodsItemSize && checkedSize != 0);
            shoppingCartVM.setToolbarActionText("编辑");
            shoppingCartVM.setBottomActionText(checkedSize > 0 ? "结算(" + checkedSize + ")" : "结算");
            shoppingCartVM.setBottomActionTextEnable(checkedSize > 0);
            shoppingCartVM.setAllSelectTextVisible(View.GONE);
            shoppingCartVM.setSummationTextVisible(View.VISIBLE);

            //更新满减、包邮信息
            foreachCalcPostageAndFullReduce();
        } else {
            for (BindingAdapterItemType bindingAdapterItemType : mViewObject.list) {
                if (bindingAdapterItemType instanceof ShoppingCartGoodsItemVM) {
                    ShoppingCartGoodsItemVM shoppingCartGoodsItemVM = (ShoppingCartGoodsItemVM) bindingAdapterItemType;
                    String uniqueId = shoppingCartGoodsItemVM.getUniqueId();
                    shoppingCartVM.getEnabledMap().put(uniqueId, shoppingCartGoodsItemVM.getCheckBoxEnable());
                    shoppingCartVM.getCheckedMap().put(uniqueId, shoppingCartGoodsItemVM.getCheckBoxIsChecked());
                    shoppingCartGoodsItemVM.setCheckBoxEnable(true);
                    shoppingCartGoodsItemVM.setCheckBoxIsChecked(false);
                } else if (bindingAdapterItemType instanceof GoodsKindViewModel) {
                    GoodsKindViewModel goodsKindViewModel = (GoodsKindViewModel) bindingAdapterItemType;
                    goodsKindViewModel.setCheckBoxRealEnable(goodsKindViewModel.getCheckBoxEnable());
                    goodsKindViewModel.setCheckBoxEnable(true);
                    goodsKindViewModel.setCheckBoxRealChecked(goodsKindViewModel.getCheckBoxIsChecked());
                    goodsKindViewModel.setCheckBoxIsChecked(false);
                    goodsKindViewModel.setPostageVisibility(View.GONE);
                    goodsKindViewModel.setPostageTagVisible(View.GONE);
                    goodsKindViewModel.setRightArrowVisible(View.GONE);
                } else if(bindingAdapterItemType instanceof FullReduceViewModel){
                    ((FullReduceViewModel) bindingAdapterItemType).setRightVisibility(View.GONE);
                }
            }
            shoppingCartVM.setAllSelectCbEnable(true);
            shoppingCartVM.setAllSelectCbChecked(false);
            shoppingCartVM.setToolbarActionText("完成");
            shoppingCartVM.setBottomActionText("删除");
            shoppingCartVM.setBottomActionTextEnable(false);
            shoppingCartVM.setAllSelectTextVisible(View.VISIBLE);
            shoppingCartVM.setSummationTextVisible(View.GONE);
        }
    }

3、底部结算/删除按钮点击事件;

   /**
     * 点击底部结算/删除按钮
     */
    public void onClickActionButton(ShoppingCartVM viewModel) {
        //构建选中的商品Id+SpecId+amount的JsonString
        List<ShoppingCartSettleParam> paramEntities = new ArrayList<>();
        for (BindingAdapterItemType bindingAdapterItemType : mViewObject.list) {
            if(bindingAdapterItemType instanceof ShoppingCartGoodsItemVM){
                ShoppingCartGoodsItemVM goodsItemVM = (ShoppingCartGoodsItemVM) bindingAdapterItemType;
                if(goodsItemVM.getCheckBoxIsChecked()){
                    paramEntities.add(new ShoppingCartSettleParam(goodsItemVM.getGoodsId(), goodsItemVM.getSpecId()));
                }
            }
        }
        final String goodsListJson = JsonUtils.toJson(paramEntities);

        if (viewModel.getIsNormalModel()) { //普通模式:结算逻辑
            if (multiGoodsKind()) {
                CenterOneDialog oneDialog = CenterOneDialog.newInstance()
                        .setContent("当前选中项包含多个专区商品,暂不支持跨专区商品合并下单,请重新勾选商品提交")
                        .setRight("我知道了", null);
                oneDialog.show(getContext());
                return;
            }

            loading(true);
            mRequestModel.settle(goodsListJson, "", "", "", mShoppingCartView.getSource())
                    .compose(new LifecycleTransformer<JSONObject>(this))
                    .subscribe(new YDLoadingSubscriber<JSONObject>(mShoppingCartView) {
                        @Override
                        public void onNext(JSONObject jsonObject) {
                            int goodsStatusResult = 0;
                            try {
                                goodsStatusResult = jsonObject.getIntValue("goodsStatusResult");
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            if (goodsStatusResult == 1) {
                                PlatformSettleRequest settleRequest = new PlatformSettleRequest(goodsListJson, "", "");
                                Bundle bundle = new Bundle();
                                settleRequest.source = mShoppingCartView.getSource();
                                bundle.putSerializable("schema", settleRequest);
                                ServiceFactory.getOrderService().startConfirmOrderActivity(bundle);
                            } else {
                                showToast(jsonObject.getString("msg"));
                            }
                        }

                        @Override
                        public void onError(int code, String message) {
                            super.onError(code, message);
                            if (code == 3822001) {
                                PlatformSettleRequest settleRequest = new PlatformSettleRequest(goodsListJson, "", "");
                                Bundle bundle = new Bundle();
                                settleRequest.source = mShoppingCartView.getSource();
                                bundle.putSerializable("schema", settleRequest);
                                ServiceFactory.getOrderService().startConfirmOrderActivity(bundle);
                            } else if (code == 3829010 || code == 3829011 || code == 3829012) {
                                Bundle bundle = new Bundle();
                                bundle.putString("error_code_key", String.valueOf(code));
                                ARouter.getInstance().build(Constants.PERSON_CERTIFICATION_ACTIVITY).with(bundle).navigation();
                            }
                        }
                    });
        } else { //编辑模式:删除逻辑
            CenterTwoDialog dialog = CenterTwoDialog.newInstance();
            dialog.setContent("确定要删除这些商品吗?")
                    .setRight(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            deleteGoods(goodsListJson);
                        }
                    }).show(mContext);
        }
    }  

4、点击删除商品;

   /**
     * 删除商品
     * @param ids delete
     */
    private void deleteGoods(String ids) {
        loading(true);
        mRequestModel.selfBatchDeleteCart(ids, mShoppingCartView.getSource())
                .compose(new LifecycleTransformer<>(this))
                .subscribe(new YDLoadingSubscriber<Object>(mShoppingCartView) {
                    @Override
                    public void onNext(@io.reactivex.annotations.NonNull Object value) {
                        super.onNext(value);
                        showToast("删除成功");
                        //刷新购物车
                        mShoppingCartView.refreshShoppingCart();
                    }
                });
    }

5、点击商品Item;

   /**
     * 商品Item点击事件
     *
     * @param viewModel goods viewModel
     */
    @Override
    public void onItemClick(ShoppingCartGoodsItemVM viewModel) {
        String source = mShoppingCartView.getSource();
        ServiceFactory.getGoodsDetailFictitiousService().entryGoodsDetail(viewModel.getGoodsId(), TextUtils.equals(viewModel.getIsShopBag(), "1"), source);
    }

6、长按商品Item;

   /**
     * 商品Item长按事件
     *
     * @param viewModel goods viewModel
     */
    @Override
    public boolean onItemLongClick(final ShoppingCartGoodsItemVM viewModel) {
        XDialog boxDialog = XDialog.buildDialog(getContext(), R.layout.dialog_shopping_cart_delete, new XDialog.OnClickListener() {
            @Override
            public void onClick(Dialog dialog, View view) {
                dialog.dismiss();
                if (view.getId() == R.id.delete_tv) {
                    List<ShoppingCartSettleParam> paramEntities = new ArrayList<>();
                    ShoppingCartSettleParam entity = new ShoppingCartSettleParam(viewModel.getGoodsId(), viewModel.getSpecId());
                    paramEntities.add(entity);
                    String params = JsonUtils.toJson(paramEntities);
                    deleteGoods(params);
                }
            }
        });
        boxDialog.show();
        return true;
    }

7、点击京东优选包邮标签;

   /**
     * 点击京东优选包邮标签
     */
    public void onClickFreePostageTag(GoodsKindViewModel viewModel){
        if (mPostageExplainDialog == null) {
            mPostageExplainDialog = new FreePostageExplainDialog(mContext);
        }
        mPostageExplainDialog.setDialogContent(viewModel.getPlatformFullText());
        mPostageExplainDialog.show();
    }

8、点击去凑单(京东优选);

   /**
     * 点击去凑单(京东优选)
     */
    public void onClickAddMoreGoods(GoodsKindViewModel viewModel){
        if (TextUtils.equals(viewModel.getKindId(), "1")) { //京东优选
            double diffFreePostage = viewModel.getDiffFreePostage();
            if (diffFreePostage > 0) {
                Bundle bundle = new Bundle();
                bundle.putDouble(ShoppingCartConstant.KEY_DIFF_PRICE_FREE_POSTAGE, diffFreePostage);
                bundle.putDouble(ShoppingCartConstant.KEY_JD_TOTAL_PRICE, viewModel.getShopGoodsTotalPrice());
                boolean fromMain = false;
                if(mContext instanceof YDBaseActivity){
                    YDBaseActivity baseActivity = (YDBaseActivity) mContext;
                    String simpleName = baseActivity.getClass().getSimpleName();
                    if(simpleName.contains("MainActivity")){
                        fromMain = true;
                    }
                }
                bundle.putBoolean(ShoppingCartConstant.KEY_FROM_MAIN, fromMain);
                ServiceFactory.getShoppingCartService().goToMakeOrderActivity((Activity) mContext, bundle, REQUEST_CODE);
            }
        }
    }

9、点击去凑单(友店商城);

   /**
     * 点击去凑单(友店商城)
     */
    public void onClickGatherTogether(FullReduceViewModel viewModel){
        ARouter.getInstance().build(Constants.SEARCH_MONEY_OFF_ACTIVITY_PATH)
                .withString("full_reduce_id", viewModel.getFullReduceId())
                .navigation();
    }

10、点击编辑商品数量;

   /**
     * 点击编辑商品数量
     * @param viewModel
     */
    @Override
    public void onClickEditGoodsQuantity(final ShoppingCartGoodsItemVM viewModel){
        if(mContext instanceof YDBaseActivity) {
            if (mEditGoodsQuantityDialog == null) {
                mEditGoodsQuantityDialog = new EditGoodsQuantityDialog(mContext, mShoppingCartView.getSource());
            }
            mEditGoodsQuantityDialog.setConfirmListener(new EditGoodsQuantityDialog.OnClickConfirmListener() {
                @Override
                public void onClickConfirm(String goodsQuantity) {
                    updateGoodsQuantity(viewModel, goodsQuantity, "1");
                }
            });
            mEditGoodsQuantityDialog.setGoodsQuantity(viewModel.getGoodsQuantity());
            mEditGoodsQuantityDialog.show();
        }
    }

11、点击增加商品数量;

   /**
     * 点击增加商品数量
     *
     * @param viewModel goods viewModel
     */
    @Override
    public void onClickAdd(final ShoppingCartGoodsItemVM viewModel) {
        int goodsQuantityInt = viewModel.getGoodsQuantityInt();
        updateGoodsQuantity(viewModel, String.valueOf(++goodsQuantityInt), "1");
    }

12、点击减少商品数量;

   /**
     * 点击减少商品数量
     *
     * @param viewModel goods viewModel
     */
    @Override
    public void onClickMinus(final ShoppingCartGoodsItemVM viewModel) {
        int goodsQuantityInt = viewModel.getGoodsQuantityInt();
        updateGoodsQuantity(viewModel, String.valueOf(--goodsQuantityInt), "1");
    }

13、点击选中商品Item;

   /**
     * 点击选中商品Item
     *
     * @param viewModel goods viewModel
     */
    @Override
    public void onClickCheckItem(ShoppingCartGoodsItemVM viewModel) {
        //更新当前商品所在店铺CheckBox状态
        viewModel.updateShopCheckState();

        //更新包邮、满减、合计金额、总额、立省、全选CheckBox状态和底部结算/删除按钮状态
        //购物车中所有商品数量(不包含不可点的)
        int enableGoodsItemSize = 0;
        //选中的商品数量
        int checkedSize = 0;

        //购物车中所有商品列表
        for (BindingAdapterItemType bindingAdapterItemType : mViewObject.list) {
            if (bindingAdapterItemType instanceof ShoppingCartGoodsItemVM) {
                ShoppingCartGoodsItemVM shoppingCartGoodsItemVM = (ShoppingCartGoodsItemVM) bindingAdapterItemType;
                if (shoppingCartGoodsItemVM.getCheckBoxEnable()) {
                    enableGoodsItemSize++;
                    if (shoppingCartGoodsItemVM.getCheckBoxIsChecked()) {
                        checkedSize++;
                    }
                }
            }
        }
        //更新全选CheckBox状态、结算/删除按钮状态
        mShoppingCartVM.setBottomActionTextEnable(checkedSize > 0);
        mShoppingCartVM.setAllSelectCbChecked(checkedSize == enableGoodsItemSize && checkedSize != 0);
        if (mShoppingCartVM.getIsNormalModel()) {
            mShoppingCartVM.setBottomActionText(checkedSize > 0 ? "结算(" + checkedSize + ")" : "结算");
        }

        if (mShoppingCartVM.getIsNormalModel()) {
            //计算当前专区商品列表
            mShoppingCartFunction.calcPostageAndFullReduce(viewModel, false);
        }
    }

14、点击店铺全选;

   /**
     * 点击店铺全选
     * @param viewModel shop viewModel.
     */
    public void onClickCheckShopItem(GoodsKindViewModel viewModel){
        //更新当前店铺下商品选中状态
        boolean shopSelectCbChecked = viewModel.getCheckBoxIsChecked();
        List<ShoppingCartGoodsItemVM> shopGoodsItemVMList = viewModel.getShopGoodsItemVMList();
        if(shopGoodsItemVMList != null) {
            for (ShoppingCartGoodsItemVM shoppingCartGoodsItemVM : shopGoodsItemVMList) {
                shoppingCartGoodsItemVM.setCheckBoxIsChecked(shopSelectCbChecked);
            }
        }

        //更新包邮、满减、合计金额、总额、立省、全选CheckBox状态和底部结算/删除按钮状态
        //购物车中所有商品数量(不包含不可点的)
        int enableGoodsItemSize = 0;
        //选中的商品数量
        int checkedSize = 0;

        //购物车中所有商品列表
        for (BindingAdapterItemType bindingAdapterItemType : mViewObject.list) {
            if (bindingAdapterItemType instanceof ShoppingCartGoodsItemVM) {
                ShoppingCartGoodsItemVM shoppingCartGoodsItemVM = (ShoppingCartGoodsItemVM) bindingAdapterItemType;
                if (shoppingCartGoodsItemVM.getCheckBoxEnable()) {
                    enableGoodsItemSize++;
                    if (shoppingCartGoodsItemVM.getCheckBoxIsChecked()) {
                        checkedSize++;
                    }
                }
            }
        }

        //更新全选CheckBox状态、结算/删除按钮状态
        mShoppingCartVM.setBottomActionTextEnable(checkedSize > 0);
        mShoppingCartVM.setAllSelectCbChecked(checkedSize == enableGoodsItemSize && checkedSize != 0);
        if (mShoppingCartVM.getIsNormalModel()) {
            //计算当前专区商品列表
            foreachCalcPostageAndFullReduce();
            mShoppingCartVM.setBottomActionText(checkedSize > 0 ? "结算(" + checkedSize + ")" : "结算");
        }
    }

15、点击底部整个购物车全选;

   /**
     * 点击底部整个购物车全选
     *
     * @param viewModel goods viewModel
     */
    public void onClickCheckAll(ShoppingCartVM viewModel) {
        boolean allSelectCbChecked = viewModel.getAllSelectCbChecked();
        int checkedSize = 0;
        for (BindingAdapterItemType bindingAdapterItemType : mViewObject.list) {
            if (bindingAdapterItemType instanceof GoodsKindViewModel) {
                ((GoodsKindViewModel) bindingAdapterItemType).setCheckBoxIsChecked(allSelectCbChecked);
            } else if (bindingAdapterItemType instanceof ShoppingCartGoodsItemVM) {
                checkedSize++;
                ((ShoppingCartGoodsItemVM) bindingAdapterItemType).setCheckBoxIsChecked(allSelectCbChecked);
            }
        }
        foreachCalcPostageAndFullReduce();
        viewModel.setBottomActionTextEnable(allSelectCbChecked);
        if (viewModel.getIsNormalModel()) {
            viewModel.setBottomActionText(allSelectCbChecked ? "结算(" + checkedSize + ")" : "结算");
        }
    }

七、注意事项

1、秒杀商品不计入满减计算逻辑;

八、版本日志

时间修改记录作者
2019年12月05日完成初步文档编写吴忠园
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值