安全传输平台项目——配置管理终端-框架搭建-初始化

在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

10-安全传输平台项目-第09天(配置管理终端-框架搭建-初始化)

 

一、复习

1、复习数据库写入
2、复习框架导入

》创建MFC项目:

主函数(类似于main)在SecMngAdmin0325.cpp中。

界面部分在MainFrm.cpp中,需要在其中添加启动的样式:

1)切换到“类视图”,在“CMainFrame”右键选择“类向导”,选择“类向导”,点击“虚函数”,点击“OnCreateClient”,点击“应用”,点击“确定”。

然后在其中添加代码:

>CMainFrame::OnCreateClient重写代码如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
    // TODO: 在此添加专用代码和/或调用基类
    if (!wndSplitter.CreateStatic(this, 1, 2)) return false;

    if (!wndSplitter.CreateView(0, 1,RUNTIME_CLASS(CFormBackground), CSize(0,0), pContext))     
        return false;

    //pContext->m_pNewViewClass RUNTIME_CLASS(CFormUserManager) CFormUserManager
    DWORD dwf = CGfxOutBarCtrl::fDragItems|
        CGfxOutBarCtrl::fEditGroups|
        CGfxOutBarCtrl::fEditItems|
        CGfxOutBarCtrl::fRemoveGroups|
        CGfxOutBarCtrl::fRemoveItems|
        CGfxOutBarCtrl::fAddGroups|
        CGfxOutBarCtrl::fAnimation; 

    wndBar.Create(WS_CHILD|WS_VISIBLE, CRect(0,0,0,0), &wndSplitter, 
        wndSplitter.IdFromRowCol(0, 0), dwf);
    wndBar.SetOwner(this);

    imaLarge.Create(32, 32, true, 2, 1);
    HICON hIcon;

    for (int i=0; i<7; ++i) 
    {
        hIcon= AfxGetApp()->LoadIcon (nImages[i]);
        imaLarge.Add (hIcon);
    }

    wndBar.SetImageList(&imaLarge, CGfxOutBarCtrl::fLargeIcon);
    wndBar.SetImageList(&imaSmall, CGfxOutBarCtrl::fSmallIcon);

    wndTree.Create(WS_CHILD|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, 
        CRect(0,0,0,0), &wndBar, 1010);
    wndTree.SetImageList(&imaSmall, TVSIL_NORMAL);    
    wndBar.SetAnimationTickCount(20);    
    wndBar.SetAnimSelHighlight(200);

    wndBar.AddFolder("SecMngServer配置管理", 0);
    wndBar.AddFolder("SecMngAdmin网点管理", 1);
    wndBar.AddFolder("人员管理", 2);
    wndBar.AddFolder("设备管理", 3);
    //wndBar.AddFolder("CA人员操作查询", 4);    

    wndBar.InsertItem(0, 0, "SecMngServer配置", 0, 0);
    wndBar.InsertItem(0, 1, "网点信息管理", 1, 0); 
    wndBar.InsertItem(0, 2, "后台业务管理", 4, 0); //
    wndBar.InsertItem(0, 3, "后台交易查询", 5, 0); //

    wndBar.InsertItem(1, 0, "前台体系管理", 6, 0);     
    wndBar.InsertItem(1, 1, "前台业务管理", 4, 0);
    wndBar.InsertItem(1, 2, "前台交易查询", 3, 0); 

    wndBar.InsertItem(2, 0, "创建人员", 3, 0); 
    wndBar.InsertItem(2, 1, "冻结人员", 4, 0); 
    wndBar.InsertItem(2, 2, "解冻", 2, 0); 
    wndBar.InsertItem(2, 3, "注销人员", 1, 0);     

    wndBar.InsertItem(3, 0, "创建设备", 5, 0); 
    wndBar.InsertItem(3, 1, "注销管理", 4, 0); 

    wndBar.SetSelFolder(0);

    CRect r;
    GetClientRect(&r);
    int w1 = r.Width()/5;
    int w2 = r.Width()/4;

    wndSplitter.SetColumnInfo( 0, w1, 0 );
    wndSplitter.SetColumnInfo( 1, w2, 0 );
    wndSplitter.RecalcLayout();
    return true;

    //return CFrameWndEx::OnCreateClient(lpcs, pContext);
}
CMainFrame::OnCreateClient

2)在MainFrm.h中,包含相应头文件,添加对象变量定义
添加

#include "GfxSplitterWnd.h"
#include "GfxOutBarCtrl.h"

然后在class CMainFrame: public CFrameWnd中添加声明:

// 特性
public:
    CGfxSplitterWnd        wndSplitter;
    CGfxOutBarCtrl        wndBar;       
    CImageList            imaLarge, imaSmall;       
    CTreeCtrl            wndTree;

3)这时编译运行,只剩两个错误:

先解决第二个错误:

在 CMainFrame::OnCreateClient函数之前添加定义nImages:

static UINT nImages[] =
{
    IDI_ICON_SET,
    IDI_ICON_USER,
    IDI_ICON_OP_LOG,
    IDI_ICON_LOG,
    IDI_ICON_REQ,
    IDI_ICON_RE,
    IDI_ICON_REPORT,
};

然后添加7张图片:

ico目录下有(log.ico、op_log.ico、re.ico、report.ico、req.ico、set.ico、user.ico)7个ico图片放入项目的文件夹的下一级res目录下;然后打开“资源视图”,在“secmngAdmin411.rc”右键“添加资源”,点击“导入”,选择这7个ico文件,点击“打开”(这时多了一个Icon目录,里面有这7个文件),右键“属性”进行设置ID:

其ID 更改:IDC_ICON7(人图标)更改为:IDI_ICON_USER;
IDC_ICON6更改为:IDI_ICON_SET;
IDC_ICON5更改为:IDI_ICON_REQ;
IDC_ICON4更改为:IDI_ICON_REPORT;
IDC_ICON3更改为:IDI_ICON_RE;
IDC_ICON2更改为:IDI_ICON_OP_LOG;
IDC_ICON1更改为:IDI_ICON_LOG;

注意,每步更改后,点击“都保存”,会弹出警告-修改影响多处,点击“是”。

4)这时编译运行,只剩1个错误:

打开“资源视图”,添加“Dialog”:

在资源视图左侧“Dialog”处右键“插入Dialog”,然后删除“确定”和“取消”按钮,修改对话框的ID(在“IDD_DIALOG1”右键“属性”进行修改ID为:IDD_FORMBACKGROUND_FORM);

点击对话框,修改属性:修改Border属性“外框对话框”配置成None;Style属性“Popup”配置成child

点击对话框,右键“添加类”(或者“双击”),然后输入类名:CFormBackground,基类选择: CFormView

然后,包含类对象:在MainFrom头文件中添加   #include "FormBackground.h"

最后点击“运行”,会弹出:

 

二、安全传输平台项目——配置管理终端-框架搭建-初始化

1、重画背景onDrow

1)切换到“类视图”,选择“CFormBackground”,右键点击“类向导”,选择“虚函数”:

然后在其中添加代码:

>CFormBackground::OnDraw重写代码如下:(注意:函数注释掉的参数pDC打开!)

void CFormBackground::OnDraw(CDC* pDC)
{
    // TODO: 在此添加专用代码和/或调用基类
    CRect clientRect;
    GetClientRect(&clientRect);    

    for(int k = 13 ;k< 18;k++) //绘图示例—显示位图
    {
        CBrush* pTempBrush = NULL;
        CBrush OrigBrush;
        OrigBrush.FromHandle((HBRUSH)pTempBrush); 

        CRect rc;
        GetClientRect(&rc);
        //ScreenToClient(&rc);
        try
        {
            CBitmap bmp;
            bmp.LoadBitmap(IDB_BITMAP_BACK);
            CBrush brush(&bmp);

            pTempBrush = (CBrush*)pDC->SelectObject(brush);

            pDC->Rectangle(rc.left,rc.top, rc.Width(), rc.Height());
            pDC->SelectObject(&OrigBrush);
            break;
        }
        catch(CResourceException* e)
        {
            e->ReportError();
            e->Delete();
        }            
    }

    CRect rect;
    GetClientRect(&rect);
    CRect rect2;
    GetClientRect(&rect2);

    CFont font ;
    font.CreatePointFont(340, _T("Arial"));
    CString string = "欢迎使用KeyMngServer管理终端";

    pDC->SelectObject(&font);
    pDC->SetBkMode(TRANSPARENT);
    rect.OffsetRect(6, -90); //背影
    pDC->SetTextColor( RGB(192, 192, 192));
    pDC->DrawText(string, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);

    rect2.OffsetRect(0, -100);
    pDC->SetTextColor( RGB(0, 0, 0));
    pDC->DrawText(string, &rect2, DT_SINGLELINE|DT_CENTER|DT_VCENTER);    

}
void CFormBackground::OnDraw(CDC* pDC)

2)bmp目录下有(background.bmp)1个bmp图片放入项目的文件夹的下一级res目录下;然后打开“资源视图”,在“secmngAdmin411.rc”右键“添加资源”,点击“导入”,选择这1个bmp文件,点击“打开”(这时多了一个Bitmap目录,里面有这7个文件),右键“属性”进行设置ID:

其ID 更改:IDB_BITMAP1更改为:IDB_BITMAP_BACK;

最后点击“运行”,会弹出:

 

2、界面切换-CCfgView

CMainFrame类中添加视图切换自定义消息

1)在MainFrame.h中添加自定义消息声明:

// 生成的消息映射函数
protected:    
DECLARE_MESSAGE_MAP()
afx_msg long OnOutbarNotify(WPARAM wParam, LPARAM lParam);//声明

2)在MainFrame.cpp中添加自定义消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
… …
ON_MESSAGE(WM_OUTBAR_NOTIFY, OnOutbarNotify) // 注意不能添加分号!!!
……
END_MESSAGE_MAP()

3)在MainFrame.cpp中添加消息映射函数的实现

long CMainFrame::OnOutbarNotify(WPARAM wParam, LPARAM lParam)
{     
    switch (wParam)
    {        
       case NM_OB_ITEMCLICK:
           // cast the lParam to an integer to get the clicked item
          {
               int index = (int) lParam;
               CString cText, cs1;
               cText = wndBar.GetItemText(index);                
               CCreateContext   Context;
         
               if (cText==_T("SecMngServer配置"))
               {
                   Context.m_pNewViewClass = RUNTIME_CLASS(CCfgView);
                   Context.m_pCurrentFrame = this;
                   Context.m_pLastView = (CView *)wndSplitter.GetPane(0,1);
                   wndSplitter.DeleteView(0,1);
                   wndSplitter.CreateView(0,1,RUNTIME_CLASS(CCfgView),CSize(500,0),&Context);
                   CCfgView *pNewView=(CCfgView *)wndSplitter.GetPane(0,1);                      
                   wndSplitter.RecalcLayout();
                      pNewView->OnInitialUpdate();
                   wndSplitter.SetActivePane(0,1);  
                   //IsHisKeyRecovry=0;           
               }
               
               else if (cText==_T("网点信息管理"))
               {                   
                   Context.m_pNewViewClass = RUNTIME_CLASS(CDlgNetInfo);
                   Context.m_pCurrentFrame = this;
                   Context.m_pLastView = (CView *)wndSplitter.GetPane(0,1);
                   wndSplitter.DeleteView(0,1);
                   wndSplitter.CreateView(0,1,RUNTIME_CLASS(CDlgNetInfo),CSize(500,0),&Context);
                   CDlgNetInfo *pNewView=(CDlgNetInfo *)wndSplitter.GetPane(0,1);                      
                   wndSplitter.RecalcLayout();
                   pNewView->OnInitialUpdate();
                   wndSplitter.SetActivePane(0,1);
               }    
               
               else if (cText==_T("后台业务管理"))
               {
                     //AfxMessageBox(cText);
                   Context.m_pNewViewClass = RUNTIME_CLASS(CSysAll);
                   Context.m_pCurrentFrame = this;
                   Context.m_pLastView = (CView *)wndSplitter.GetPane(0,1);
                   wndSplitter.DeleteView(0,1);
                   wndSplitter.CreateView(0,1,RUNTIME_CLASS(CSysAll),CSize(500,0),&Context);
                   CSysAll *pNewView=(CSysAll *)wndSplitter.GetPane(0,1);                      
                   wndSplitter.RecalcLayout();
                   pNewView->OnInitialUpdate();
                   wndSplitter.SetActivePane(0,1); 
               } 
          }
        
        return 0;
          
        case NM_OB_ONLABELENDEDIT:
            // cast the lParam to an OUTBAR_INFO * struct; it will contain info about the edited item
            // return 1 to do the change and 0 to cancel it
            {
                /*
                if(IsLoginOutFlag == 1)
                {
                    AfxMessageBox("人员已登出,请重新登录CA人员以进行相应操作。");
                    return 1;
                }
                */
                
                OUTBAR_INFO * pOI = (OUTBAR_INFO *) lParam;
                TRACE2("Editing item %d, new text:%s\n", pOI->index, pOI->cText);
            }
            return 1;
            
        case NM_OB_ONGROUPENDEDIT:
            // cast the lParam to an OUTBAR_INFO * struct; it will contain info about the edited folder
            // return 1 to do the change and 0 to cancel it
            {
                /*
                if(IsLoginOutFlag == 1)
                {
                    AfxMessageBox("人员已登出,请重新登录人员以进行相应操作。");
                    return 1;
                }
                */

                OUTBAR_INFO * pOI = (OUTBAR_INFO *) lParam;
                TRACE2("Editing folder %d, new text:%s\n", pOI->index, pOI->cText);
            }
            return 1;
            
        case NM_OB_DRAGITEM:
            // cast the lParam to an OUTBAR_INFO * struct; it will contain info about the dragged items
            // return 1 to do the change and 0 to cancel it
            {
                /*
                if(IsLoginOutFlag == 1)
                {
                    AfxMessageBox("人员已登出,请重新登录人员以进行相应操作。");
                    return 1;
                }*/

                OUTBAR_INFO * pOI = (OUTBAR_INFO *) lParam;
                TRACE2("Drag item %d at position %d\n", pOI->iDragFrom, pOI->iDragTo);
            }
            return 1;
    }
    return 0;
}
long CMainFrame::OnOutbarNotify(WPARAM wParam, LPARAM lParam)

4)打开“资源视图”,添加“Dialog”:

(1)在资源视图左侧“Dialog”处右键“插入Dialog”,然后删除“确定”和“取消”按钮,修改对话框的ID(在“IDD_DIALOG2”右键“属性”进行修改ID为:IDD_DIALOG_CFG);

(2)点击对话框,修改属性:修改Border属性“外框对话框”配置成None;Style属性“Popup”配置成child;

(3)点击对话框,右键“添加类”,然后输入类名:CCfgView,基类选择: CFormView

(4)然后,包含类对象:在MainFrom头文件中添加   #include "CfgView.h"

(5)在IDD_DIALOG_CFG的Dialog中添加:

 

3、界面切换-网点信息管理界面NetInfo

(1)在资源视图左侧“Dialog”处右键“插入Dialog”,然后删除“确定”和“取消”按钮,修改对话框的ID(在“IDD_DIALOG3”右键“属性”进行修改ID为:IDD_DIALOG_NETMNG);

(2)点击对话框,修改属性:修改Border属性“外框对话框”配置成None;Style属性“Popup”配置成child;

(3)点击对话框,右键“添加类”,然后输入类名:CDlgNetInfo,基类选择: CFormView

(4)然后,包含类对象:在MainFrom头文件中添加   #include "DlgNetInfo.h"

(5)在IDD_DIALOG_CFG的Dialog中添加:

 

同理,

为COpTranView类添加Dialog资源(id可以命名:IDD_DIALOG_TRAN)

CSysAll类添加Dialog资源(id可以命名:IDD_DIALOG_SYSALL)

 

4、多态知识回顾

面向对象:继承(子类可以使用父类的变量和函数)、多态、封装(功能相近和相似的代码集成)

多态:

1)父类指针指向子类对象;2)继承;3)虚函数重写

练习:

class parent
{
    public:
        virtual void print()
        {
            printf("I am parent.\n");
        }
}

class child:public parent
{
    public:
        virtual void print()
        {
            printf("I am child.\n");
        }
}

void howToPrint(parent *p)
{
    p->print();
}

int main()
{
    parent p1;
    child c1;
    howToPrint(&p1);
    howToPrint(&c1);//多态
}
test.cpp

多态实现的原理:1)每个类对象有一个vptr指针,指向虚函数表首地址;2)虚函数表

 

5、多态分析和开源源码走读

为什么重写了OnCreateClient函数,可以实现左侧的样式?

》项目中的多态分析:

 

6、小结:

》对接开源框架相关:

1)创建MFC项目;

2)导入开源文件  9个(.cpp .h);

3)CString --> const char *  在项目上右键--> 属性 --> 字符集:使用unicode字符集 --> 使用多字节字符集;

  VS2013:如果,上述操作不生效。使用管理员身份运行:vc_mbcsmfc.exe

4)导入.cur图片资源 --> MFC项目资源目录res中;

5)“资源视图”标签,任意一个目录上 右键“添加资源”-->“导入”选择res中的.cur 文件(3个)添加到项目中。

6)根据错误提示,修改ID;

7)添加消息宏定义 resource.h  -->正常编译

#define ID_GFX_SMALLICON                50000
#define ID_GFX_LARGEICON                50001
#define ID_GFX_RENAMEITEM                50002
#define ID_GFX_REMOVEITEM                50003
#define ID_GFX_GROUPICON                 50004
#define ID_GFX_FONTCICON                 50005
#define ID_GFX_BACKCICON                 50006

8)给CMainFrame类 重写父类的 onCreateClient() 虚函数;

9)添加代码实现 QQ 抽屉效果:(1)视图的切分;(2)视图的切换;

10)添加类对应头文件 --MainFrame.h

#include "GfxSplitterWnd.h"
#include "GfxOutBarCtrl.h"

11)添加类变量 --MainFram.h

public:
    CGfxSplitterWnd        wndSplitter;
    CGfxOutBarCtrl        wndBar;       
    CImageList            imaLarge, imaSmall;       
    CTreeCtrl            wndTree;

12)添加控件Dialog

  在“资源视图”的“Dialog”目录上右击,添加一个新的Dialog

  修改ID、修改Dialog属性 Border --> None、修改 Style属性 Popup -->child

13)给Dialog添加类CFormBackground

  继承自CFormView 类

  #include "FormBackground.h" 添加到 MainFrame.cpp或MainFrame.h

14)onCreateClient() 函数实现之前 nImages 数组

static UINT nImages[] =
{
    IDI_ICON_SET,
    IDI_ICON_USER,
    IDI_ICON_OP_LOG,
    IDI_ICON_LOG,
    IDI_ICON_REQ,
    IDI_ICON_RE,
    IDI_ICON_REPORT,
};

15)导入.ico图片到项目res目录中

  一次修改ID(7个)

16)添加背景图片

  给CFormBackground 重写onDraw函数 -->用到bmp 图片资源

  在函数内部添加代码。

  导入 background.bmp图片

  修改ID

17)完成视图切换功能

  (1)添加消息声明

    afx_msg long OnOutbarNotify(WPARAM wParam, LPARAM lParam);

  (2)注册消息映射

    ON_MESSAGE(WM_OUTBAR_NOTIFY, OnOutbarNotify)

  (3)对应消息声明添加实现。-->MainFram.cpp

    在函数内部添加代码。

18)添加控件Dialog

  (1)在“资源视图”的“Dialog”目录上右击,添加一个新的Dialog

  修改ID、修改Dialog属性 Border --> None、修改 Style属性 Popup -->child

  给Dialog添加类CCfgView

  #include "CfgView.h" 添加到MainFram.cpp 或 MainFram.h

  【可选】在Dialog中添加控件

  (2)在“资源视图”的“Dialog”目录上右击,添加一个新的Dialog

  修改ID、修改Dialog属性 Border --> None、修改 Style属性 Popup -->child

  给Dialog添加类CDlgNetInfo

  #include "DlgNetInfo.h" 添加到MainFram.cpp 或 MainFram.h

  【可选】在Dialog中添加控件

 

7、管理终端功能简析

 

 

8、初始化-获取配置文件路径

 

 

9、创建对话框

 

 

10、弹窗供用户输入信息

 

11、将用户录入数据保存ini文件

 

12、全局变量赋值及取消按钮

 

13、测试连接数据库

 

14、总结

 

 

 

 

在学习安全传输平台项目总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

### RS485配置标准EIA-754-1985方法教程 #### 一、RS485简介 RS485是一种用于平衡传输线路的数据终端设备和数据传输设备之间的串行二进制数据交换的电气特性规定[^1]。它支持多点通信,能够实现远距离高效可靠的数据传输。 #### 二、遵循EIA-754-1985标准的关键要素 为了确保RS485网络按照EIA-754-1985标准正常工作,需注意以下几个方面: ##### 数据速率与电缆长度关系 最大允许的数据速率取决于所使用的双绞线的最大长度以及其电容特性。对于大多数应用场合而言,在不超过1200米的距离内可以达到最高10Mbps的速度;而在更长距离下则需要降低速度以维持信号质量。 ##### 终端匹配电阻设置 为了避免反射波造成干扰并提高抗噪能力,应在总线两端安装约等于传输介质特征阻抗(通常为120Ω)大小的终端匹配电阻。当只有两个节点参与通信时可省略此操作,但在多个节点构成复杂拓扑结构的情况下务必加入这些元件来优化性能表现。 ##### 接地处理 尽管差分模式本身具有较好的共模抑制效果,但仍建议将整个系统的公共接地良好连接在一起,从而减少由于不同地点间存在较大电压差异而引起的潜在问题。 #### 三、基于STM32平台下的RS485接口初始化实例 下面给出一段利用STM32CubeMX工具生成的基础代码框架,并通过修改部分参数完成对USART外设及其关联GPIO引脚的功能设定过程说明[^2]。 ```c // 初始化USART1, 设置波特率为115200bps UART_HandleTypeDef huart1; void MX_USART1_UART_Init(void){ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; // 波特率设置 huart1.Init.WordLength = UART_WORDLENGTH_8B;// 字符长度 huart1.Init.StopBits = UART_STOPBITS_1; // 停止位数 huart1.Init.Parity = UART_PARITY_NONE; // 校验方式 huart1.Init.Mode = UART_MODE_TX_RX; // 发送接收使能 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 流控选项 huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart1) != HAL_OK){ Error_Handler(); } } // PB5作为RE/DE控制引脚 static void MX_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); // 开启GPIOB时钟 /*Configure GPIO pin : PB5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } ``` 上述代码片段展示了如何针对特定型号单片机进行基本外围电路搭建的同时也兼顾到了实际应用场景中的灵活性需求——即可以通过调整`huart1.Init.*`成员变量来自定义更多细节属性比如奇偶校验类型或是停止位数目等等。 #### 四、Modbus RTU协议集成指南 如果计划让RS485链路上运行Modbus RTU协议,则除了以上提到的内容之外还需要额外考虑如下事项: - **地址分配**: 每个从站都需要被赋予独一无二的逻辑地址以便于主站在发起请求时准确定位目标对象; - **帧格式构建**: 构造符合规范的消息包体,包括但不限于功能码的选择、寄存器起始位置及数量指定等字段填充规则; - **CRC检验计算**: 对每一帧报文实施循环冗余校验(CRC),以此保障信息传递过程中不会因为外界因素影响而导致误判现象发生[^3]. 综上所述,正确理解和严格执行EIA-754-1985有关RS485物理层的各项指标要求是建立稳定可靠的工业自动化控制系统不可或缺的前提条件之一.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值