用C++写一个自己的QQ(四、账户设置)

37 篇文章 3 订阅
9 篇文章 2 订阅

一、封装类

将账户设置可能的操作,封装到一个类中

通过分析,它应该有以下几个功能

  1. 通过id号获取该id对应的账户信息
  2. 获取所有账户信息
  3. 获取部门主管信息
  4. 通过部门id获取此部门所有账户信息
  5. 添加账户
  6. 设置账户为主管
  7. 获取最新添加的账户信息
  8. 删除账户

.cpp文件

#include "pch.h"
#include "AccountCtrl.h"

AccountCtrl::AccountCtrl()
{
	m_sql = MysqlUtil::GetInstance();
}

AccountCtrl::~AccountCtrl()
{

}

bool AccountCtrl::GetAccountInfo(AccountInfo& account, int id)
{
	vector<vector<string>> temp;
	if (!m_sql->SelectData(temp, "Select * from tb_account where account_id = "+ to_string(id) + ";")) {
		return false;
	}
	vector<string> d = temp.at(0);
	AccountInfo value;
	value.account_id = atoi(d.at(FIELD_ACCOUNT_ID).c_str());
	value.name = CString(d.at(FIELD_ACCOUNT_NAME).c_str());
	value.password = CString(d.at(FIELD_ACCOUNT_PASSWORD).c_str());
	value.sex = CString(d.at(FIELD_ACCOUNT_SEX).c_str());
	value.age = atoi(d.at(FIELD_ACCOUNT_AGE).c_str());
	value.department_id = atoi(d.at(FIELD_ACCOUNT_DEPARTMENT_ID).c_str());
	value.department_name = CString(d.at(FIELD_ACCOUNT_DEPARTMENT_NAME).c_str());
	value.headship = CString(d.at(FIELD_ACCOUNT_HEADSHIP).c_str());
	value.office_phone = CString(d.at(FIELD_ACCOUNT_OFFICE_PHONE).c_str());
	value.hand_set = CString(d.at(FIELD_ACCOUNT_HANDSET).c_str());
	value.email = CString(d.at(FIELD_ACCOUNT_EMAIL).c_str());
	value.address = CString(d.at(FIELD_ACCOUNT_ADDRESS).c_str());
	value.picture = CString(d.at(FIELD_ACCOUNT_PICTURE).c_str());

	account = value;
	return true;
}

bool AccountCtrl::GetAccountAllInfo(vector<AccountInfo>& account)
{
	vector<vector<string>> temp;
	if (!m_sql->SelectData(temp, "SELECT * FROM tb_account")) {
		return false;
	}
	for (auto d : temp) {
		AccountInfo value;
		value.account_id = atoi(d.at(FIELD_ACCOUNT_ID).c_str());
		value.name = CString(d.at(FIELD_ACCOUNT_NAME).c_str());
		value.password = CString(d.at(FIELD_ACCOUNT_PASSWORD).c_str());
		value.sex = CString(d.at(FIELD_ACCOUNT_SEX).c_str());
		value.age = atoi(d.at(FIELD_ACCOUNT_AGE).c_str());
		value.department_id = atoi(d.at(FIELD_ACCOUNT_DEPARTMENT_ID).c_str());
		value.department_name = CString(d.at(FIELD_ACCOUNT_DEPARTMENT_NAME).c_str());
		value.headship = CString(d.at(FIELD_ACCOUNT_HEADSHIP).c_str());
		value.office_phone = CString(d.at(FIELD_ACCOUNT_OFFICE_PHONE).c_str());
		value.hand_set = CString(d.at(FIELD_ACCOUNT_HANDSET).c_str());
		value.email = CString(d.at(FIELD_ACCOUNT_EMAIL).c_str());
		value.address = CString(d.at(FIELD_ACCOUNT_ADDRESS).c_str());
		value.picture = CString(d.at(FIELD_ACCOUNT_PICTURE).c_str());
		account.push_back(value);
	}
	return true;
}

bool AccountCtrl::GetAccountInfoInDepartment(vector<AccountInfo>& account, int department_id)
{
	vector<vector<string>> temp;
	if (!m_sql->SelectData(temp, "Select * from tb_account where department_id =" + to_string(department_id) + " and account_id not in (select manager_id from tb_department where manager_id=" + to_string(department_id) + ");")) {
		return false;
	}
	for (auto d : temp) {
		AccountInfo value;
		value.account_id = atoi(d.at(FIELD_ACCOUNT_ID).c_str());
		value.name = CString(d.at(FIELD_ACCOUNT_NAME).c_str());
		value.password = CString(d.at(FIELD_ACCOUNT_PASSWORD).c_str());
		value.sex = CString(d.at(FIELD_ACCOUNT_SEX).c_str());
		value.age = atoi(d.at(FIELD_ACCOUNT_AGE).c_str());
		value.department_id = atoi(d.at(FIELD_ACCOUNT_DEPARTMENT_ID).c_str());
		value.department_name = CString(d.at(FIELD_ACCOUNT_DEPARTMENT_NAME).c_str());
		value.headship = CString(d.at(FIELD_ACCOUNT_HEADSHIP).c_str());
		value.office_phone = CString(d.at(FIELD_ACCOUNT_OFFICE_PHONE).c_str());
		value.hand_set = CString(d.at(FIELD_ACCOUNT_HANDSET).c_str());
		value.email = CString(d.at(FIELD_ACCOUNT_EMAIL).c_str());
		value.address = CString(d.at(FIELD_ACCOUNT_ADDRESS).c_str());
		value.picture = CString(d.at(FIELD_ACCOUNT_PICTURE).c_str());
		account.push_back(value);
	}
	return true;
}

bool AccountCtrl::GetManagerAccountInfoInDepartment(AccountInfo& account, int department_id)
{
	vector<vector<string>> temp;
	if (!m_sql->SelectData(temp, "Select * from tb_account where account_id = (select manager_id from tb_department where department_id=" + to_string(department_id) + ");")) {
		return false;
	}
	vector<string> d = temp.at(0);
	AccountInfo value;
	value.account_id = atoi(d.at(FIELD_ACCOUNT_ID).c_str());
	value.name = CString(d.at(FIELD_ACCOUNT_NAME).c_str());
	value.password = CString(d.at(FIELD_ACCOUNT_PASSWORD).c_str());
	value.sex = CString(d.at(FIELD_ACCOUNT_SEX).c_str());
	value.age = atoi(d.at(FIELD_ACCOUNT_AGE).c_str());
	value.department_id = atoi(d.at(FIELD_ACCOUNT_DEPARTMENT_ID).c_str());
	value.department_name = CString(d.at(FIELD_ACCOUNT_DEPARTMENT_NAME).c_str());
	value.headship = CString(d.at(FIELD_ACCOUNT_HEADSHIP).c_str());
	value.office_phone = CString(d.at(FIELD_ACCOUNT_OFFICE_PHONE).c_str());
	value.hand_set = CString(d.at(FIELD_ACCOUNT_HANDSET).c_str());
	value.email = CString(d.at(FIELD_ACCOUNT_EMAIL).c_str());
	value.address = CString(d.at(FIELD_ACCOUNT_ADDRESS).c_str());
	value.picture = CString(d.at(FIELD_ACCOUNT_PICTURE).c_str());

	account = value;
	return true;
}

bool AccountCtrl::AddAccount(AccountInfo info)
{
	string sql =
		"INSERT INTO `db_myqq`.`tb_account` (`name`, `password`, `sex`, `age`, `department_id`, `department_name`, `headership`, `office_phone`, `hand_set`, `email`, `address`, `picture`) VALUES ('";
	sql += info.name + "',"
		+ "'" + info.password + "',"
		+ "'" + info.sex + "',"
		+ "'" + to_string(info.age).c_str() + "',"
		+ "'" + to_string(info.department_id).c_str() + "',"
		+ "'" + info.department_name + "',"
		+ "'" + info.headship + "',"
		+ "'" + info.office_phone + "',"
		+ "'" + info.hand_set + "',"
		+ "'" + info.email + "',"
		+ "'" + info.address + "',"
		+ "'" + info.picture + "'"
		+ ");";
	CString s = sql.c_str();
	s.Replace("\\\\","\\");
	s.Replace("\\", "/");
	sql = s.GetBuffer(0);
	s.ReleaseBuffer();
	if (!m_sql->OperateData(sql)) {
		return false;
	}
	return true;
}

bool AccountCtrl::SetDepartmentManager(int departmentId, int managerId)
{
	string sql = "UPDATE `db_myqq`.`tb_department` SET";
	sql+="`Manager_id` = '"+to_string(managerId) +"'"
		+"WHERE(`department_id` = '"+to_string(departmentId)+"'); ";
	if (!m_sql->OperateData(sql)) {
		return false;
	}
	return true;
}

bool AccountCtrl::GetNewAddItemId(int& id)
{
	string sql = "Select * from tb_account order by account_id DESC limit 1;";
	vector<vector<string>> temp;
	if (!m_sql->SelectData(temp,sql)) {
		return false;
	}
	id = atoi(temp.at(0).at(0).c_str());
	return true;
}

bool AccountCtrl::DeleteAddcount(int id)
{
	string sql = "DELETE FROM `db_myqq`.`tb_account` WHERE(`account_id` = '" + to_string(id) + "'); ";
	if (!m_sql->OperateData(sql)) {
		return false;
	}
	return true;
}

.h文件

#pragma once
#include "MysqlUtil.h"
#include "Common.h"

class AccountCtrl
{
public:
	AccountCtrl();
	~AccountCtrl();

public:
	bool GetAccountInfo(AccountInfo &account ,int id);
	bool GetAccountAllInfo(vector<AccountInfo>& account);

	bool GetAccountInfoInDepartment(vector<AccountInfo>& account, int department_id);

	bool GetManagerAccountInfoInDepartment(AccountInfo &account, int department_id);

	bool AddAccount(AccountInfo info);

	bool SetDepartmentManager(int departmentId,int managerId);

	bool GetNewAddItemId(int &id);

	bool DeleteAddcount(int id);

private:
	MysqlUtil* m_sql;

};


二、账户设置

2.1 初始化tree

分两步,1. 初始化部门信息
在这里插入图片描述
2. 初始化账户信息
在这里插入图片描述

2.2 添加账户

在这里插入图片描述

2.3 删除账户

在这里插入图片描述

2.4 切换账户

在这里插入图片描述

三、代码

// CDlgAccount.cpp: 实现文件
//

#include "pch.h"
#include "qqService.h"
#include "CDlgAccount.h"
#include "afxdialogex.h"


// CDlgAccount 对话框

IMPLEMENT_DYNAMIC(CDlgAccount, CDialogEx)

CDlgAccount::CDlgAccount(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DLG_ACCOUNT, pParent)
{

}

CDlgAccount::~CDlgAccount()
{
}

void CDlgAccount::InitDepartmentInfo()
{
	vector<DepartmentInfo> info;
	m_departmentCtrl.GetDepartmentAllInfo(info);
	m_dpInfo = info;

	m_dpList.DeleteAllItems();
	HTREEITEM hParent;
	m_hRoot = m_dpList.InsertItem(info.at(0).name, 0, 0);
	info.erase(info.begin());
	for (auto d : info)
	{
		if (d.parentId == 0) {
			hParent = m_dpList.InsertItem(d.name, 0, 0, m_hRoot);
			FindSubNode(hParent, d.id, info);
		}
	}
	m_dpList.Expand(m_hRoot, TVE_EXPAND);
}

void CDlgAccount::FindSubNode(HTREEITEM node, int id, vector<DepartmentInfo> info)
{
	HTREEITEM  hParent;
	for (auto d : info) {
		if (d.parentId == id) {
			hParent = m_dpList.InsertItem(d.name, 0, 0, node);
			FindSubNode(hParent, d.id, info);
		}
	}
}

void CDlgAccount::InitAccountInfo()
{
	vector<AccountInfo> info;
	m_accountAtrl.GetAccountAllInfo(info);
	m_AcInfo = info;
	FindSubAccountNode(m_hRoot);
}

void CDlgAccount::FindSubAccountNode(HTREEITEM node)
{
	HTREEITEM hInsert = m_dpList.GetChildItem(node);
	//m_dpInfo.erase(m_dpInfo.begin());
	while (hInsert) {
		// 1. 获取部门ID
		int tempDpId=0;
		CString text = m_dpList.GetItemText(hInsert);
 		for (auto t : m_dpInfo) {
			if (t.name == m_dpList.GetItemText(hInsert)) {
				tempDpId = t.id;
				break;
			}
		}
		// 2. 若部门没有子节点
		if (!m_dpList.ItemHasChildren(hInsert)) {
			// 2.1 获取该部门所有员工信息
			vector<AccountInfo> info;
			if (!m_accountAtrl.GetAccountInfoInDepartment(info, tempDpId)) {
				hInsert = m_dpList.GetNextItem(hInsert, TVGN_NEXT);
				continue;
			}
			// 2.2 添加员工信息
			for (auto v : info) {
				if (v.sex == "male") {
					m_dpList.InsertItem(v.name, 1, 1, hInsert);
				}
				else {
					m_dpList.InsertItem(v.name, 2, 2, hInsert);
				}
			}
		}
		// 3. 若部门有子节点
		else {
			// 3.1 查找此部门主管
			AccountInfo info;
			if (m_accountAtrl.GetManagerAccountInfoInDepartment(info, tempDpId)) {
				// 3.2添加主管信息
				if (hInsert != NULL) {
					if (info.sex == "male") {
						m_dpList.InsertItem(info.name, 1, 1, hInsert);
					}
					else {
						m_dpList.InsertItem(info.name, 2, 2, hInsert);
					}
				}
			}
			// 3.3 递归查找其子节点情况
			FindSubAccountNode(hInsert);
		}
		hInsert = m_dpList.GetNextItem(hInsert, TVGN_NEXT);
	}
}

void CDlgAccount::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE1, m_dpList);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_ID, m_selAccount.account_id);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_NAME, m_selAccount.name);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_SEX, m_selAccount.sex);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_DPID, m_selAccount.department_id);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_DEPARTMENT, m_selAccount.department_name);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_HEADSHIP, m_selAccount.headship);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_OFFICE_PHONE, m_selAccount.office_phone);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_TEL, m_selAccount.hand_set);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_EMAIL, m_selAccount.email);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_ADDRESS, m_selAccount.address);


	//DDX_Text(pDX, IDC_EDIT_ACCOUNT_ID, m_selAccount.account_id); 
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_NAME_SET, m_addAccount.name);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_AGE_SET, m_addAccount.age);
	DDX_Text(pDX, IDC_COMBO_ACCOUNT_SEX_SET, m_addAccount.sex);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_PWD_SET, m_addAccount.password);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_DEPARTMENT_ID_SET, m_addAccount.department_id);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_DEPARTMENT_SET, m_addAccount.department_name);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_HEADSHIP_SET, m_addAccount.headship);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_OFFICE_TEL_SET, m_addAccount.office_phone);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_TEL_SET, m_addAccount.hand_set);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_EMAIL_SET, m_addAccount.email);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_ADDRESS_SET, m_addAccount.address);
	DDX_Text(pDX, IDC_EDIT_ACCOUNT_PICTURE_SET, m_addAccount.picture);

	DDX_Control(pDX, IDC_STATIC_PICTURE, m_picture);
	DDX_Control(pDX, IDC_CHECK_MANAGER, m_check);
}


BEGIN_MESSAGE_MAP(CDlgAccount, CDialogEx)
	ON_BN_CLICKED(IDC_BTN_ACCOUNT_ADD, &CDlgAccount::OnBnClickedBtnAccountAdd)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CDlgAccount::OnTvnSelchangedTree1)
	ON_BN_CLICKED(IDC_BTN_BROWSER, &CDlgAccount::OnBnClickedBtnBrowser)
	ON_BN_CLICKED(IDC_BTN_ACCOUNT_DEL, &CDlgAccount::OnBnClickedBtnAccountDel)
END_MESSAGE_MAP()


// CDlgAccount 消息处理程序


void CDlgAccount::OnBnClickedBtnAccountAdd()
{
	// TODO: 在此添加控件通知处理程序代码
	CString pwd1, pwd2;
	GetDlgItemText(IDC_EDIT_PWD_REPEAT_SET, pwd2);
	GetDlgItemText(IDC_EDIT_ACCOUNT_PWD_SET, pwd1);
	if (pwd1.IsEmpty() || pwd2.IsEmpty()) {
		AfxMessageBox("密码输入为空!");
		return;
	}
	if (pwd1.Compare(pwd2)) {
		AfxMessageBox("两次输入密码不一致!");
		return;
	}
	m_addAccount.clear();
	UpdateData(TRUE);
	bool res = m_addAccount.address.IsEmpty();
	if (m_addAccount.isEmpty()) {
		AfxMessageBox("参数不能为空!");
		return;
	}
	if (!m_accountAtrl.AddAccount(m_addAccount)) {
		AfxMessageBox("添加失败!");
		return;
	}

	if (m_check.GetCheck()) {
		int id;
		if (!m_accountAtrl.GetNewAddItemId(id)) {
			AfxMessageBox("获取最新添加数据失败!");
			return;
		}
		if (!m_accountAtrl.SetDepartmentManager(m_selDepartment.id, id)) {
			AfxMessageBox("设置"+m_selDepartment.name+"部门主管失败!");
			return;
		}	
	}
	InitDepartmentInfo();
	InitAccountInfo();
	
}


BOOL CDlgAccount::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	 // 图片列表设置:用于给树控件增加图片
	m_ImageList.Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);
	CBitmap bmp;
	// 部门图片
	bmp.LoadBitmap(IDB_DEPARTMENT);
	m_ImageList.Add(&bmp, RGB(255, 255, 255));
	bmp.Detach();
	// 人员图片:男
	bmp.LoadBitmap(IDB_MAN);
	m_ImageList.Add(&bmp, RGB(255, 255, 255));
	bmp.Detach();
	// 人员图片:女
	bmp.LoadBitmap(IDB_FEMALE);
	m_ImageList.Add(&bmp, RGB(255, 255, 255));
	m_dpList.SetImageList(&m_ImageList, TVSIL_NORMAL);

	InitDepartmentInfo();
	InitAccountInfo();
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}


void CDlgAccount::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	HTREEITEM curItem =  m_dpList.GetSelectedItem();
	CString s = m_dpList.GetItemText(curItem);
	for (auto ac : m_AcInfo) {
		if (ac.name == s) {
			m_selAccount = ac;
			UpdateData(FALSE);
			CImage image;
			image.Load(m_selAccount.picture);
			if (image.IsNull()) {
				AfxMessageBox("加载图片失败!");
				return;
			}
			CRect rc;
			GetDlgItem(IDC_STATIC_ACCOUNT_PICTURE)->GetClientRect(rc);
			image.Draw(GetDlgItem(IDC_STATIC_ACCOUNT_PICTURE)->GetDC()->m_hDC, rc);
			break;
		}
	}
	m_departmentCtrl.GetDepartmentAllInfo(m_dpInfo);
	for (auto dp : m_dpInfo) {
		if (dp.name == s) {
			m_selDepartment = dp;
			GetDlgItem(IDC_EDIT_ACCOUNT_DEPARTMENT_SET)->SetWindowText(m_selDepartment.name);
			GetDlgItem(IDC_EDIT_ACCOUNT_DEPARTMENT_ID_SET)->SetWindowText(to_string(m_selDepartment.id).c_str());
		}
	
	}
	*pResult = 0;
}


void CDlgAccount::OnBnClickedBtnBrowser()
{
	// TODO: 在此添加控件通知处理程序代码
	CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, "图片文件(*.jpg)|*.jpg||", this);    //这里修改浏览文件类型
	if (fileDlg.DoModal() != IDOK) {
		return;
	}
	CString path = fileDlg.GetPathName();
	SetDlgItemText(IDC_EDIT_ACCOUNT_PICTURE_SET, path);
	CImage image;
	image.Load(path);
	if (image.IsNull()) {
		AfxMessageBox("加载图片失败!");
		return;
	}
	CRect rc;
	m_picture.GetClientRect(rc);
	image.Draw(m_picture.GetDC()->m_hDC,rc);
}


void CDlgAccount::OnBnClickedBtnAccountDel()
{
	// TODO: 在此添加控件通知处理程序代码
	if (MessageBox("确实要删除当前账户信息吗?", "提示", MB_YESNO) != IDYES) {
		return;
	}
	if (!m_accountAtrl.DeleteAddcount(m_selAccount.account_id)) {
		AfxMessageBox("删除失败!");
		return;
	}
	InitDepartmentInfo();
	InitAccountInfo();
	m_selAccount.clear();
	UpdateData(FALSE);
}

.h文件

#pragma once
#include "AccountCtrl.h"
#include "DepartmentCtrl.h"


// CDlgAccount 对话框

class CDlgAccount : public CDialogEx
{
	DECLARE_DYNAMIC(CDlgAccount)

public:
	CDlgAccount(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~CDlgAccount();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DLG_ACCOUNT };
#endif

private:
	CImageList m_ImageList;
	CTreeCtrl m_dpList;
	HTREEITEM m_hRoot;
	HTREEITEM m_hParent;
	vector<DepartmentInfo> m_dpInfo;
	vector<AccountInfo> m_AcInfo;
	AccountCtrl m_accountAtrl;
	DepartmentCtrl m_departmentCtrl;
	void InitDepartmentInfo();
	void FindSubNode(HTREEITEM node, int id, vector<DepartmentInfo> info);
	void InitAccountInfo();
	void FindSubAccountNode(HTREEITEM node);
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedBtnAccountAdd();
	virtual BOOL OnInitDialog();
	;
	afx_msg void OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult);
	AccountInfo m_selAccount;
	AccountInfo m_addAccount;
	DepartmentInfo m_selDepartment;
	
	afx_msg void OnBnClickedBtnBrowser();
	CStatic m_picture;
	afx_msg void OnBnClickedBtnAccountDel();
	CButton m_check;
};

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值